Author: kib
Date: Sun Feb 17 20:35:54 2013
New Revision: 246921
URL: http://svnweb.freebsd.org/changeset/base/246921

Log:
  Do not update the fsinfo block on each update of any fat block, this
  is excessive. Postpone the flush of the fsinfo to VFS_SYNC(),
  remembering the need for update with the flag MSDOSFS_FSIMOD, stored
  in pm_flags.
  
  FAT32 specification describes both FSI_Free_Count and FSI_Nxt_Free as
  the advisory hints, not requiring them to be correct.
  
  Based on the patch from bde, modified by me.
  
  Reviewed by: bde
  MFC after:   2 weeks

Modified:
  head/sys/fs/msdosfs/msdosfs_fat.c
  head/sys/fs/msdosfs/msdosfs_vfsops.c
  head/sys/fs/msdosfs/msdosfsmount.h

Modified: head/sys/fs/msdosfs/msdosfs_fat.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_fat.c   Sun Feb 17 19:49:59 2013        
(r246920)
+++ head/sys/fs/msdosfs/msdosfs_fat.c   Sun Feb 17 20:35:54 2013        
(r246921)
@@ -328,29 +328,6 @@ updatefats(pmp, bp, fatbn)
        printf("updatefats(pmp %p, bp %p, fatbn %lu)\n", pmp, bp, fatbn);
 #endif
 
-       /*
-        * If we have an FSInfo block, update it.
-        */
-       if (pmp->pm_fsinfo) {
-               if (bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
-                   NOCRED, &bpn) != 0) {
-                       /*
-                        * Ignore the error, but turn off FSInfo update for the 
future.
-                        */
-                       pmp->pm_fsinfo = 0;
-                       brelse(bpn);
-               } else {
-                       struct fsinfo *fp = (struct fsinfo *)bpn->b_data;
-
-                       putulong(fp->fsinfree, pmp->pm_freeclustercount);
-                       putulong(fp->fsinxtfree, pmp->pm_nxtfree);
-                       if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
-                               bwrite(bpn);
-                       else
-                               bdwrite(bpn);
-               }
-       }
-
        if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
                /*
                 * Now copy the block(s) of the modified fat to the other 
copies of
@@ -393,9 +370,6 @@ updatefats(pmp, bp, fatbn)
                bwrite(bp);
        else
                bdwrite(bp);
-       /*
-        * Maybe update fsinfo sector here?
-        */
 }
 
 /*
@@ -431,6 +405,7 @@ usemap_alloc(pmp, cn)
        pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
        KASSERT(pmp->pm_freeclustercount > 0, ("usemap_alloc: too little"));
        pmp->pm_freeclustercount--;
+       pmp->pm_flags |= MSDOSFS_FSIMOD;
 }
 
 static __inline void
@@ -441,6 +416,7 @@ usemap_free(pmp, cn)
 
        MSDOSFS_ASSERT_MP_LOCKED(pmp);
        pmp->pm_freeclustercount++;
+       pmp->pm_flags |= MSDOSFS_FSIMOD;
        KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] & (1 << (cn % N_INUSEBITS)))
            != 0, ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
                (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
@@ -742,7 +718,10 @@ chainalloc(pmp, start, count, fillwith, 
 
        for (cl = start, n = count; n-- > 0;)
                usemap_alloc(pmp, cl++);
-
+       pmp->pm_nxtfree = start + count;
+       if (pmp->pm_nxtfree > pmp->pm_maxcluster)
+               pmp->pm_nxtfree = CLUST_FIRST;
+       pmp->pm_flags |= MSDOSFS_FSIMOD;
        error = fatchain(pmp, start, count, fillwith);
        if (error != 0)
                return (error);
@@ -754,9 +733,6 @@ chainalloc(pmp, start, count, fillwith, 
                *retcluster = start;
        if (got)
                *got = count;
-       pmp->pm_nxtfree = start + count;
-       if (pmp->pm_nxtfree > pmp->pm_maxcluster)
-               pmp->pm_nxtfree = CLUST_FIRST;
        return (0);
 }
 

Modified: head/sys/fs/msdosfs/msdosfs_vfsops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vfsops.c        Sun Feb 17 19:49:59 2013        
(r246920)
+++ head/sys/fs/msdosfs/msdosfs_vfsops.c        Sun Feb 17 20:35:54 2013        
(r246921)
@@ -896,6 +896,40 @@ msdosfs_statfs(struct mount *mp, struct 
        return (0);
 }
 
+/*
+ * If we have an FSInfo block, update it.
+ */
+static int
+msdosfs_fsiflush(struct msdosfsmount *pmp, int waitfor)
+{
+       struct fsinfo *fp;
+       struct buf *bp;
+       int error;
+
+       MSDOSFS_LOCK_MP(pmp);
+       if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) {
+               error = 0;
+               goto unlock;
+       }
+       error = bread(pmp->pm_devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
+           NOCRED, &bp);
+       if (error != 0) {
+               brelse(bp);
+               goto unlock;
+       }
+       fp = (struct fsinfo *)bp->b_data;
+       putulong(fp->fsinfree, pmp->pm_freeclustercount);
+       putulong(fp->fsinxtfree, pmp->pm_nxtfree);
+       pmp->pm_flags &= ~MSDOSFS_FSIMOD;
+       if (waitfor == MNT_WAIT)
+               error = bwrite(bp);
+       else
+               bawrite(bp);
+unlock:
+       MSDOSFS_UNLOCK_MP(pmp);
+       return (error);
+}
+
 static int
 msdosfs_sync(struct mount *mp, int waitfor)
 {
@@ -958,6 +992,10 @@ loop:
                        allerror = error;
                VOP_UNLOCK(pmp->pm_devvp, 0);
        }
+
+       error = msdosfs_fsiflush(pmp, waitfor);
+       if (error != 0)
+               allerror = error;
        return (allerror);
 }
 

Modified: head/sys/fs/msdosfs/msdosfsmount.h
==============================================================================
--- head/sys/fs/msdosfs/msdosfsmount.h  Sun Feb 17 19:49:59 2013        
(r246920)
+++ head/sys/fs/msdosfs/msdosfsmount.h  Sun Feb 17 20:35:54 2013        
(r246921)
@@ -262,6 +262,7 @@ struct msdosfs_args {
 #define        MSDOSFSMNT_WAITONFAT    0x40000000      /* mounted synchronous  
*/
 #define        MSDOSFS_FATMIRROR       0x20000000      /* FAT is mirrored */
 #define        MSDOSFS_LARGEFS         0x10000000      /* perform fileno 
mapping */
+#define        MSDOSFS_FSIMOD          0x01000000
 
 #define MSDOSFS_ARGSMAGIC      0xe4eff300
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to