diff options
author | Chunwei Chen <[email protected]> | 2017-03-08 09:26:33 -0800 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2017-03-08 09:26:33 -0800 |
commit | 9b77d1c9585572b7ce3af204d40278752d5f5842 (patch) | |
tree | f833d83cdede67ba1a43f1729caa64ebf899a00a /module/zfs/zfs_vnops.c | |
parent | 463009865fb4398b32a825d7c00cd8a942637fae (diff) |
Fix nfs snapdir automount
The current implementation for allowing nfs to access snapdir is very buggy.
It uses a special fh for snapdirs, such that the next time nfsd does
fh_to_dentry, it actually returns the root inode inside the snapshot. So nfsd
never knows it cross a mountpoint.
The problem is that nfsd will not hold a reference on the vfsmount of the
snapshot. This cause auto unmounter to unmount the snapshot even though nfs is
still holding dentries in it.
To fix this, we return the inode for the snapdirs themselves. However, we also
trigger automount upon fh_to_dentry, and return ESTALE so nfsd will revalidate
and see the mountpoint and do crossmnt.
Because nfsd will now be aware that these are different filesystems users
must add crossmnt to their export options to access snapshot directories.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Chunwei Chen <[email protected]>
Closes #3794
Closes #4716
Closes #5810
Closes #5833
Diffstat (limited to 'module/zfs/zfs_vnops.c')
-rw-r--r-- | module/zfs/zfs_vnops.c | 21 |
1 files changed, 1 insertions, 20 deletions
diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 41572d34f..2e5099574 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -4714,12 +4714,7 @@ zfs_fid(struct inode *ip, fid_t *fidp) gen = (uint32_t)gen64; - size = (zsb->z_parent != zsb) ? LONG_FID_LEN : SHORT_FID_LEN; - if (fidp->fid_len < size) { - fidp->fid_len = size; - ZFS_EXIT(zsb); - return (SET_ERROR(ENOSPC)); - } + size = SHORT_FID_LEN; zfid = (zfid_short_t *)fidp; @@ -4734,20 +4729,6 @@ zfs_fid(struct inode *ip, fid_t *fidp) for (i = 0; i < sizeof (zfid->zf_gen); i++) zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i)); - if (size == LONG_FID_LEN) { - uint64_t objsetid = dmu_objset_id(zsb->z_os); - zfid_long_t *zlfid; - - zlfid = (zfid_long_t *)fidp; - - for (i = 0; i < sizeof (zlfid->zf_setid); i++) - zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i)); - - /* XXX - this should be the generation number for the objset */ - for (i = 0; i < sizeof (zlfid->zf_setgen); i++) - zlfid->zf_setgen[i] = 0; - } - ZFS_EXIT(zsb); return (0); } |