exportfs: make ->encode_fh() a mandatory method for NFS export
authorAmir Goldstein <amir73il@gmail.com>
Mon, 23 Oct 2023 18:07:59 +0000 (21:07 +0300)
committerChristian Brauner <brauner@kernel.org>
Sat, 28 Oct 2023 14:15:15 +0000 (16:15 +0200)
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>
19 files changed:
Documentation/filesystems/nfs/exporting.rst
Documentation/filesystems/porting.rst
fs/affs/namei.c
fs/befs/linuxvfs.c
fs/efs/super.c
fs/erofs/super.c
fs/exportfs/expfs.c
fs/ext2/super.c
fs/ext4/super.c
fs/f2fs/super.c
fs/fat/nfs.c
fs/jffs2/super.c
fs/jfs/super.c
fs/ntfs/namei.c
fs/ntfs3/super.c
fs/smb/client/export.c
fs/squashfs/export.c
fs/ufs/super.c
include/linux/exportfs.h

index 4b30daee399af74070b5f494b323fd3aa345cd7a..de64d2d002a204c5460980c898d4ec41fd43d47a 100644 (file)
@@ -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"
 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
-    to find or create a dentry for the same object.  The default
-    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.
+    to find or create a dentry for the same object.
 
   fh_to_dentry (mandatory)
     Given a filehandle fragment, this should find the implied object and
index 4d05b9862451ea8237c583b5f276b1834ee4adb9..9cc6cb27c4d58c9e47392bc55dc313c4b2a2b881 100644 (file)
@@ -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
 other than that all of them must use one of the provided kill_litter_super(),
 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.
index 2fe4a5832fcf4779a25aa122fd2327af1c46d45e..d6b9758ee23dcb8404dd08c7c892e912a6acfdc3 100644 (file)
@@ -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 = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = affs_fh_to_dentry,
        .fh_to_parent = affs_fh_to_parent,
        .get_parent = affs_get_parent,
