}
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
/*
* 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;
}
/*
- * 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,
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);
#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;
};