diff options
author | avg <avg@FreeBSD.org> | 2016-07-13 10:11:48 +0000 |
---|---|---|
committer | avg <avg@FreeBSD.org> | 2016-07-13 10:11:48 +0000 |
commit | fe6f83f81589f969eb04c98d4b7c0e191ff64bcd (patch) | |
tree | 5362642a3d86b2aad27813990181a35dd8fa3ba2 /sys/cddl/contrib | |
parent | 3e58df09596aea413cde6ad3fbfd7b9a90280711 (diff) | |
download | FreeBSD-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.c | 13 |
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 |