exportfs: make ->encode_fh() a mandatory method for NFS export
Rename the default helper for encoding FILEID_INO32_GEN* file handles to generic_encode_ino32_fh() and convert the filesystems that used the default implementation to use the generic helper explicitly. After this change, exportfs_encode_inode_fh() no longer has a default implementation to encode FILEID_INO32_GEN* file handles. This is a step towards allowing filesystems to encode non-decodeable file handles for fanotify without having to implement any export_operations. Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Jeff Layton <jlayton@kernel.org> Acked-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://lore.kernel.org/r/20231023180801.2953446-3-amir73il@gmail.com Acked-by: Dave Kleikamp <dave.kleikamp@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
66c62769bc
commit
e21fc2038c
@ -122,12 +122,9 @@ are exportable by setting the s_export_op field in the struct
|
|||||||
super_block. This field must point to a "struct export_operations"
|
super_block. This field must point to a "struct export_operations"
|
||||||
struct which has the following members:
|
struct which has the following members:
|
||||||
|
|
||||||
encode_fh (optional)
|
encode_fh (mandatory)
|
||||||
Takes a dentry and creates a filehandle fragment which may later be used
|
Takes a dentry and creates a filehandle fragment which may later be used
|
||||||
to find or create a dentry for the same object. The default
|
to find or create a dentry for the same object.
|
||||||
implementation creates a filehandle fragment that encodes a 32bit inode
|
|
||||||
and generation number for the inode encoded, and if necessary the
|
|
||||||
same information for the parent.
|
|
||||||
|
|
||||||
fh_to_dentry (mandatory)
|
fh_to_dentry (mandatory)
|
||||||
Given a filehandle fragment, this should find the implied object and
|
Given a filehandle fragment, this should find the implied object and
|
||||||
|
@ -1045,3 +1045,12 @@ filesystem type is now moved to a later point when the devices are closed:
|
|||||||
As this is a VFS level change it has no practical consequences for filesystems
|
As this is a VFS level change it has no practical consequences for filesystems
|
||||||
other than that all of them must use one of the provided kill_litter_super(),
|
other than that all of them must use one of the provided kill_litter_super(),
|
||||||
kill_anon_super(), or kill_block_super() helpers.
|
kill_anon_super(), or kill_block_super() helpers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**mandatory**
|
||||||
|
|
||||||
|
export_operations ->encode_fh() no longer has a default implementation to
|
||||||
|
encode FILEID_INO32_GEN* file handles.
|
||||||
|
Filesystems that used the default implementation may use the generic helper
|
||||||
|
generic_encode_ino32_fh() explicitly.
|
||||||
|
@ -568,6 +568,7 @@ static struct dentry *affs_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct export_operations affs_export_ops = {
|
const struct export_operations affs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = affs_fh_to_dentry,
|
.fh_to_dentry = affs_fh_to_dentry,
|
||||||
.fh_to_parent = affs_fh_to_parent,
|
.fh_to_parent = affs_fh_to_parent,
|
||||||
.get_parent = affs_get_parent,
|
.get_parent = affs_get_parent,
|
||||||
|
@ -96,6 +96,7 @@ static const struct address_space_operations befs_symlink_aops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct export_operations befs_export_operations = {
|
static const struct export_operations befs_export_operations = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = befs_fh_to_dentry,
|
.fh_to_dentry = befs_fh_to_dentry,
|
||||||
.fh_to_parent = befs_fh_to_parent,
|
.fh_to_parent = befs_fh_to_parent,
|
||||||
.get_parent = befs_get_parent,
|
.get_parent = befs_get_parent,
|
||||||
|
@ -123,6 +123,7 @@ static const struct super_operations efs_superblock_operations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct export_operations efs_export_ops = {
|
static const struct export_operations efs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = efs_fh_to_dentry,
|
.fh_to_dentry = efs_fh_to_dentry,
|
||||||
.fh_to_parent = efs_fh_to_parent,
|
.fh_to_parent = efs_fh_to_parent,
|
||||||
.get_parent = efs_get_parent,
|
.get_parent = efs_get_parent,
|
||||||
|
@ -626,6 +626,7 @@ static struct dentry *erofs_get_parent(struct dentry *child)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations erofs_export_ops = {
|
static const struct export_operations erofs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = erofs_fh_to_dentry,
|
.fh_to_dentry = erofs_fh_to_dentry,
|
||||||
.fh_to_parent = erofs_fh_to_parent,
|
.fh_to_parent = erofs_fh_to_parent,
|
||||||
.get_parent = erofs_get_parent,
|
.get_parent = erofs_get_parent,
|
||||||
|
@ -343,20 +343,21 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* export_encode_fh - default export_operations->encode_fh function
|
* generic_encode_ino32_fh - generic export_operations->encode_fh function
|
||||||
* @inode: the object to encode
|
* @inode: the object to encode
|
||||||
* @fid: where to store the file handle fragment
|
* @fh: where to store the file handle fragment
|
||||||
* @max_len: maximum length to store there
|
* @max_len: maximum length to store there (in 4 byte units)
|
||||||
* @parent: parent directory inode, if wanted
|
* @parent: parent directory inode, if wanted
|
||||||
*
|
*
|
||||||
* This default encode_fh function assumes that the 32 inode number
|
* This generic encode_fh function assumes that the 32 inode number
|
||||||
* is suitable for locating an inode, and that the generation number
|
* is suitable for locating an inode, and that the generation number
|
||||||
* can be used to check that it is still valid. It places them in the
|
* can be used to check that it is still valid. It places them in the
|
||||||
* filehandle fragment where export_decode_fh expects to find them.
|
* filehandle fragment where export_decode_fh expects to find them.
|
||||||
*/
|
*/
|
||||||
static int export_encode_fh(struct inode *inode, struct fid *fid,
|
int generic_encode_ino32_fh(struct inode *inode, __u32 *fh, int *max_len,
|
||||||
int *max_len, struct inode *parent)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
|
struct fid *fid = (void *)fh;
|
||||||
int len = *max_len;
|
int len = *max_len;
|
||||||
int type = FILEID_INO32_GEN;
|
int type = FILEID_INO32_GEN;
|
||||||
|
|
||||||
@ -380,6 +381,7 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
|
|||||||
*max_len = len;
|
*max_len = len;
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(generic_encode_ino32_fh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* exportfs_encode_inode_fh - encode a file handle from inode
|
* exportfs_encode_inode_fh - encode a file handle from inode
|
||||||
@ -402,7 +404,7 @@ int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid,
|
|||||||
if (nop && nop->encode_fh)
|
if (nop && nop->encode_fh)
|
||||||
return nop->encode_fh(inode, fid->raw, max_len, parent);
|
return nop->encode_fh(inode, fid->raw, max_len, parent);
|
||||||
|
|
||||||
return export_encode_fh(inode, fid, max_len, parent);
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
|
EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh);
|
||||||
|
|
||||||
|
@ -397,6 +397,7 @@ static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations ext2_export_ops = {
|
static const struct export_operations ext2_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = ext2_fh_to_dentry,
|
.fh_to_dentry = ext2_fh_to_dentry,
|
||||||
.fh_to_parent = ext2_fh_to_parent,
|
.fh_to_parent = ext2_fh_to_parent,
|
||||||
.get_parent = ext2_get_parent,
|
.get_parent = ext2_get_parent,
|
||||||
|
@ -1646,6 +1646,7 @@ static const struct super_operations ext4_sops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct export_operations ext4_export_ops = {
|
static const struct export_operations ext4_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = ext4_fh_to_dentry,
|
.fh_to_dentry = ext4_fh_to_dentry,
|
||||||
.fh_to_parent = ext4_fh_to_parent,
|
.fh_to_parent = ext4_fh_to_parent,
|
||||||
.get_parent = ext4_get_parent,
|
.get_parent = ext4_get_parent,
|
||||||
|
@ -3282,6 +3282,7 @@ static struct dentry *f2fs_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations f2fs_export_ops = {
|
static const struct export_operations f2fs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = f2fs_fh_to_dentry,
|
.fh_to_dentry = f2fs_fh_to_dentry,
|
||||||
.fh_to_parent = f2fs_fh_to_parent,
|
.fh_to_parent = f2fs_fh_to_parent,
|
||||||
.get_parent = f2fs_get_parent,
|
.get_parent = f2fs_get_parent,
|
||||||
|
@ -279,6 +279,7 @@ static struct dentry *fat_get_parent(struct dentry *child_dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct export_operations fat_export_ops = {
|
const struct export_operations fat_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = fat_fh_to_dentry,
|
.fh_to_dentry = fat_fh_to_dentry,
|
||||||
.fh_to_parent = fat_fh_to_parent,
|
.fh_to_parent = fat_fh_to_parent,
|
||||||
.get_parent = fat_get_parent,
|
.get_parent = fat_get_parent,
|
||||||
|
@ -150,6 +150,7 @@ static struct dentry *jffs2_get_parent(struct dentry *child)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations jffs2_export_ops = {
|
static const struct export_operations jffs2_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.get_parent = jffs2_get_parent,
|
.get_parent = jffs2_get_parent,
|
||||||
.fh_to_dentry = jffs2_fh_to_dentry,
|
.fh_to_dentry = jffs2_fh_to_dentry,
|
||||||
.fh_to_parent = jffs2_fh_to_parent,
|
.fh_to_parent = jffs2_fh_to_parent,
|
||||||
|
@ -896,6 +896,7 @@ static const struct super_operations jfs_super_operations = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct export_operations jfs_export_operations = {
|
static const struct export_operations jfs_export_operations = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = jfs_fh_to_dentry,
|
.fh_to_dentry = jfs_fh_to_dentry,
|
||||||
.fh_to_parent = jfs_fh_to_parent,
|
.fh_to_parent = jfs_fh_to_parent,
|
||||||
.get_parent = jfs_get_parent,
|
.get_parent = jfs_get_parent,
|
||||||
|
@ -384,6 +384,7 @@ static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
|
|||||||
* and due to using iget() whereas NTFS needs ntfs_iget().
|
* and due to using iget() whereas NTFS needs ntfs_iget().
|
||||||
*/
|
*/
|
||||||
const struct export_operations ntfs_export_ops = {
|
const struct export_operations ntfs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.get_parent = ntfs_get_parent, /* Find the parent of a given
|
.get_parent = ntfs_get_parent, /* Find the parent of a given
|
||||||
directory. */
|
directory. */
|
||||||
.fh_to_dentry = ntfs_fh_to_dentry,
|
.fh_to_dentry = ntfs_fh_to_dentry,
|
||||||
|
@ -811,6 +811,7 @@ static int ntfs_nfs_commit_metadata(struct inode *inode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations ntfs_export_ops = {
|
static const struct export_operations ntfs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = ntfs_fh_to_dentry,
|
.fh_to_dentry = ntfs_fh_to_dentry,
|
||||||
.fh_to_parent = ntfs_fh_to_parent,
|
.fh_to_parent = ntfs_fh_to_parent,
|
||||||
.get_parent = ntfs3_get_parent,
|
.get_parent = ntfs3_get_parent,
|
||||||
|
@ -41,13 +41,12 @@ static struct dentry *cifs_get_parent(struct dentry *dentry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct export_operations cifs_export_ops = {
|
const struct export_operations cifs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.get_parent = cifs_get_parent,
|
.get_parent = cifs_get_parent,
|
||||||
/* Following five export operations are unneeded so far and can default:
|
/*
|
||||||
.get_dentry =
|
* Following export operations are mandatory for NFS export support:
|
||||||
.get_name =
|
* .fh_to_dentry =
|
||||||
.find_exported_dentry =
|
*/
|
||||||
.decode_fh =
|
|
||||||
.encode_fs = */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
||||||
|
@ -173,6 +173,7 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
|
|||||||
|
|
||||||
|
|
||||||
const struct export_operations squashfs_export_ops = {
|
const struct export_operations squashfs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = squashfs_fh_to_dentry,
|
.fh_to_dentry = squashfs_fh_to_dentry,
|
||||||
.fh_to_parent = squashfs_fh_to_parent,
|
.fh_to_parent = squashfs_fh_to_parent,
|
||||||
.get_parent = squashfs_get_parent
|
.get_parent = squashfs_get_parent
|
||||||
|
@ -137,6 +137,7 @@ static struct dentry *ufs_get_parent(struct dentry *child)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct export_operations ufs_export_ops = {
|
static const struct export_operations ufs_export_ops = {
|
||||||
|
.encode_fh = generic_encode_ino32_fh,
|
||||||
.fh_to_dentry = ufs_fh_to_dentry,
|
.fh_to_dentry = ufs_fh_to_dentry,
|
||||||
.fh_to_parent = ufs_fh_to_parent,
|
.fh_to_parent = ufs_fh_to_parent,
|
||||||
.get_parent = ufs_get_parent,
|
.get_parent = ufs_get_parent,
|
||||||
|
@ -235,7 +235,7 @@ extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
|
|||||||
|
|
||||||
static inline bool exportfs_can_encode_fid(const struct export_operations *nop)
|
static inline bool exportfs_can_encode_fid(const struct export_operations *nop)
|
||||||
{
|
{
|
||||||
return nop;
|
return nop && nop->encode_fh;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool exportfs_can_decode_fh(const struct export_operations *nop)
|
static inline bool exportfs_can_decode_fh(const struct export_operations *nop)
|
||||||
@ -279,6 +279,13 @@ extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
|
|||||||
/*
|
/*
|
||||||
* Generic helpers for filesystems.
|
* Generic helpers for filesystems.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_EXPORTFS
|
||||||
|
int generic_encode_ino32_fh(struct inode *inode, __u32 *fh, int *max_len,
|
||||||
|
struct inode *parent);
|
||||||
|
#else
|
||||||
|
#define generic_encode_ino32_fh NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
extern struct dentry *generic_fh_to_dentry(struct super_block *sb,
|
extern struct dentry *generic_fh_to_dentry(struct super_block *sb,
|
||||||
struct fid *fid, int fh_len, int fh_type,
|
struct fid *fid, int fh_len, int fh_type,
|
||||||
struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
|
struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));
|
||||||
|
Loading…
Reference in New Issue
Block a user