index 9a16a51fbb88d473b0f7f5c6173ffbb7179db555..410dcaffd5ab88a3bd0dffa4755ecef3f526a034 100644 (file)
@@ -96,6 +96,7 @@ static const struct address_space_operations befs_symlink_aops = {
 };
 
 static const struct export_operations befs_export_operations = {
+       .encode_fh      = generic_encode_ino32_fh,
        .fh_to_dentry   = befs_fh_to_dentry,
        .fh_to_parent   = befs_fh_to_parent,
        .get_parent     = befs_get_parent,
index b287f47c165ba8775d978343164d80e472f4e4d7..f17fdac76b2eea716631f63bce3ca2c66b14a2fc 100644 (file)
@@ -123,6 +123,7 @@ static const struct super_operations efs_superblock_operations = {
 };
 
 static const struct export_operations efs_export_ops = {
+       .encode_fh      = generic_encode_ino32_fh,
        .fh_to_dentry   = efs_fh_to_dentry,
        .fh_to_parent   = efs_fh_to_parent,
        .get_parent     = efs_get_parent,
index 3700af9ee17332f4f6ea766ba3297cdd1e3746fc..edbe07a241562713894f51a97634109ff91ce4ce 100644 (file)
@@ -626,6 +626,7 @@ static struct dentry *erofs_get_parent(struct dentry *child)
 }
 
 static const struct export_operations erofs_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = erofs_fh_to_dentry,
        .fh_to_parent = erofs_fh_to_parent,
        .get_parent = erofs_get_parent,
index 9ee205df8fa76fe02be2c33f1fbc16e9e69fcb8e..8f883c4758f5fef7861c3eff967eb8c2f4496882 100644 (file)
@@ -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
- * @fid:     where to store the file handle fragment
- * @max_len: maximum length to store there
+ * @fh:      where to store the file handle fragment
+ * @max_len: maximum length to store there (in 4 byte units)
  * @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
  * 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.
  */
-static int export_encode_fh(struct inode *inode, struct fid *fid,
-               int *max_len, struct inode *parent)
+int generic_encode_ino32_fh(struct inode *inode, __u32 *fh, int *max_len,
+                           struct inode *parent)
 {
+       struct fid *fid = (void *)fh;
        int len = *max_len;
        int type = FILEID_INO32_GEN;
 
@@ -380,6 +381,7 @@ static int export_encode_fh(struct inode *inode, struct fid *fid,
        *max_len = len;
        return type;
 }
+EXPORT_SYMBOL_GPL(generic_encode_ino32_fh);
 
 /**
  * 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)
                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);
 
index aaf3e3e88cb218a55297b4968dfc325eceb0ed00..b9f158a34997aadc13dcaf46b9784fbb18a63d4c 100644 (file)
@@ -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 = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = ext2_fh_to_dentry,
        .fh_to_parent = ext2_fh_to_parent,
        .get_parent = ext2_get_parent,
index dbebd8b3127e514e7dc165ced48da0b6ff3cd7da..c44db19154375214d79018861eebd33d8a78edc6 100644 (file)
@@ -1646,6 +1646,7 @@ static const struct super_operations ext4_sops = {
 };
 
 static const struct export_operations ext4_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = ext4_fh_to_dentry,
        .fh_to_parent = ext4_fh_to_parent,
        .get_parent = ext4_get_parent,
index a8c8232852bb18749f8a60238c15dfab7f55e0e7..60cfa11f65bf38e8e34ac48e583fbefc22460071 100644 (file)
@@ -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 = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = f2fs_fh_to_dentry,
        .fh_to_parent = f2fs_fh_to_parent,
        .get_parent = f2fs_get_parent,
index 3626eb585a983e9d1a639df5da5e56bf9f19a118..c52e63e10d35cd3ccacee22341bed2679df1db80 100644 (file)
@@ -279,6 +279,7 @@ static struct dentry *fat_get_parent(struct dentry *child_dir)
 }
 
 const struct export_operations fat_export_ops = {
+       .encode_fh      = generic_encode_ino32_fh,
        .fh_to_dentry   = fat_fh_to_dentry,
        .fh_to_parent   = fat_fh_to_parent,
        .get_parent     = fat_get_parent,
index 7ea37f49f1e18e0c7737ac4132c8c4930b4d474f..f99591a634b4dd5b8450ff54bc70de2c66d4677d 100644 (file)
@@ -150,6 +150,7 @@ static struct dentry *jffs2_get_parent(struct dentry *child)
 }
 
 static const struct export_operations jffs2_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .get_parent = jffs2_get_parent,
        .fh_to_dentry = jffs2_fh_to_dentry,
        .fh_to_parent = jffs2_fh_to_parent,
index 2e2f7f6d36a09dd907ca2542c93f0ffe48723f01..2cc2632f3c4792fc5824cfbd8bfea5a13a64e203 100644 (file)
@@ -896,6 +896,7 @@ static const struct super_operations jfs_super_operations = {
 };
 
 static const struct export_operations jfs_export_operations = {
+       .encode_fh      = generic_encode_ino32_fh,
        .fh_to_dentry   = jfs_fh_to_dentry,
        .fh_to_parent   = jfs_fh_to_parent,
        .get_parent     = jfs_get_parent,
index ab44f2db533be099d0a13485c8c2adeedae9f82c..d7498ddc4a7214c60a1526380c17035694979006 100644 (file)
@@ -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().
  */
 const struct export_operations ntfs_export_ops = {
+       .encode_fh      = generic_encode_ino32_fh,
        .get_parent     = ntfs_get_parent,      /* Find the parent of a given
                                                   directory. */
        .fh_to_dentry   = ntfs_fh_to_dentry,
index f763e3256ccc1b6bf8b49acd783030ec4f59eef6..9153dffde950c2a396291bea88e3e6d31169f568 100644 (file)
@@ -811,6 +811,7 @@ static int ntfs_nfs_commit_metadata(struct inode *inode)
 }
 
 static const struct export_operations ntfs_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = ntfs_fh_to_dentry,
        .fh_to_parent = ntfs_fh_to_parent,
        .get_parent = ntfs3_get_parent,
index 37c28415df1e0227d52956a173e12cd6d9f6b9e5..d606e8cbcb7db2b4026675bd9cbc264834687807 100644 (file)
@@ -41,13 +41,12 @@ static struct dentry *cifs_get_parent(struct dentry *dentry)
 }
 
 const struct export_operations cifs_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .get_parent = cifs_get_parent,
-/*     Following five export operations are unneeded so far and can default:
-       .get_dentry =
-       .get_name =
-       .find_exported_dentry =
-       .decode_fh =
-       .encode_fs =  */
+/*
+ * Following export operations are mandatory for NFS export support:
+ *     .fh_to_dentry =
+ */
 };
 
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
index 723763746238d8b260b0b5c7dbca75495f65035f..62972f0ff8681c798f0b11e17d501373b2145bd9 100644 (file)
@@ -173,6 +173,7 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb,
 
 
 const struct export_operations squashfs_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry = squashfs_fh_to_dentry,
        .fh_to_parent = squashfs_fh_to_parent,
        .get_parent = squashfs_get_parent
index 23377c1baed9e09bd938b4d34d80d35b7e2fe8b6..a480810cd4e359f5b272b23677746fba57bddaea 100644 (file)
@@ -137,6 +137,7 @@ static struct dentry *ufs_get_parent(struct dentry *child)
 }
 
 static const struct export_operations ufs_export_ops = {
+       .encode_fh = generic_encode_ino32_fh,
        .fh_to_dentry   = ufs_fh_to_dentry,
        .fh_to_parent   = ufs_fh_to_parent,
        .get_parent     = ufs_get_parent,
index 5b3c9f30b422ada43ec1b1d6e8eedfbc82da1d48..85bd027494e5463018b17545896aa98a6a9124ca 100644 (file)
@@ -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)
 {
-       return nop;
+       return nop && nop->encode_fh;
 }
 
 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.
  */
+#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,
        struct fid *fid, int fh_len, int fh_type,
        struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen));