Author: kib
Date: Sun Feb 28 17:13:59 2010
New Revision: 204471
URL: http://svn.freebsd.org/changeset/base/204471

Log:
  Use pm_fatlock to protect fat bitmap.
  
  Tested by:    pho
  MFC after:    3 weeks

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

Modified: head/sys/fs/msdosfs/msdosfs_fat.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_fat.c   Sun Feb 28 17:13:07 2010        
(r204470)
+++ head/sys/fs/msdosfs/msdosfs_fat.c   Sun Feb 28 17:13:59 2010        
(r204471)
@@ -77,6 +77,9 @@ static __inline void
                usemap_alloc(struct msdosfsmount *pmp, u_long cn);
 static __inline void
                usemap_free(struct msdosfsmount *pmp, u_long cn);
+static int     clusteralloc1(struct msdosfsmount *pmp, u_long start,
+                   u_long count, u_long fillwith, u_long *retcluster,
+                   u_long *got);
 
 static void
 fatblock(pmp, ofs, bnp, sizep, bop)
@@ -409,6 +412,7 @@ usemap_alloc(pmp, cn)
        u_long cn;
 {
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
        pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
        pmp->pm_freeclustercount--;
 }
@@ -419,6 +423,7 @@ usemap_free(pmp, cn)
        u_long cn;
 {
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
        pmp->pm_freeclustercount++;
        pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
 }
@@ -432,17 +437,17 @@ clusterfree(pmp, cluster, oldcnp)
        int error;
        u_long oldcn;
 
-       usemap_free(pmp, cluster);
        error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
-       if (error) {
-               usemap_alloc(pmp, cluster);
+       if (error)
                return (error);
-       }
        /*
         * If the cluster was successfully marked free, then update
         * the count of free clusters, and turn off the "allocated"
         * bit in the "in use" cluster bit map.
         */
+       MSDOSFS_LOCK_MP(pmp);
+       usemap_free(pmp, cluster);
+       MSDOSFS_UNLOCK_MP(pmp);
        if (oldcnp)
                *oldcnp = oldcn;
        return (0);
@@ -660,6 +665,8 @@ chainlength(pmp, start, count)
        u_int map;
        u_long len;
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
        max_idx = pmp->pm_maxcluster / N_INUSEBITS;
        idx = start / N_INUSEBITS;
        start %= N_INUSEBITS;
@@ -708,6 +715,8 @@ chainalloc(pmp, start, count, fillwith, 
        int error;
        u_long cl, n;
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
        for (cl = start, n = count; n-- > 0;)
                usemap_alloc(pmp, cl++);
 
@@ -740,19 +749,28 @@ chainalloc(pmp, start, count, fillwith, 
  * got       - how many clusters were actually allocated.
  */
 int
-clusteralloc(pmp, start, count, fillwith, retcluster, got)
-       struct msdosfsmount *pmp;
-       u_long start;
-       u_long count;
-       u_long fillwith;
-       u_long *retcluster;
-       u_long *got;
+clusteralloc(struct msdosfsmount *pmp, u_long start, u_long count,
+    u_long fillwith, u_long *retcluster, u_long *got)
+{
+       int error;
+
+       MSDOSFS_LOCK_MP(pmp);
+       error = clusteralloc1(pmp, start, count, fillwith, retcluster, got);
+       MSDOSFS_UNLOCK_MP(pmp);
+       return (error);
+}
+
+static int
+clusteralloc1(struct msdosfsmount *pmp, u_long start, u_long count,
+    u_long fillwith, u_long *retcluster, u_long *got)
 {
        u_long idx;
        u_long len, newst, foundl, cn, l;
        u_long foundcn = 0; /* XXX: foundcn could be used unititialized */
        u_int map;
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
 #ifdef MSDOSFS_DEBUG
        printf("clusteralloc(): find %lu clusters\n", count);
 #endif
@@ -828,6 +846,7 @@ freeclusterchain(pmp, cluster)
        u_long bn, bo, bsize, byteoffset;
        u_long readcn, lbn = -1;
 
+       MSDOSFS_LOCK_MP(pmp);
        while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
                byteoffset = FATOFS(pmp, cluster);
                fatblock(pmp, byteoffset, &bn, &bsize, &bo);
@@ -837,6 +856,7 @@ freeclusterchain(pmp, cluster)
                        error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
                        if (error) {
                                brelse(bp);
+                               MSDOSFS_UNLOCK_MP(pmp);
                                return (error);
                        }
                        lbn = bn;
@@ -872,6 +892,7 @@ freeclusterchain(pmp, cluster)
        }
        if (bp)
                updatefats(pmp, bp, bn);
+       MSDOSFS_UNLOCK_MP(pmp);
        return (0);
 }
 
@@ -888,6 +909,8 @@ fillinusemap(pmp)
        int error;
        u_long bn, bo, bsize, byteoffset;
 
+       MSDOSFS_ASSERT_MP_LOCKED(pmp);
+
        /*
         * Mark all clusters in use, we mark the free ones in the fat scan
         * loop further down.

Modified: head/sys/fs/msdosfs/msdosfs_vfsops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vfsops.c        Sun Feb 28 17:13:07 2010        
(r204470)
+++ head/sys/fs/msdosfs/msdosfs_vfsops.c        Sun Feb 28 17:13:59 2010        
(r204471)
@@ -720,7 +720,10 @@ mountmsdosfs(struct vnode *devvp, struct
        /*
         * Have the inuse map filled in.
         */
-       if ((error = fillinusemap(pmp)) != 0)
+       MSDOSFS_LOCK_MP(pmp);
+       error = fillinusemap(pmp);
+       MSDOSFS_UNLOCK_MP(pmp);
+       if (error != 0)
                goto error_exit;
 
        /*
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to