From 66c62769bcf6aa142e2309278980a2e52f4b08db Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 23 Oct 2023 21:07:58 +0300 Subject: exportfs: add helpers to check if filesystem can encode/decode file handles The logic of whether filesystem can encode/decode file handles is open coded in many places. In preparation to changing the logic, move the open coded logic into inline helpers. Reviewed-by: Jan Kara Reviewed-by: Jeff Layton Signed-off-by: Amir Goldstein Link: https://lore.kernel.org/r/20231023180801.2953446-2-amir73il@gmail.com Signed-off-by: Christian Brauner --- include/linux/exportfs.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'include/linux') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 11fbd0ee1370..5b3c9f30b422 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -233,6 +233,33 @@ extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, int flags); +static inline bool exportfs_can_encode_fid(const struct export_operations *nop) +{ + return nop; +} + +static inline bool exportfs_can_decode_fh(const struct export_operations *nop) +{ + return nop && nop->fh_to_dentry; +} + +static inline bool exportfs_can_encode_fh(const struct export_operations *nop, + int fh_flags) +{ + /* + * If a non-decodeable file handle was requested, we only need to make + * sure that filesystem can encode file handles. + */ + if (fh_flags & EXPORT_FH_FID) + return exportfs_can_encode_fid(nop); + + /* + * If a decodeable file handle was requested, we need to make sure that + * filesystem can also decode file handles. + */ + return exportfs_can_decode_fh(nop); +} + static inline int exportfs_encode_fid(struct inode *inode, struct fid *fid, int *max_len) { -- cgit v1.2.3 From e21fc2038c1b978b89bbc3d45a4c5c6ef598e178 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 23 Oct 2023 21:07:59 +0300 Subject: 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 Reviewed-by: Jeff Layton Acked-by: Chuck Lever Signed-off-by: Amir Goldstein Link: https://lore.kernel.org/r/20231023180801.2953446-3-amir73il@gmail.com Acked-by: Dave Kleikamp Reviewed-by: Christoph Hellwig Signed-off-by: Christian Brauner --- include/linux/exportfs.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 5b3c9f30b422..85bd027494e5 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -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)); -- cgit v1.2.3 From 41d1ddd2717c758b8606a66d57d2cc63b41373c0 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 23 Oct 2023 21:08:00 +0300 Subject: exportfs: define FILEID_INO64_GEN* file handle types Similar to the common FILEID_INO32* file handle types, define common FILEID_INO64* file handle types. The type values of FILEID_INO64_GEN and FILEID_INO64_GEN_PARENT are the values returned by fuse and xfs for 64bit ino encoded file handle types. Note that these type value are filesystem specific and they do not define a universal file handle format, for example: fuse encodes FILEID_INO64_GEN as [ino-hi32,ino-lo32,gen] and xfs encodes FILEID_INO64_GEN as [hostr-order-ino64,gen] (a.k.a xfs_fid64). The FILEID_INO64_GEN fhandle type is going to be used for file ids for fanotify from filesystems that do not support NFS export. Reviewed-by: Jan Kara Reviewed-by: Jeff Layton Signed-off-by: Amir Goldstein Link: https://lore.kernel.org/r/20231023180801.2953446-4-amir73il@gmail.com Signed-off-by: Christian Brauner --- include/linux/exportfs.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/linux') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 85bd027494e5..4119d3ee72eb 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -98,6 +98,17 @@ enum fid_type { */ FILEID_FAT_WITH_PARENT = 0x72, + /* + * 64 bit inode number, 32 bit generation number. + */ + FILEID_INO64_GEN = 0x81, + + /* + * 64 bit inode number, 32 bit generation number, + * 64 bit parent inode number, 32 bit parent generation. + */ + FILEID_INO64_GEN_PARENT = 0x82, + /* * 128 bit child FID (struct lu_fid) * 128 bit parent FID (struct lu_fid) -- cgit v1.2.3 From 64343119d7b80b4ee9ba7703390681608a17f2c5 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 23 Oct 2023 21:08:01 +0300 Subject: exportfs: support encoding non-decodeable file handles by default AT_HANDLE_FID was added as an API for name_to_handle_at() that request the encoding of a file id, which is not intended to be decoded. This file id is used by fanotify to describe objects in events. So far, overlayfs is the only filesystem that supports encoding non-decodeable file ids, by providing export_operations with an ->encode_fh() method and without a ->decode_fh() method. Add support for encoding non-decodeable file ids to all the filesystems that do not provide export_operations, by encoding a file id of type FILEID_INO64_GEN from { i_ino, i_generation }. A filesystem may that does not support NFS export, can opt-out of encoding non-decodeable file ids for fanotify by defining an empty export_operations struct (i.e. with a NULL ->encode_fh() method). This allows the use of fanotify events with file ids on filesystems like 9p which do not support NFS export to bring fanotify in feature parity with inotify on those filesystems. Note that fanotify also requires that the filesystems report a non-null fsid. Currently, many simple filesystems that have support for inotify (e.g. debugfs, tracefs, sysfs) report a null fsid, so can still not be used with fanotify in file id reporting mode. Reviewed-by: Jan Kara Reviewed-by: Jeff Layton Signed-off-by: Amir Goldstein Link: https://lore.kernel.org/r/20231023180801.2953446-5-amir73il@gmail.com Signed-off-by: Christian Brauner --- include/linux/exportfs.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 4119d3ee72eb..21bae8bfeef1 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -134,7 +134,11 @@ struct fid { u32 parent_ino; u32 parent_gen; } i32; - struct { + struct { + u64 ino; + u32 gen; + } __packed i64; + struct { u32 block; u16 partref; u16 parent_partref; @@ -246,7 +250,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 && nop->encode_fh; + return !nop || nop->encode_fh; } static inline bool exportfs_can_decode_fh(const struct export_operations *nop) @@ -259,7 +263,7 @@ static inline bool exportfs_can_encode_fh(const struct export_operations *nop, { /* * If a non-decodeable file handle was requested, we only need to make - * sure that filesystem can encode file handles. + * sure that filesystem did not opt-out of encoding fid. */ if (fh_flags & EXPORT_FH_FID) return exportfs_can_encode_fid(nop); -- cgit v1.2.3 From d9e5d9221d7f82a2736f091bbc5b54ab8d6ef701 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Thu, 26 Oct 2023 23:45:40 +0300 Subject: fs: fix build error with CONFIG_EXPORTFS=m or not defined Many of the filesystems that call the generic exportfs helpers do not select the EXPORTFS config. Move generic_encode_ino32_fh() to libfs.c, same as generic_fh_to_*() to avoid having to fix all those config dependencies. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202310262151.renqMvme-lkp@intel.com/ Fixes: dfaf653dc415 ("exportfs: make ->encode_fh() a mandatory method for NFS export") Suggested-by: Arnd Bergmann Signed-off-by: Amir Goldstein Link: https://lore.kernel.org/r/20231026204540.143217-1-amir73il@gmail.com Tested-by: Arnd Bergmann Signed-off-by: Christian Brauner --- include/linux/exportfs.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 21bae8bfeef1..e0e69dafaa43 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -294,17 +294,12 @@ 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 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)); -extern struct dentry *generic_fh_to_parent(struct super_block *sb, +struct dentry *generic_fh_to_parent(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)); -- cgit v1.2.3