The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2c9a1c22c323b069d1f4883170349545c94b7b8d

commit 2c9a1c22c323b069d1f4883170349545c94b7b8d
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-12-25 18:39:15 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2022-01-08 03:41:44 +0000

    msdosfs: take inusemap inconsistency as an error, not invariants violation
    
    In other words, stop silently accepting freeing free cluster in
    non-debug kernels, but return the error to the caller.  Modify callers
    to handle errors from usemap_free().
    
    In collaboration with:  pho
    Reviewed by:    markj, mckusick
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D33721
---
 sys/fs/msdosfs/msdosfs_fat.c | 41 +++++++++++++++++++++++++++--------------
 1 file changed, 27 insertions(+), 14 deletions(-)

diff --git a/sys/fs/msdosfs/msdosfs_fat.c b/sys/fs/msdosfs/msdosfs_fat.c
index 6d5bfc7fa46e..202feeef0102 100644
--- a/sys/fs/msdosfs/msdosfs_fat.c
+++ b/sys/fs/msdosfs/msdosfs_fat.c
@@ -80,8 +80,7 @@ static void   updatefats(struct msdosfsmount *pmp, struct buf 
*bp,
                    u_long fatbn);
 static __inline void
                usemap_alloc(struct msdosfsmount *pmp, u_long cn);
-static __inline void
-               usemap_free(struct msdosfsmount *pmp, u_long cn);
+static int     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);
@@ -398,7 +397,7 @@ usemap_alloc(struct msdosfsmount *pmp, u_long cn)
        pmp->pm_flags |= MSDOSFS_FSIMOD;
 }
 
-static __inline void
+static int
 usemap_free(struct msdosfsmount *pmp, u_long cn)
 {
 
@@ -408,13 +407,17 @@ usemap_free(struct msdosfsmount *pmp, u_long cn)
            pmp->pm_maxcluster));
        KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
            ("usemap_free on ro msdosfs mount"));
+       if ((pmp->pm_inusemap[cn / N_INUSEBITS] &
+           (1U << (cn % N_INUSEBITS))) == 0) {
+               printf("%s: Freeing unused sector %ld %ld %x\n",
+                   pmp->pm_mountp->mnt_stat.f_mntonname, cn, cn % N_INUSEBITS,
+                   (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]);
+               return (EINTEGRITY);
+       }
        pmp->pm_freeclustercount++;
        pmp->pm_flags |= MSDOSFS_FSIMOD;
-       KASSERT((pmp->pm_inusemap[cn / N_INUSEBITS] &
-           (1U << (cn % N_INUSEBITS))) != 0,
-           ("Freeing unused sector %ld %ld %x", cn, cn % N_INUSEBITS,
-           (unsigned)pmp->pm_inusemap[cn / N_INUSEBITS]));
        pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1U << (cn % N_INUSEBITS));
+       return (0);
 }
 
 int
@@ -432,11 +435,11 @@ clusterfree(struct msdosfsmount *pmp, u_long cluster, 
u_long *oldcnp)
         * bit in the "in use" cluster bit map.
         */
        MSDOSFS_LOCK_MP(pmp);
-       usemap_free(pmp, cluster);
+       error = usemap_free(pmp, cluster);
        MSDOSFS_UNLOCK_MP(pmp);
-       if (oldcnp)
+       if (error == 0 && oldcnp != NULL)
                *oldcnp = oldcn;
-       return (0);
+       return (error);
 }
 
 /*
@@ -712,7 +715,7 @@ chainalloc(struct msdosfsmount *pmp, u_long start, u_long 
count,
        error = fatchain(pmp, start, count, fillwith);
        if (error != 0) {
                for (cl = start, n = count; n-- > 0;)
-                       usemap_free(pmp, cl++);
+                       (void)usemap_free(pmp, cl++);
                return (error);
        }
 #ifdef MSDOSFS_DEBUG
@@ -846,7 +849,12 @@ freeclusterchain(struct msdosfsmount *pmp, u_long cluster)
                        }
                        lbn = bn;
                }
-               usemap_free(pmp, cluster);
+               error = usemap_free(pmp, cluster);
+               if (error != 0) {
+                       updatefats(pmp, bp, lbn);
+                       MSDOSFS_UNLOCK_MP(pmp);
+                       return (error);
+               }
                switch (pmp->pm_fatmask) {
                case FAT12_MASK:
                        readcn = getushort(bp->b_data + bo);
@@ -940,8 +948,13 @@ fillinusemap(struct msdosfsmount *pmp)
 #endif
                        brelse(bp);
                        return (EINVAL);
-               } else if (readcn == CLUST_FREE)
-                       usemap_free(pmp, cn);
+               } else if (readcn == CLUST_FREE) {
+                       error = usemap_free(pmp, cn);
+                       if (error != 0) {
+                               brelse(bp);
+                               return (error);
+                       }
+               }
        }
        if (bp != NULL)
                brelse(bp);

Reply via email to