HAMMER VFS - Adjust signedness of a media field for future de-dup
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 13 Aug 2010 02:02:34 +0000 (19:02 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 13 Aug 2010 02:02:34 +0000 (19:02 -0700)
* Make bytes_free in hammer_blockmap_layer2 a signed field and remove
  KKASSERT() that disallowed a negative value.

  This field can go negative in a future data de-dup implementation.

sys/vfs/hammer/hammer_blockmap.c
sys/vfs/hammer/hammer_disk.h

index 89b5dce..a657355 100644 (file)
@@ -332,12 +332,14 @@ again:
        }
        KKASSERT(layer2->zone == zone);
 
+       /*
+        * NOTE: bytes_free can legally go negative due to de-dup.
+        */
        layer2->bytes_free -= bytes;
        KKASSERT(layer2->append_off <= offset);
        layer2->append_off = offset + bytes;
        layer2->entry_crc = crc32(layer2, HAMMER_LAYER2_CRCSIZE);
        hammer_modify_buffer_done(buffer2);
-       KKASSERT(layer2->bytes_free >= 0);
 
        /*
         * We hold the blockmap lock and should be the only ones
@@ -825,6 +827,9 @@ hammer_blockmap_free(hammer_transaction_t trans,
 
        /*
         * Free space previously allocated via blockmap_alloc().
+        *
+        * NOTE: bytes_free can be and remain negative due to de-dup ops
+        *       but can never become larger than HAMMER_LARGEBLOCK_SIZE.
         */
        KKASSERT(layer2->zone == zone);
        layer2->bytes_free += bytes;
@@ -1013,8 +1018,14 @@ failed:
 }
 
 /*
- * Return the number of free bytes in the big-block containing the
- * specified blockmap offset.
+ * Return the approximate number of free bytes in the big-block
+ * containing the specified blockmap offset.
+ *
+ * WARNING: A negative number can be returned if data de-dup exists,
+ *         and the result will also not represent he actual number
+ *         of free bytes in this case.
+ *
+ *         This code is used only by the reblocker.
  */
 int
 hammer_blockmap_getfree(hammer_mount_t hmp, hammer_off_t zone_offset,
@@ -1028,7 +1039,7 @@ hammer_blockmap_getfree(hammer_mount_t hmp, hammer_off_t zone_offset,
        hammer_buffer_t buffer = NULL;
        hammer_off_t layer1_offset;
        hammer_off_t layer2_offset;
-       int bytes;
+       int32_t bytes;
        int zone;
 
        zone = HAMMER_ZONE_DECODE(zone_offset);
index 7d6ddfa..74c58db 100644 (file)
@@ -287,12 +287,20 @@ typedef struct hammer_blockmap_layer1 *hammer_blockmap_layer1_t;
 #define HAMMER_LAYER1_CRCSIZE  \
        offsetof(struct hammer_blockmap_layer1, layer1_crc)
 
+/*
+ * layer2 entry for 8MB bigblock.
+ *
+ * NOTE: bytes_free is signed and can legally go negative if/when data
+ *      de-dup occurs.  This field will never go higher than
+ *      HAMMER_LARGEBLOCK_SIZE.  If exactly HAMMER_LARGEBLOCK_SIZE
+ *      the big-block is completely free.
+ */
 struct hammer_blockmap_layer2 {
        u_int8_t        zone;           /* typed allocation zone */
        u_int8_t        unused01;
        u_int16_t       unused02;
        u_int32_t       append_off;     /* allocatable space index */
-       u_int32_t       bytes_free;     /* bytes free within this bigblock */
+       int32_t         bytes_free;     /* bytes free within this bigblock */
        hammer_crc_t    entry_crc;
 };