summaryrefslogtreecommitdiffstats
path: root/sys/cddl/contrib
diff options
context:
space:
mode:
authoravg <avg@FreeBSD.org>2016-07-13 10:11:48 +0000
committeravg <avg@FreeBSD.org>2016-07-13 10:11:48 +0000
commitfe6f83f81589f969eb04c98d4b7c0e191ff64bcd (patch)
tree5362642a3d86b2aad27813990181a35dd8fa3ba2 /sys/cddl/contrib
parent3e58df09596aea413cde6ad3fbfd7b9a90280711 (diff)
downloadFreeBSD-src-fe6f83f81589f969eb04c98d4b7c0e191ff64bcd.zip
FreeBSD-src-fe6f83f81589f969eb04c98d4b7c0e191ff64bcd.tar.gz
MFC r299945: avoid deadlock between zfsctl_snapdir_lookup and
zfsctl_snapshot_reclaim
Diffstat (limited to 'sys/cddl/contrib')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
index fa350a1..42c697a 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
@@ -1037,6 +1037,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) {
@@ -1104,7 +1105,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) {
@@ -1118,7 +1128,6 @@ domount:
ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs);
VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
}
- mutex_exit(&sdp->sd_lock);
ZFS_EXIT(zfsvfs);
#ifdef illumos
OpenPOWER on IntegriCloud