diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2020-11-20 15:19:30 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2020-11-20 15:19:30 +0000 |
commit | 69367793476876bb9b03ee5c9a180f2a9f9df8a4 (patch) | |
tree | f55f5f2698d6790710b42777e3bbabbdcc87fde2 /sys/fs/msdosfs | |
parent | 70af7ce99a1daebc3f82062e4d13a733328af554 (diff) | |
download | src-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.c | 43 |
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(); |