Account for lock recursion when transfering snaplock to the vnode lock

in ffs_snapremove().

Apparently ffs_snapremove() may be called with the snap lock recursed,
at least one trace demonstrated this when snapshot vnode was unlinked
while synced.  It was inactivated from the syncer thread.

Reported and tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2017-07-21 18:28:27 +00:00
parent 754301e94f
commit f2e6bf5c05

View File

@ -1598,7 +1598,7 @@ ffs_snapremove(vp)
struct buf *ibp;
struct fs *fs;
ufs2_daddr_t numblks, blkno, dblk;
int error, loc, last;
int error, i, last, loc;
struct snapdata *sn;
ip = VTOI(vp);
@ -1618,10 +1618,14 @@ ffs_snapremove(vp)
ip->i_nextsnap.tqe_prev = 0;
VI_UNLOCK(devvp);
lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
for (i = 0; i < sn->sn_lock.lk_recurse; i++)
lockmgr(&vp->v_lock, LK_EXCLUSIVE, NULL);
KASSERT(vp->v_vnlock == &sn->sn_lock,
("ffs_snapremove: lost lock mutation"));
vp->v_vnlock = &vp->v_lock;
VI_LOCK(devvp);
while (sn->sn_lock.lk_recurse > 0)
lockmgr(&sn->sn_lock, LK_RELEASE, NULL);
lockmgr(&sn->sn_lock, LK_RELEASE, NULL);
try_free_snapdata(devvp);
} else