Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 May 2016 15:03:53 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r299945 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201605161503.u4GF3rRa020856@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Mon May 16 15:03:52 2016
New Revision: 299945
URL: https://svnweb.freebsd.org/changeset/base/299945

Log:
  avoid deadlock between zfsctl_snapdir_lookup and zfsctl_snapshot_reclaim
  
  The former acquired a snap vnode lock while holding sd_lock while the
  latter does the opposite.
  
  The solution is drop sd_lock before acquiring the vnode lock.  That
  should be okay as we are still holding a lock on the 'snapshot'
  directory in the exclusive mode.  That lock ensures that there are no
  concurrent lookups in the directory and thus no concurrent mount attempts.
  
  But now we have to account for the possibility that the snap vnode
  might get reclaim after we drop sd_lock and before we can get
  the node lock.  So, check for that case and retry.
  
  MFC after:	5 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Mon May 16 14:07:43 2016	(r299944)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Mon May 16 15:03:52 2016	(r299945)
@@ -1011,6 +1011,7 @@ zfsctl_snapdir_lookup(ap)
 #endif
 	}
 
+relookup:
 	mutex_enter(&sdp->sd_lock);
 	search.se_name = (char *)nm;
 	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
@@ -1085,7 +1086,16 @@ domount:
 	(void) snprintf(mountpoint, mountpoint_len,
 	    "%s/" ZFS_CTLDIR_NAME "/snapshot/%s",
 	    dvp->v_vfsp->mnt_stat.f_mntonname, nm);
-	VERIFY0(vn_lock(*vpp, LK_EXCLUSIVE));
+	mutex_exit(&sdp->sd_lock);
+
+	/*
+	 * The vnode may get reclaimed between dropping sd_lock and
+	 * getting the vnode lock.
+	 * */
+	err = vn_lock(*vpp, LK_EXCLUSIVE);
+	if (err == ENOENT)
+		goto relookup;
+	VERIFY0(err);
 	err = mount_snapshot(curthread, vpp, "zfs", mountpoint, snapname, 0);
 	kmem_free(mountpoint, mountpoint_len);
 	if (err == 0) {
@@ -1100,7 +1110,6 @@ domount:
 		VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
 		(*vpp)->v_flag &= ~VROOT;
 	}
-	mutex_exit(&sdp->sd_lock);
 	ZFS_EXIT(zfsvfs);
 
 #ifdef illumos



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605161503.u4GF3rRa020856>