summaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_ctldir.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2015-04-24 16:21:13 -0700
committerBrian Behlendorf <[email protected]>2015-08-31 13:54:39 -0700
commit278bee9319ba5947b995673d2c76e0333f2d33d4 (patch)
treea621142a2d5314b460cbf1a8bc6b6092f7a46424 /module/zfs/zpl_ctldir.c
parentb23975cbe0f249671c131b0d6e4ae1bb10594440 (diff)
Linux 3.18 compat: Snapshot auto-mounting
Re-factor the .zfs/snapshot auto-mouting code to take in to account changes made to the upstream kernels. And to lay the groundwork for enabling access to .zfs snapshots via NFS clients. This patch makes the following core improvements. * All actively auto-mounted snapshots are now tracked in two global trees which are indexed by snapshot name and objset id respectively. This allows for fast lookups of any auto-mounted snapshot regardless without needing access to the parent dataset. * Snapshot entries are added to the tree in zfsctl_snapshot_mount(). However, they are now removed from the tree in the context of the unmount process. This eliminates the need complicated error logic in zfsctl_snapshot_unmount() to handle unmount failures. * References are now taken on the snapshot entries in the tree to ensure they always remain valid while a task is outstanding. * The MNT_SHRINKABLE flag is set on the snapshot vfsmount_t right after the auto-mount succeeds. This allows to kernel to unmount idle auto-mounted snapshots if needed removing the need for the zfsctl_unmount_snapshots() function. * Snapshots in active use will not be automatically unmounted. As long as at least one dentry is revalidated every zfs_expire_snapshot/2 seconds the auto-unmount expiration timer will be extended. * Commit torvalds/linux@bafc9b7 caused snapshots auto-mounted by ZFS to be immediately unmounted when the dentry was revalidated. This was a consequence of ZFS invaliding all snapdir dentries to ensure that negative dentries didn't mask new snapshots. This patch modifies the behavior such that only negative dentries are invalidated. This solves the issue and may result in a performance improvement. Signed-off-by: Brian Behlendorf <[email protected]> Closes #3589 Closes #3344 Closes #3295 Closes #3257 Closes #3243 Closes #3030 Closes #2841
Diffstat (limited to 'module/zfs/zpl_ctldir.c')
-rw-r--r--module/zfs/zpl_ctldir.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c
index d93d900aa..dd02e9e99 100644
--- a/module/zfs/zpl_ctldir.c
+++ b/module/zfs/zpl_ctldir.c
@@ -160,19 +160,9 @@ const struct inode_operations zpl_ops_root = {
static struct vfsmount *
zpl_snapdir_automount(struct path *path)
{
- struct dentry *dentry = path->dentry;
int error;
- /*
- * We must briefly disable automounts for this dentry because the
- * user space mount utility will trigger another lookup on this
- * directory. That will result in zpl_snapdir_automount() being
- * called repeatedly. The DCACHE_NEED_AUTOMOUNT flag can be
- * safely reset once the mount completes.
- */
- dentry->d_flags &= ~DCACHE_NEED_AUTOMOUNT;
- error = -zfsctl_mount_snapshot(path, 0);
- dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+ error = -zfsctl_snapshot_mount(path, 0);
if (error)
return (ERR_PTR(error));
@@ -188,8 +178,10 @@ zpl_snapdir_automount(struct path *path)
#endif /* HAVE_AUTOMOUNT */
/*
- * Revalidate any dentry in the snapshot directory on lookup, since a snapshot
- * having the same name have been created or destroyed since it was cached.
+ * Negative dentries must always be revalidated so newly created snapshots
+ * can be detected and automounted. Normal dentries should be kept because
+ * as of the 3.18 kernel revaliding the mountpoint dentry will result in
+ * the snapshot being immediately unmounted.
*/
static int
#ifdef HAVE_D_REVALIDATE_NAMEIDATA
@@ -198,7 +190,7 @@ zpl_snapdir_revalidate(struct dentry *dentry, struct nameidata *i)
zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
#endif
{
- return (0);
+ return (!!dentry->d_inode);
}
dentry_operations_t zpl_dops_snapdirs = {
@@ -245,6 +237,9 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
ASSERT(error == 0 || ip == NULL);
d_clear_d_op(dentry);
d_set_d_op(dentry, &zpl_dops_snapdirs);
+#ifdef HAVE_AUTOMOUNT
+ dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+#endif
return (d_splice_alias(ip, dentry));
}
@@ -373,7 +368,7 @@ zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry,
ZFS_ENTER(zsb);
error = simple_getattr(mnt, dentry, stat);
- stat->nlink = stat->size = avl_numnodes(&zsb->z_ctldir_snaps) + 2;
+ stat->nlink = stat->size = 2;
stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zsb->z_os);
stat->atime = CURRENT_TIME;
ZFS_EXIT(zsb);