Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

exportfs: add explicit flag to request non-decodeable file handles

So far, all callers of exportfs_encode_inode_fh(), except for fsnotify's
show_mark_fhandle(), check that filesystem can decode file handles, but
we would like to add more callers that do not require a file handle that
can be decoded.

Introduce a flag to explicitly request a file handle that may not to be
decoded later and a wrapper exportfs_encode_fid() that sets this flag
and convert show_mark_fhandle() to use the new wrapper.

This will be used to allow adding fanotify support to filesystems that
do not support NFS export.

Acked-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Message-Id: <20230502124817.3070545-3-amir73il@gmail.com>

authored by

Amir Goldstein and committed by
Jan Kara
304e9c83 b5287827

+34 -8
+2 -2
Documentation/filesystems/nfs/exporting.rst
··· 122 122 super_block. This field must point to a "struct export_operations" 123 123 struct which has the following members: 124 124 125 - encode_fh (optional) 126 - Takes a dentry and creates a filehandle fragment which can later be used 125 + encode_fh (optional) 126 + Takes a dentry and creates a filehandle fragment which may later be used 127 127 to find or create a dentry for the same object. The default 128 128 implementation creates a filehandle fragment that encodes a 32bit inode 129 129 and generation number for the inode encoded, and if necessary the
+18 -2
fs/exportfs/expfs.c
··· 381 381 return type; 382 382 } 383 383 384 + /** 385 + * exportfs_encode_inode_fh - encode a file handle from inode 386 + * @inode: the object to encode 387 + * @fid: where to store the file handle fragment 388 + * @max_len: maximum length to store there 389 + * @flags: properties of the requested file handle 390 + * 391 + * Returns an enum fid_type or a negative errno. 392 + */ 384 393 int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, 385 - int *max_len, struct inode *parent) 394 + int *max_len, struct inode *parent, int flags) 386 395 { 387 396 const struct export_operations *nop = inode->i_sb->s_export_op; 397 + 398 + /* 399 + * If a decodeable file handle was requested, we need to make sure that 400 + * filesystem can decode file handles. 401 + */ 402 + if (nop && !(flags & EXPORT_FH_FID) && !nop->fh_to_dentry) 403 + return -EOPNOTSUPP; 388 404 389 405 if (nop && nop->encode_fh) 390 406 return nop->encode_fh(inode, fid->raw, max_len, parent); ··· 434 418 parent = p->d_inode; 435 419 } 436 420 437 - error = exportfs_encode_inode_fh(inode, fid, max_len, parent); 421 + error = exportfs_encode_inode_fh(inode, fid, max_len, parent, flags); 438 422 dput(p); 439 423 440 424 return error;
+2 -2
fs/notify/fanotify/fanotify.c
··· 380 380 if (!inode) 381 381 return 0; 382 382 383 - exportfs_encode_inode_fh(inode, NULL, &dwords, NULL); 383 + exportfs_encode_inode_fh(inode, NULL, &dwords, NULL, 0); 384 384 fh_len = dwords << 2; 385 385 386 386 /* ··· 443 443 } 444 444 445 445 dwords = fh_len >> 2; 446 - type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL); 446 + type = exportfs_encode_inode_fh(inode, buf, &dwords, NULL, 0); 447 447 err = -EINVAL; 448 448 if (!type || type == FILEID_INVALID || fh_len != dwords << 2) 449 449 goto out_err;
+1 -1
fs/notify/fdinfo.c
··· 50 50 f.handle.handle_bytes = sizeof(f.pad); 51 51 size = f.handle.handle_bytes >> 2; 52 52 53 - ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, NULL); 53 + ret = exportfs_encode_fid(inode, (struct fid *)f.handle.f_handle, &size); 54 54 if ((ret == FILEID_INVALID) || (ret < 0)) { 55 55 WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret); 56 56 return;
+11 -1
include/linux/exportfs.h
··· 136 136 }; 137 137 138 138 #define EXPORT_FH_CONNECTABLE 0x1 /* Encode file handle with parent */ 139 + #define EXPORT_FH_FID 0x2 /* File handle may be non-decodeable */ 139 140 140 141 /** 141 142 * struct export_operations - for nfsd to communicate with file systems ··· 228 227 }; 229 228 230 229 extern int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, 231 - int *max_len, struct inode *parent); 230 + int *max_len, struct inode *parent, 231 + int flags); 232 232 extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, 233 233 int *max_len, int flags); 234 + 235 + static inline int exportfs_encode_fid(struct inode *inode, struct fid *fid, 236 + int *max_len) 237 + { 238 + return exportfs_encode_inode_fh(inode, fid, max_len, NULL, 239 + EXPORT_FH_FID); 240 + } 241 + 234 242 extern struct dentry *exportfs_decode_fh_raw(struct vfsmount *mnt, 235 243 struct fid *fid, int fh_len, 236 244 int fileid_type,