From 320a5c59a1e83c4392b5d5efba75163a286bd94c Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 12 Aug 2010 19:02:34 -0700 Subject: [PATCH] HAMMER VFS - Adjust signedness of a media field for future de-dup * 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 | 19 +++++++++++++++---- sys/vfs/hammer/hammer_disk.h | 10 +++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sys/vfs/hammer/hammer_blockmap.c b/sys/vfs/hammer/hammer_blockmap.c index 89b5dce..a657355 100644 --- a/sys/vfs/hammer/hammer_blockmap.c +++ b/sys/vfs/hammer/hammer_blockmap.c @@ -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); diff --git a/sys/vfs/hammer/hammer_disk.h b/sys/vfs/hammer/hammer_disk.h index 7d6ddfa..74c58db 100644 --- a/sys/vfs/hammer/hammer_disk.h +++ b/sys/vfs/hammer/hammer_disk.h @@ -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; }; -- 1.7.7.2