msdosfs: suspend around unmount or remount rw->ro.

This also eliminates unsafe use of VFS_SYNC(MNT_WAIT).

Requested by:	mckusick
Discussed with:	imp
Tested by:	pho (previous version)
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D27269
This commit is contained in:
kib 2020-11-20 15:19:30 +00:00
parent fc2747e5ed
commit f23271115b

View File

@ -248,22 +248,28 @@ msdosfs_mount(struct mount *mp)
pmp = VFSTOMSDOSFS(mp);
if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) &&
vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) {
error = VFS_SYNC(mp, MNT_WAIT);
if (error)
if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0)
return (error);
error = vfs_write_suspend_umnt(mp);
if (error != 0)
return (error);
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
error = vflush(mp, 0, flags, td);
if (error)
if (error != 0) {
vfs_write_resume(mp, 0);
return (error);
}
/*
* Now the volume is clean. Mark it so while the
* device is still rw.
*/
error = markvoldirty(pmp, 0);
if (error) {
if (error != 0) {
vfs_write_resume(mp, 0);
(void)markvoldirty(pmp, 1);
return (error);
}
@ -273,6 +279,7 @@ msdosfs_mount(struct mount *mp)
error = g_access(pmp->pm_cp, 0, -1, 0);
g_topology_unlock();
if (error) {
vfs_write_resume(mp, 0);
(void)markvoldirty(pmp, 1);
return (error);
}
@ -286,6 +293,7 @@ msdosfs_mount(struct mount *mp)
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
MNT_IUNLOCK(mp);
vfs_write_resume(mp, 0);
} else if ((pmp->pm_flags & MSDOSFSMNT_RONLY) &&
!vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) {
/*
@ -749,21 +757,31 @@ msdosfs_unmount(struct mount *mp, int mntflags)
{
struct msdosfsmount *pmp;
int error, flags;
bool susp;
error = flags = 0;
pmp = VFSTOMSDOSFS(mp);
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0)
error = msdosfs_sync(mp, MNT_WAIT);
susp = (pmp->pm_flags & MSDOSFSMNT_RONLY) == 0;
if (susp) {
error = vfs_write_suspend_umnt(mp);
if (error != 0)
return (error);
}
if ((mntflags & MNT_FORCE) != 0)
flags |= FORCECLOSE;
else if (error != 0)
return (error);
error = vflush(mp, 0, flags, curthread);
if (error != 0 && error != ENXIO)
if (error != 0 && error != ENXIO) {
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
return (error);
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) {
}
if (susp) {
error = markvoldirty(pmp, 0);
if (error && error != ENXIO) {
if (error != 0 && error != ENXIO) {
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
(void)markvoldirty(pmp, 1);
return (error);
}
@ -800,6 +818,9 @@ msdosfs_unmount(struct mount *mp, int mntflags)
BO_UNLOCK(bo);
}
#endif
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
g_topology_lock();
g_vfs_close(pmp->pm_cp);
g_topology_unlock();