--- zzzz-none-000/linux-5.4.213/fs/exportfs/expfs.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/fs/exportfs/expfs.c 2024-05-29 11:20:02.000000000 +0000 @@ -344,20 +344,21 @@ } /** - * 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; @@ -381,27 +382,75 @@ *max_len = len; return type; } +EXPORT_SYMBOL_GPL(generic_encode_ino32_fh); + +#define FILEID_INO64_GEN_LEN 3 + +/** + * exportfs_encode_ino64_fid - encode non-decodeable 64bit ino file id + * @inode: the object to encode + * @fid: where to store the file handle fragment + * @max_len: maximum length to store there (in 4 byte units) + * + * This generic function is used to encode a non-decodeable file id for + * fanotify for filesystems that do not support NFS export. + */ +static int exportfs_encode_ino64_fid(struct inode *inode, struct fid *fid, + int *max_len) +{ + if (*max_len < FILEID_INO64_GEN_LEN) { + *max_len = FILEID_INO64_GEN_LEN; + return FILEID_INVALID; + } + + fid->i64.ino = inode->i_ino; + fid->i64.gen = inode->i_generation; + *max_len = FILEID_INO64_GEN_LEN; + return FILEID_INO64_GEN; +} + +/** + * exportfs_encode_inode_fh - encode a file handle from inode + * @inode: the object to encode + * @fid: where to store the file handle fragment + * @max_len: maximum length to store there + * @flags: properties of the requested file handle + * + * Returns an enum fid_type or a negative errno. + */ int exportfs_encode_inode_fh(struct inode *inode, struct fid *fid, - int *max_len, struct inode *parent) + int *max_len, struct inode *parent, int flags) { const struct export_operations *nop = inode->i_sb->s_export_op; - if (nop && nop->encode_fh) - return nop->encode_fh(inode, fid->raw, max_len, parent); + if (!exportfs_can_encode_fh(nop, flags)) + return -EOPNOTSUPP; - return export_encode_fh(inode, fid, max_len, parent); + if (!nop && (flags & EXPORT_FH_FID)) + return exportfs_encode_ino64_fid(inode, fid, max_len); + + return nop->encode_fh(inode, fid->raw, max_len, parent); } EXPORT_SYMBOL_GPL(exportfs_encode_inode_fh); +/** + * exportfs_encode_fh - encode a file handle from dentry + * @dentry: the object to encode + * @fid: where to store the file handle fragment + * @max_len: maximum length to store there + * @flags: properties of the requested file handle + * + * Returns an enum fid_type or a negative errno. + */ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, - int connectable) + int flags) { int error; struct dentry *p = NULL; struct inode *inode = dentry->d_inode, *parent = NULL; - if (connectable && !S_ISDIR(inode->i_mode)) { + if ((flags & EXPORT_FH_CONNECTABLE) && !S_ISDIR(inode->i_mode)) { p = dget_parent(dentry); /* * note that while p might've ceased to be our parent already, @@ -410,7 +459,7 @@ parent = p->d_inode; } - error = exportfs_encode_inode_fh(inode, fid, max_len, parent); + error = exportfs_encode_inode_fh(inode, fid, max_len, parent, flags); dput(p); return error; @@ -429,7 +478,7 @@ /* * Try to get any dentry for the given file handle from the filesystem. */ - if (!nop || !nop->fh_to_dentry) + if (!exportfs_can_decode_fh(nop)) return ERR_PTR(-ESTALE); result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); if (PTR_ERR(result) == -ENOMEM)