Author: kib
Date: Fri Nov 20 15:19:30 2020
New Revision: 367895
URL: https://svnweb.freebsd.org/changeset/base/367895

Log:
  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

Modified:
  head/sys/fs/msdosfs/msdosfs_vfsops.c

Modified: head/sys/fs/msdosfs/msdosfs_vfsops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vfsops.c        Fri Nov 20 14:45:45 2020        
(r367894)
+++ head/sys/fs/msdosfs/msdosfs_vfsops.c        Fri Nov 20 15:19:30 2020        
(r367895)
@@ -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();
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to