diff options
Diffstat (limited to 'module/zfs/zpl_inode.c')
-rw-r--r-- | module/zfs/zpl_inode.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index 9b5533755..d9b918b43 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -25,6 +25,7 @@ #include <sys/zfs_vfsops.h> #include <sys/zfs_vnops.h> +#include <sys/zfs_znode.h> #include <sys/vfs.h> #include <sys/zpl.h> @@ -51,7 +52,7 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) return d_splice_alias(ip, dentry); } -static void +void zpl_vap_init(vattr_t *vap, struct inode *dir, struct dentry *dentry, mode_t mode, cred_t *cr) { @@ -171,8 +172,20 @@ zpl_rmdir(struct inode * dir, struct dentry *dentry) static int zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { + boolean_t issnap = ITOZSB(dentry->d_inode)->z_issnap; int error; + /* + * Ensure MNT_SHRINKABLE is set on snapshots to ensure they are + * unmounted automatically with the parent file system. This + * is done on the first getattr because it's not easy to get the + * vfsmount structure at mount time. This call path is explicitly + * marked unlikely to avoid any performance impact. FWIW, ext4 + * resorts to a similar trick for sysadmin convenience. + */ + if (unlikely(issnap && !(mnt->mnt_flags & MNT_SHRINKABLE))) + mnt->mnt_flags |= MNT_SHRINKABLE; + error = -zfs_getattr_fast(dentry->d_inode, stat); ASSERT3S(error, <=, 0); |