aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zpl_inode.c')
-rw-r--r--module/zfs/zpl_inode.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
index e81a3cd04..6475c72d7 100644
--- a/module/zfs/zpl_inode.c
+++ b/module/zfs/zpl_inode.c
@@ -24,6 +24,7 @@
*/
+#include <sys/zfs_ctldir.h>
#include <sys/zfs_vfsops.h>
#include <sys/zfs_vnops.h>
#include <sys/zfs_znode.h>
@@ -240,21 +241,9 @@ 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;
fstrans_cookie_t cookie;
- /*
- * 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;
-
cookie = spl_fstrans_mark();
error = -zfs_getattr_fast(dentry->d_inode, stat);
spl_fstrans_unmark(cookie);
@@ -504,6 +493,19 @@ zpl_revalidate(struct dentry *dentry, unsigned int flags)
return (-ECHILD);
/*
+ * Automounted snapshots rely on periodic dentry revalidation
+ * to defer snapshots from being automatically unmounted.
+ */
+ if (zsb->z_issnap) {
+ if (time_after(jiffies, zsb->z_snap_defer_time +
+ MAX(zfs_expire_snapshot * HZ / 2, HZ))) {
+ zsb->z_snap_defer_time = jiffies;
+ zfsctl_snapshot_unmount_delay(
+ dmu_objset_id(zsb->z_os), zfs_expire_snapshot);
+ }
+ }
+
+ /*
* After a rollback negative dentries created before the rollback
* time must be invalidated. Otherwise they can obscure files which
* are only present in the rolled back dataset.