aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorAlyssa Ross <[email protected]>2021-05-07 22:08:16 +0000
committerGitHub <[email protected]>2021-05-07 15:08:16 -0700
commitc074a7de1366656f77635da9db02cf5c09798cae (patch)
tree35977ffcebafa2037c87a506aa90cc343c929972 /module
parent4fb9e5638b31bc4b187607601d2ab824257e20d2 (diff)
Return required size when encode_fh size too small
Quoting <linux/exportfs.h>: > encode_fh() should return the fileid_type on success and on error > returns 255 (if the space needed to encode fh is greater than > @max_len*4 bytes). On error @max_len contains the minimum size (in 4 > byte unit) needed to encode the file handle. ZFS was not setting max_len in the case where the handle was too small. As a result of this, the `t_name_to_handle_at.c' example in name_to_handle_at(2) did not work on ZFS. zfsctl_fid() will itself set max_len if called with a fid that is too small, so if we give zfs_fid() that behavior as well, the fix is quite easy: if the handle is too small, just use a zero-size fid instead of the handle. Tested by running t_name_to_handle_at on a normal file, a directory, a .zfs directory, and a snapshot. Thanks-to: Puck Meerburg <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Tony Nguyen <[email protected]> Signed-off-by: Alyssa Ross <[email protected]> Closes #11995
Diffstat (limited to 'module')
-rw-r--r--module/os/linux/zfs/zfs_vnops_os.c7
-rw-r--r--module/os/linux/zfs/zpl_export.c12
2 files changed, 15 insertions, 4 deletions
diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c
index e95d051ed..6f3faab04 100644
--- a/module/os/linux/zfs/zfs_vnops_os.c
+++ b/module/os/linux/zfs/zfs_vnops_os.c
@@ -3950,6 +3950,13 @@ zfs_fid(struct inode *ip, fid_t *fidp)
int size, i, error;
ZFS_ENTER(zfsvfs);
+
+ if (fidp->fid_len < SHORT_FID_LEN) {
+ fidp->fid_len = SHORT_FID_LEN;
+ ZFS_EXIT(zfsvfs);
+ return (SET_ERROR(ENOSPC));
+ }
+
ZFS_VERIFY_ZP(zp);
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
diff --git a/module/os/linux/zfs/zpl_export.c b/module/os/linux/zfs/zpl_export.c
index eaf048c38..5be63532d 100644
--- a/module/os/linux/zfs/zpl_export.c
+++ b/module/os/linux/zfs/zpl_export.c
@@ -41,15 +41,19 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
struct inode *ip = dentry->d_inode;
#endif /* HAVE_ENCODE_FH_WITH_INODE */
fstrans_cookie_t cookie;
- fid_t *fid = (fid_t *)fh;
+ ushort_t empty_fid = 0;
+ fid_t *fid;
int len_bytes, rc;
len_bytes = *max_len * sizeof (__u32);
- if (len_bytes < offsetof(fid_t, fid_data))
- return (255);
+ if (len_bytes < offsetof(fid_t, fid_data)) {
+ fid = (fid_t *)&empty_fid;
+ } else {
+ fid = (fid_t *)fh;
+ fid->fid_len = len_bytes - offsetof(fid_t, fid_data);
+ }
- fid->fid_len = len_bytes - offsetof(fid_t, fid_data);
cookie = spl_fstrans_mark();
if (zfsctl_is_node(ip))