mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-20 00:26:39 +08:00
udf: Make udf exportable
Cc: Christoph Hellwig <hch@infradead.org> Signed-off-by: Rasmus Rohde <rohde@duff.dk> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
22ba0317c8
commit
221e583a73
140
fs/udf/namei.c
140
fs/udf/namei.c
@ -32,6 +32,7 @@
|
|||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/crc-itu-t.h>
|
#include <linux/crc-itu-t.h>
|
||||||
|
#include <linux/exportfs.h>
|
||||||
|
|
||||||
static inline int udf_match(int len1, const char *name1, int len2,
|
static inline int udf_match(int len1, const char *name1, int len2,
|
||||||
const char *name2)
|
const char *name2)
|
||||||
@ -158,6 +159,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||||||
sector_t offset;
|
sector_t offset;
|
||||||
struct extent_position epos = {};
|
struct extent_position epos = {};
|
||||||
struct udf_inode_info *dinfo = UDF_I(dir);
|
struct udf_inode_info *dinfo = UDF_I(dir);
|
||||||
|
int isdotdot = dentry->d_name.len == 2 &&
|
||||||
|
dentry->d_name.name[0] == '.' && dentry->d_name.name[1] == '.';
|
||||||
|
|
||||||
size = udf_ext0_offset(dir) + dir->i_size;
|
size = udf_ext0_offset(dir) + dir->i_size;
|
||||||
f_pos = udf_ext0_offset(dir);
|
f_pos = udf_ext0_offset(dir);
|
||||||
@ -225,6 +228,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
|
||||||
|
isdotdot) {
|
||||||
|
brelse(epos.bh);
|
||||||
|
return fi;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lfi)
|
if (!lfi)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -286,9 +295,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock_kernel();
|
unlock_kernel();
|
||||||
d_add(dentry, inode);
|
|
||||||
|
|
||||||
return NULL;
|
return d_splice_alias(inode, dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
static struct fileIdentDesc *udf_add_entry(struct inode *dir,
|
||||||
@ -1232,6 +1240,134 @@ end_rename:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct dentry *udf_get_parent(struct dentry *child)
|
||||||
|
{
|
||||||
|
struct dentry *parent;
|
||||||
|
struct inode *inode = NULL;
|
||||||
|
struct dentry dotdot;
|
||||||
|
struct fileIdentDesc cfi;
|
||||||
|
struct udf_fileident_bh fibh;
|
||||||
|
|
||||||
|
dotdot.d_name.name = "..";
|
||||||
|
dotdot.d_name.len = 2;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
if (fibh.sbh != fibh.ebh)
|
||||||
|
brelse(fibh.ebh);
|
||||||
|
brelse(fibh.sbh);
|
||||||
|
|
||||||
|
inode = udf_iget(child->d_inode->i_sb,
|
||||||
|
lelb_to_cpu(cfi.icb.extLocation));
|
||||||
|
if (!inode)
|
||||||
|
goto out_unlock;
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
|
parent = d_alloc_anon(inode);
|
||||||
|
if (!parent) {
|
||||||
|
iput(inode);
|
||||||
|
parent = ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
out_unlock:
|
||||||
|
unlock_kernel();
|
||||||
|
return ERR_PTR(-EACCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
|
||||||
|
u16 partref, __u32 generation)
|
||||||
|
{
|
||||||
|
struct inode *inode;
|
||||||
|
struct dentry *result;
|
||||||
|
kernel_lb_addr loc;
|
||||||
|
|
||||||
|
if (block == 0)
|
||||||
|
return ERR_PTR(-ESTALE);
|
||||||
|
|
||||||
|
loc.logicalBlockNum = block;
|
||||||
|
loc.partitionReferenceNum = partref;
|
||||||
|
inode = udf_iget(sb, loc);
|
||||||
|
|
||||||
|
if (inode == NULL)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
if (generation && inode->i_generation != generation) {
|
||||||
|
iput(inode);
|
||||||
|
return ERR_PTR(-ESTALE);
|
||||||
|
}
|
||||||
|
result = d_alloc_anon(inode);
|
||||||
|
if (!result) {
|
||||||
|
iput(inode);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dentry *udf_fh_to_dentry(struct super_block *sb,
|
||||||
|
struct fid *fid, int fh_len, int fh_type)
|
||||||
|
{
|
||||||
|
if ((fh_len != 3 && fh_len != 5) ||
|
||||||
|
(fh_type != FILEID_UDF_WITH_PARENT &&
|
||||||
|
fh_type != FILEID_UDF_WITHOUT_PARENT))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
|
||||||
|
fid->udf.generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dentry *udf_fh_to_parent(struct super_block *sb,
|
||||||
|
struct fid *fid, int fh_len, int fh_type)
|
||||||
|
{
|
||||||
|
if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return udf_nfs_get_inode(sb, fid->udf.parent_block,
|
||||||
|
fid->udf.parent_partref,
|
||||||
|
fid->udf.parent_generation);
|
||||||
|
}
|
||||||
|
static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
|
||||||
|
int connectable)
|
||||||
|
{
|
||||||
|
int len = *lenp;
|
||||||
|
struct inode *inode = de->d_inode;
|
||||||
|
kernel_lb_addr location = UDF_I(inode)->i_location;
|
||||||
|
struct fid *fid = (struct fid *)fh;
|
||||||
|
int type = FILEID_UDF_WITHOUT_PARENT;
|
||||||
|
|
||||||
|
if (len < 3 || (connectable && len < 5))
|
||||||
|
return 255;
|
||||||
|
|
||||||
|
*lenp = 3;
|
||||||
|
fid->udf.block = location.logicalBlockNum;
|
||||||
|
fid->udf.partref = location.partitionReferenceNum;
|
||||||
|
fid->udf.generation = inode->i_generation;
|
||||||
|
|
||||||
|
if (connectable && !S_ISDIR(inode->i_mode)) {
|
||||||
|
spin_lock(&de->d_lock);
|
||||||
|
inode = de->d_parent->d_inode;
|
||||||
|
location = UDF_I(inode)->i_location;
|
||||||
|
fid->udf.parent_block = location.logicalBlockNum;
|
||||||
|
fid->udf.parent_partref = location.partitionReferenceNum;
|
||||||
|
fid->udf.parent_generation = inode->i_generation;
|
||||||
|
spin_unlock(&de->d_lock);
|
||||||
|
*lenp = 5;
|
||||||
|
type = FILEID_UDF_WITH_PARENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct export_operations udf_export_ops = {
|
||||||
|
.encode_fh = udf_encode_fh,
|
||||||
|
.fh_to_dentry = udf_fh_to_dentry,
|
||||||
|
.fh_to_parent = udf_fh_to_parent,
|
||||||
|
.get_parent = udf_get_parent,
|
||||||
|
};
|
||||||
|
|
||||||
const struct inode_operations udf_dir_inode_operations = {
|
const struct inode_operations udf_dir_inode_operations = {
|
||||||
.lookup = udf_lookup,
|
.lookup = udf_lookup,
|
||||||
.create = udf_create,
|
.create = udf_create,
|
||||||
|
@ -1933,6 +1933,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
|
|||||||
|
|
||||||
/* Fill in the rest of the superblock */
|
/* Fill in the rest of the superblock */
|
||||||
sb->s_op = &udf_sb_ops;
|
sb->s_op = &udf_sb_ops;
|
||||||
|
sb->s_export_op = &udf_export_ops;
|
||||||
sb->dq_op = NULL;
|
sb->dq_op = NULL;
|
||||||
sb->s_dirt = 0;
|
sb->s_dirt = 0;
|
||||||
sb->s_magic = UDF_SUPER_MAGIC;
|
sb->s_magic = UDF_SUPER_MAGIC;
|
||||||
|
@ -73,6 +73,7 @@ struct task_struct;
|
|||||||
struct buffer_head;
|
struct buffer_head;
|
||||||
struct super_block;
|
struct super_block;
|
||||||
|
|
||||||
|
extern const struct export_operations udf_export_ops;
|
||||||
extern const struct inode_operations udf_dir_inode_operations;
|
extern const struct inode_operations udf_dir_inode_operations;
|
||||||
extern const struct file_operations udf_dir_operations;
|
extern const struct file_operations udf_dir_operations;
|
||||||
extern const struct inode_operations udf_file_inode_operations;
|
extern const struct inode_operations udf_file_inode_operations;
|
||||||
|
@ -33,6 +33,19 @@ enum fid_type {
|
|||||||
* 32 bit parent directory inode number.
|
* 32 bit parent directory inode number.
|
||||||
*/
|
*/
|
||||||
FILEID_INO32_GEN_PARENT = 2,
|
FILEID_INO32_GEN_PARENT = 2,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 32 bit block number, 16 bit partition reference,
|
||||||
|
* 16 bit unused, 32 bit generation number.
|
||||||
|
*/
|
||||||
|
FILEID_UDF_WITHOUT_PARENT = 0x51,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 32 bit block number, 16 bit partition reference,
|
||||||
|
* 16 bit unused, 32 bit generation number,
|
||||||
|
* 32 bit parent block number, 32 bit parent generation number
|
||||||
|
*/
|
||||||
|
FILEID_UDF_WITH_PARENT = 0x52,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fid {
|
struct fid {
|
||||||
@ -43,6 +56,14 @@ struct fid {
|
|||||||
u32 parent_ino;
|
u32 parent_ino;
|
||||||
u32 parent_gen;
|
u32 parent_gen;
|
||||||
} i32;
|
} i32;
|
||||||
|
struct {
|
||||||
|
u32 block;
|
||||||
|
u16 partref;
|
||||||
|
u16 parent_partref;
|
||||||
|
u32 generation;
|
||||||
|
u32 parent_block;
|
||||||
|
u32 parent_generation;
|
||||||
|
} udf;
|
||||||
__u32 raw[0];
|
__u32 raw[0];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user