|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <vfs/hammer/hammer_disk.h>
|
|
|
|
/*
|
|
* mimic freemap initialization loop of
|
|
* ondisk.c:initialize_freemap
|
|
*/
|
|
static void assert_freemap_init_loop(int vol_no, hammer_off_t base,
|
|
hammer_off_t end, int debug) {
|
|
hammer_off_t layer1_base;
|
|
hammer_off_t layer1_offset = 0xDEADBEEF;
|
|
hammer_off_t phys_offset;
|
|
hammer_off_t vol_free_end;
|
|
hammer_off_t aligned_vol_free_end;
|
|
hammer_off_t tmp;
|
|
int count = 0;
|
|
|
|
layer1_base = HAMMER_ENCODE_RAW_BUFFER(0, base);
|
|
|
|
vol_free_end = HAMMER_ENCODE_RAW_BUFFER(vol_no, end
|
|
& ~HAMMER_LARGEBLOCK_MASK64);
|
|
aligned_vol_free_end = (vol_free_end + HAMMER_BLOCKMAP_LAYER2_MASK)
|
|
& ~HAMMER_BLOCKMAP_LAYER2_MASK;
|
|
|
|
if (debug) {
|
|
printf("\n");
|
|
printf("layer1_base = 0x%0lX\n", layer1_base);
|
|
printf("vol_free_end = 0x%0lX\n", vol_free_end);
|
|
printf("aligned_vol_free_end = 0x%0lX\n", aligned_vol_free_end);
|
|
}
|
|
|
|
for (phys_offset = HAMMER_ENCODE_RAW_BUFFER(vol_no, 0);
|
|
phys_offset < aligned_vol_free_end;
|
|
phys_offset += HAMMER_LARGEBLOCK_SIZE) {
|
|
|
|
if ((phys_offset % HAMMER_BLOCKMAP_LAYER2) == 0) {
|
|
/* Get layer1 when moving on to the next layer 1 */
|
|
layer1_offset = layer1_base +
|
|
HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset);
|
|
if (debug)
|
|
printf("get layer1 = 0x%0lX\n", layer1_offset);
|
|
count++;
|
|
} else {
|
|
/* We can reuse layer 1 till it hits the next one */
|
|
tmp = layer1_base +
|
|
HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset);
|
|
/* Make sure it's same as the one we already have */
|
|
assert(layer1_offset == tmp);
|
|
/* Make sure we don't come here on the first time */
|
|
assert(layer1_offset != 0xDEADBEEF);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* layer1/layer2 direct map:
|
|
* zzzzvvvvvvvvoooo oooooooooooooooo oooooooooooooooo oooooooooooooooo
|
|
* ----111111111111 1111112222222222 222222222ooooooo oooooooooooooooo
|
|
* ^^^^ ^^^^^^
|
|
* We read layer 1 for ^^^^^^^^^^ times + 1 per volume.
|
|
* e.g. Maximum will be 2^10 = 1024 times per volume
|
|
* e.g. Minimum will be 1 time per volume
|
|
* e.g. If the volume size is < 4TB it reads layer 1 only
|
|
* once per volume.
|
|
*/
|
|
vol_free_end &= 0x000FFFFFFFFFFFFF;
|
|
vol_free_end >>= 42;
|
|
assert(count == vol_free_end + 1);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
int i, debug = 0;
|
|
hammer_off_t base, end;
|
|
|
|
if (argc > 1)
|
|
debug = 1;
|
|
|
|
/* HAMMER_BLOCKMAP_LAYER1_OFFSET() gets +sizeof(layer1) every 4TB */
|
|
assert((HAMMER_BLOCKMAP_LAYER2 >> 42) == 1);
|
|
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(0) == 0);
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 - 1)
|
|
== 0);
|
|
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2)
|
|
== sizeof(struct hammer_blockmap_layer1));
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 + 1)
|
|
== sizeof(struct hammer_blockmap_layer1));
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 * 2 - 1)
|
|
== sizeof(struct hammer_blockmap_layer1));
|
|
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 * 2)
|
|
== sizeof(struct hammer_blockmap_layer1) * 2);
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 * 2 + 1)
|
|
== sizeof(struct hammer_blockmap_layer1) * 2);
|
|
assert(HAMMER_BLOCKMAP_LAYER1_OFFSET(HAMMER_BLOCKMAP_LAYER2 * 3 - 1)
|
|
== sizeof(struct hammer_blockmap_layer1) * 2);
|
|
|
|
base = 0x0; /* use 0 for freemap zone offset */
|
|
end = 0xFFFFFFFFFFFFFFFF; /* just pass maximum possible */
|
|
|
|
/* Freemap init assertions are based on above behavior */
|
|
for (i = 0; i < 256; i++) {
|
|
assert_freemap_init_loop(i, base, end, debug);
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
|
|
printf("\n");
|
|
printf("success\n");
|
|
return 0;
|
|
}
|