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 <puck@puckipedia.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Tony Nguyen <tony.nguyen@delphix.com> Signed-off-by: Alyssa Ross <hi@alyssa.is> Closes #11995
This commit is contained in:
parent
0db64e9036
commit
f15ec889a9
|
@ -3950,6 +3950,13 @@ zfs_fid(struct inode *ip, fid_t *fidp)
|
||||||
int size, i, error;
|
int size, i, error;
|
||||||
|
|
||||||
ZFS_ENTER(zfsvfs);
|
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);
|
ZFS_VERIFY_ZP(zp);
|
||||||
|
|
||||||
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
|
if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
|
||||||
|
|
|
@ -41,15 +41,19 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
|
||||||
struct inode *ip = dentry->d_inode;
|
struct inode *ip = dentry->d_inode;
|
||||||
#endif /* HAVE_ENCODE_FH_WITH_INODE */
|
#endif /* HAVE_ENCODE_FH_WITH_INODE */
|
||||||
fstrans_cookie_t cookie;
|
fstrans_cookie_t cookie;
|
||||||
fid_t *fid = (fid_t *)fh;
|
ushort_t empty_fid = 0;
|
||||||
|
fid_t *fid;
|
||||||
int len_bytes, rc;
|
int len_bytes, rc;
|
||||||
|
|
||||||
len_bytes = *max_len * sizeof (__u32);
|
len_bytes = *max_len * sizeof (__u32);
|
||||||
|
|
||||||
if (len_bytes < offsetof(fid_t, fid_data))
|
if (len_bytes < offsetof(fid_t, fid_data)) {
|
||||||
return (255);
|
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();
|
cookie = spl_fstrans_mark();
|
||||||
|
|
||||||
if (zfsctl_is_node(ip))
|
if (zfsctl_is_node(ip))
|
||||||
|
|
Loading…
Reference in New Issue