DragonFlyBSD Kernel Audit
DF-2652 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer2/hammer2_freemap.c
+++ b/sys/vfs/hammer2/hammer2_freemap.c
@@ -1070,7 +1070,15 @@
 	/*
 	 * Calculate the bitmask (runs in 2-bit pairs).
 	 */
-	start = ((int)(data_off >> HAMMER2_FREEMAP_BLOCK_RADIX) & 15) * 2;
+	/*
+	 * DF-2652: each bitmapq[] element covers 32 x 16KB blocks
+	 * (HAMMER2_BMAP_BLOCKS_PER_ELEMENT), so the block number within
+	 * the element is 5 bits, not 4.  The old '& 15' made every
+	 * recovery/dedup fixup for blocks 16..31 of a 512KB element mark
+	 * the wrong 16KB chunk, leaving live blocks marked free.
+	 */
+	start = ((int)(data_off >> HAMMER2_FREEMAP_BLOCK_RADIX) &
+		 (HAMMER2_BMAP_BLOCKS_PER_ELEMENT - 1)) * 2;
 	//bmmask01 = (hammer2_bitmap_t)1 << start;
 	//bmmask10 = (hammer2_bitmap_t)2 << start;
 	bmmask11 = (hammer2_bitmap_t)3 << start;