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
This commit is contained in:
parent
88f7980a81
commit
7223645bd1
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user