aboutsummaryrefslogtreecommitdiff
path: root/sys/fs/msdosfs
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2020-11-20 15:19:30 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2020-11-20 15:19:30 +0000
commit69367793476876bb9b03ee5c9a180f2a9f9df8a4 (patch)
treef55f5f2698d6790710b42777e3bbabbdcc87fde2 /sys/fs/msdosfs
parent70af7ce99a1daebc3f82062e4d13a733328af554 (diff)
downloadsrc-69367793476876bb9b03ee5c9a180f2a9f9df8a4.tar.gz
src-69367793476876bb9b03ee5c9a180f2a9f9df8a4.zip
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
Notes
Notes: svn path=/head/; revision=367895
Diffstat (limited to 'sys/fs/msdosfs')
-rw-r--r--sys/fs/msdosfs/msdosfs_vfsops.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
index da207c612257..86d5b920643f 100644
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -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();