mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
kernfs: implement custom exportfs ops and fid type
The current kernfs exportfs implementation uses the generic_fh_*() helpers and FILEID_INO32_GEN[_PARENT] which limits ino to 32bits. Let's implement custom exportfs operations and fid type to remove the restriction. * FILEID_KERNFS is a single u64 value whose content is kernfs_node->id. This is the only native fid type. * For backward compatibility with blk_log_action() path which exposes (ino,gen) pairs which userland assembles into FILEID_INO32_GEN keys, combine the generic keys into 64bit IDs in the same order. Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Namhyung Kim <namhyung@kernel.org>
This commit is contained in:
parent
fe0f726c9f
commit
33c5ac9175
@ -53,40 +53,84 @@ const struct super_operations kernfs_sops = {
|
||||
.show_path = kernfs_sop_show_path,
|
||||
};
|
||||
|
||||
static struct inode *kernfs_fh_get_inode(struct super_block *sb,
|
||||
u64 ino, u32 generation)
|
||||
static int kernfs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
|
||||
struct inode *parent)
|
||||
{
|
||||
struct kernfs_node *kn = inode->i_private;
|
||||
|
||||
if (*max_len < 2) {
|
||||
*max_len = 2;
|
||||
return FILEID_INVALID;
|
||||
}
|
||||
|
||||
*max_len = 2;
|
||||
*(u64 *)fh = kn->id;
|
||||
return FILEID_KERNFS;
|
||||
}
|
||||
|
||||
static struct dentry *__kernfs_fh_to_dentry(struct super_block *sb,
|
||||
struct fid *fid, int fh_len,
|
||||
int fh_type, bool get_parent)
|
||||
{
|
||||
struct kernfs_super_info *info = kernfs_info(sb);
|
||||
struct inode *inode;
|
||||
struct kernfs_node *kn;
|
||||
struct inode *inode;
|
||||
u64 id;
|
||||
|
||||
if (ino == 0)
|
||||
return ERR_PTR(-ESTALE);
|
||||
if (fh_len < 2)
|
||||
return NULL;
|
||||
|
||||
kn = kernfs_find_and_get_node_by_id(info->root,
|
||||
ino | ((u64)generation << 32));
|
||||
switch (fh_type) {
|
||||
case FILEID_KERNFS:
|
||||
id = *(u64 *)fid;
|
||||
break;
|
||||
case FILEID_INO32_GEN:
|
||||
case FILEID_INO32_GEN_PARENT:
|
||||
/*
|
||||
* blk_log_action() exposes (ino,gen) pair without type and
|
||||
* userland can call us with generic fid constructed from
|
||||
* them. Combine it back to ID. See blk_log_action().
|
||||
*/
|
||||
id = ((u64)fid->i32.gen << 32) | fid->i32.ino;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kn = kernfs_find_and_get_node_by_id(info->root, id);
|
||||
if (!kn)
|
||||
return ERR_PTR(-ESTALE);
|
||||
|
||||
if (get_parent) {
|
||||
struct kernfs_node *parent;
|
||||
|
||||
parent = kernfs_get_parent(kn);
|
||||
kernfs_put(kn);
|
||||
kn = parent;
|
||||
if (!kn)
|
||||
return ERR_PTR(-ESTALE);
|
||||
}
|
||||
|
||||
inode = kernfs_get_inode(sb, kn);
|
||||
kernfs_put(kn);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ESTALE);
|
||||
|
||||
return inode;
|
||||
return d_obtain_alias(inode);
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type)
|
||||
static struct dentry *kernfs_fh_to_dentry(struct super_block *sb,
|
||||
struct fid *fid, int fh_len,
|
||||
int fh_type)
|
||||
{
|
||||
return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
|
||||
kernfs_fh_get_inode);
|
||||
return __kernfs_fh_to_dentry(sb, fid, fh_len, fh_type, false);
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_fh_to_parent(struct super_block *sb, struct fid *fid,
|
||||
int fh_len, int fh_type)
|
||||
static struct dentry *kernfs_fh_to_parent(struct super_block *sb,
|
||||
struct fid *fid, int fh_len,
|
||||
int fh_type)
|
||||
{
|
||||
return generic_fh_to_parent(sb, fid, fh_len, fh_type,
|
||||
kernfs_fh_get_inode);
|
||||
return __kernfs_fh_to_dentry(sb, fid, fh_len, fh_type, true);
|
||||
}
|
||||
|
||||
static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
|
||||
@ -97,6 +141,7 @@ static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
|
||||
}
|
||||
|
||||
static const struct export_operations kernfs_export_ops = {
|
||||
.encode_fh = kernfs_encode_fh,
|
||||
.fh_to_dentry = kernfs_fh_to_dentry,
|
||||
.fh_to_parent = kernfs_fh_to_parent,
|
||||
.get_parent = kernfs_get_parent_dentry,
|
||||
|
@ -104,6 +104,11 @@ enum fid_type {
|
||||
*/
|
||||
FILEID_LUSTRE = 0x97,
|
||||
|
||||
/*
|
||||
* 64 bit unique kernfs id
|
||||
*/
|
||||
FILEID_KERNFS = 0xfe,
|
||||
|
||||
/*
|
||||
* Filesystems must not use 0xff file ID.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user