The process_deferred_inactive() function locks the vnodes of the ufs

mount, which means that is must not be called while the snaplock is
owned.  The vfs_write_resume(9) does call the function as the
VFS_SUSP_CLEAN() method, which is too early and falls into the region
still protected by snaplock.

Add yet another flag for the vfs_write_resume_flags() to avoid calling
suspension cleanup handler after the suspend is lifted, and use it in
the ffs_snapshot() call to vfs_write_resume.

Reported and tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2013-01-01 16:14:48 +00:00
parent 364d32d67d
commit f99cb34c4f
3 changed files with 4 additions and 2 deletions

View File

@ -1667,7 +1667,8 @@ vfs_write_resume_flags(struct mount *mp, int flags)
mp->mnt_writeopcount++;
}
MNT_IUNLOCK(mp);
VFS_SUSP_CLEAN(mp);
if ((flags & VR_NO_SUSPCLR) == 0)
VFS_SUSP_CLEAN(mp);
} else if ((flags & VR_START_WRITE) != 0) {
MNT_REF(mp);
vn_start_write_locked(mp, 0);

View File

@ -393,6 +393,7 @@ extern int vttoif_tab[];
#define V_XSLEEP 0x0004 /* vn_start_write: just return after sleep */
#define VR_START_WRITE 0x0001 /* vfs_write_resume: start write atomically */
#define VR_NO_SUSPCLR 0x0002 /* vfs_write_resume: do not clear suspension */
#define VREF(vp) vref(vp)

View File

@ -687,7 +687,7 @@ ffs_snapshot(mp, snapfile)
/*
* Resume operation on filesystem.
*/
vfs_write_resume_flags(vp->v_mount, VR_START_WRITE);
vfs_write_resume_flags(vp->v_mount, VR_START_WRITE | VR_NO_SUSPCLR);
if (collectsnapstats && starttime.tv_sec > 0) {
nanotime(&endtime);
timespecsub(&endtime, &starttime);