⬢ DragonFlyBSD Kernel Audit
DF-3093 / instr.patch
← back to finding ↓ download raw
--- a/sys/vfs/msdosfs/msdosfs_fat.c
+++ b/sys/vfs/msdosfs/msdosfs_fat.c
@@ -55,18 +55,30 @@
 #include <sys/buf.h>
 #include <sys/mount.h>
 #include <sys/vnode.h>
 
 #include <sys/buf2.h>
+#include <sys/sysctl.h>
 
 #include <vfs/msdosfs/bpb.h>
 #include <vfs/msdosfs/direntry.h>
 #include <vfs/msdosfs/denode.h>
 #include <vfs/msdosfs/fat.h>
 #include <vfs/msdosfs/msdosfsmount.h>
 
 #define	FULL_RUN	((u_int)0xffffffff)
+
+/* DF-3093 instrumentation (diagnostic build only) */
+static int df3093_inflight = 0;
+static long df3093_overlaps = 0;
+static long df3093_double = 0;
+SYSCTL_INT(_debug, OID_AUTO, df3093_inflight, CTLFLAG_RD, &df3093_inflight, 0,
+    "DFDBG concurrent clusteralloc depth");
+SYSCTL_LONG(_debug, OID_AUTO, df3093_overlaps, CTLFLAG_RD, &df3093_overlaps, 0,
+    "DFDBG clusteralloc overlap events");
+SYSCTL_LONG(_debug, OID_AUTO, df3093_double, CTLFLAG_RD, &df3093_double, 0,
+    "DFDBG double usemap_alloc events");
 
 static void	fc_lookup(struct denode *dep, u_long findcn, u_long *frcnp,
 		    u_long *fsrcnp);
 static int	clusteralloc1(struct msdosfsmount *pmp, u_long start,
 		    u_long count, u_long fillwith, u_long *retcluster,
@@ -370,10 +382,19 @@
  *
  */
 static __inline void
 usemap_alloc(struct msdosfsmount *pmp, u_long cn)
 {
+	/* DF-3093 instrumentation: INVARIANTS KASSERT, print-only form */
+	if (pmp->pm_inusemap[cn / N_INUSEBITS] &
+	    (1U << (cn % N_INUSEBITS))) {
+		atomic_fetchadd_long(&df3093_double, 1);
+		if (df3093_double < 200)
+			kprintf("DFDBG: DOUBLE usemap_alloc cn=%lu max=%lu\n",
+			    cn, pmp->pm_maxcluster);
+	}
+
 	MSDOSFS_ASSERT_MP_LOCKED(pmp);
 
 	KASSERT(cn <= pmp->pm_maxcluster, ("cn too large %lu %lu", cn,
 	    pmp->pm_maxcluster));
 	KASSERT((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0,
@@ -725,14 +746,20 @@
 int
 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);
+	int ent = atomic_fetchadd_int(&df3093_inflight, 1) + 1;
+
+	if (ent > 1) {
+		atomic_fetchadd_long(&df3093_overlaps, 1);
+		if (df3093_overlaps < 200)
+			kprintf("DFDBG: clusteralloc overlap depth=%d "
+			    "count=%lu\n", ent, count);
+	}
 	error = clusteralloc1(pmp, start, count, fillwith, retcluster, got);
-	MSDOSFS_UNLOCK_MP(pmp);
+	atomic_subtract_int(&df3093_inflight, 1);
 	return (error);
 }
 
 static int
 clusteralloc1(struct msdosfsmount *pmp, u_long start, u_long count,