Remove some unneeded vfs_busy() calls in SU code.

When softdep_fsync() is running, a caller must already started write
for the mount point.  Since unmount or remount to ro suspends mount
point, it cannot run in parallel with softdep_fsync(), which makes
vfs_busy() call there not needed.

Doing blocking vfs_busy() there effectively causes lock order reversal
between vn_start_write() and setting MNTK_UNMOUNT, because
vfs_busy(mp, 0) sleeps waiting for MNTK_UNMOUNT becoming clear, while
unmount sets the flag and starts the suspension.

Note that all other uses of vfs_busy() in SU code are non-blocking.

Reported by:	chs by mckusick
Reviewed by:	mckusick
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2019-09-09 11:22:38 +00:00
parent 7f3ea0ab3a
commit d89ac450a7

View File

@ -12507,24 +12507,13 @@ softdep_fsync(vp)
FREE_LOCK(ump); FREE_LOCK(ump);
if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp, if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp,
FFSV_FORCEINSMQ)) { FFSV_FORCEINSMQ)) {
error = vfs_busy(mp, MBF_NOWAIT); /*
if (error != 0) { * Unmount cannot proceed after unlock because
vfs_ref(mp); * caller must have called vn_start_write().
VOP_UNLOCK(vp, 0); */
error = vfs_busy(mp, 0);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
vfs_rel(mp);
if (error != 0)
return (ENOENT);
if (vp->v_iflag & VI_DOOMED) {
vfs_unbusy(mp);
return (ENOENT);
}
}
VOP_UNLOCK(vp, 0); VOP_UNLOCK(vp, 0);
error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE, error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE,
&pvp, FFSV_FORCEINSMQ); &pvp, FFSV_FORCEINSMQ);
vfs_unbusy(mp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) { if (vp->v_iflag & VI_DOOMED) {
if (error == 0) if (error == 0)