Add a test for redirect_intent
This commit is contained in:
+129
-1
@@ -1871,8 +1871,135 @@ void test_recalc_stats()
|
||||
printf("OK test_recalc_stats\n");
|
||||
}
|
||||
|
||||
void test_redirect_intent_csums()
|
||||
{
|
||||
blockstore_disk_t dsk;
|
||||
_test_init(dsk, true /*csum*/);
|
||||
dsk.disable_journal_fsync = dsk.disable_meta_fsync = false;
|
||||
std::vector<uint8_t> buffer_area(dsk.journal_device_size);
|
||||
memset(buffer_area.data(), 0xab, 4096);
|
||||
memset(buffer_area.data()+4096, 0xac, 4096);
|
||||
|
||||
std::vector<uint8_t> tmp;
|
||||
|
||||
{
|
||||
blockstore_heap_t heap(&dsk, buffer_area.data());
|
||||
heap.finish_load();
|
||||
|
||||
_test_big_write(heap, dsk, 1, 0, 1, 0x20000, true, 0, 4096, buffer_area.data());
|
||||
|
||||
uint32_t mblock = 999999;
|
||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||
uint8_t ext_bitmap[dsk.clean_entry_bitmap_size];
|
||||
memset(ext_bitmap, 0x8e, dsk.clean_entry_bitmap_size);
|
||||
heap_entry_t *obj = heap.read_entry(oid);
|
||||
int res = heap.add_redirect_intent(oid, &obj, 2, 32768, 4096, 0x40000, ext_bitmap, buffer_area.data()+4096, &mblock);
|
||||
assert(res == 0);
|
||||
assert(mblock == 0);
|
||||
heap.start_block_write(mblock);
|
||||
heap.complete_block_write(mblock);
|
||||
|
||||
// persist
|
||||
assert(heap.get_meta_block_used_space(0) > 0);
|
||||
tmp.resize(dsk.meta_block_size);
|
||||
heap.get_meta_block(0, tmp.data());
|
||||
}
|
||||
|
||||
// reload heap to check that the write is still here
|
||||
{
|
||||
blockstore_heap_t heap(&dsk, buffer_area.data(), 10);
|
||||
uint64_t entries_loaded;
|
||||
heap.load_blocks(0, dsk.meta_block_size, tmp.data(), false, entries_loaded);
|
||||
|
||||
int calls = 0;
|
||||
bool done = heap.recheck_small_writes([&](bool is_data, uint64_t offset, uint64_t len, uint8_t *buf, std::function<void()> cb)
|
||||
{
|
||||
calls++;
|
||||
if (len)
|
||||
{
|
||||
assert(is_data);
|
||||
assert(offset == 0x40000+32768 && len == 4096);
|
||||
memcpy(buf, buffer_area.data()+4096, len);
|
||||
assert(cb);
|
||||
cb();
|
||||
}
|
||||
}, 1);
|
||||
assert(done);
|
||||
assert(calls == 2);
|
||||
|
||||
heap.finish_load();
|
||||
|
||||
auto mod = heap.get_recheck_modified_blocks();
|
||||
assert(mod.size() == 0);
|
||||
|
||||
// read object 1 - big_intent should be there
|
||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||
heap_entry_t *obj = heap.read_entry(oid);
|
||||
assert(obj);
|
||||
assert(count_writes(heap, obj) == 2);
|
||||
assert(obj->lsn == 2);
|
||||
assert(obj->entry_type == BS_HEAP_BIG_INTENT|BS_HEAP_STABLE);
|
||||
assert(obj->version == 2);
|
||||
assert(obj->big_location(&heap) == 0x40000);
|
||||
|
||||
// verify csums
|
||||
uint32_t ref_csums[dsk.data_block_size/4096];
|
||||
memset(ref_csums, 0, dsk.data_block_size/4096*4);
|
||||
ref_csums[8] = crc32c(0, buffer_area.data()+4096, 4096);
|
||||
assert(!memcmp(obj->get_checksums(&heap), ref_csums, dsk.data_block_size/dsk.csum_block_size*4));
|
||||
|
||||
// verify bitmap
|
||||
uint8_t ref_bmp[dsk.clean_entry_bitmap_size];
|
||||
memset(ref_bmp, 0, dsk.clean_entry_bitmap_size);
|
||||
bitmap_set(ref_bmp, 32768, 4096, 4096);
|
||||
assert(!memcmp(obj->get_int_bitmap(&heap), ref_bmp, dsk.clean_entry_bitmap_size));
|
||||
|
||||
uint8_t ext_bitmap[dsk.clean_entry_bitmap_size];
|
||||
memset(ext_bitmap, 0x8e, dsk.clean_entry_bitmap_size);
|
||||
assert(!memcmp(obj->get_ext_bitmap(&heap), ext_bitmap, dsk.clean_entry_bitmap_size));
|
||||
}
|
||||
|
||||
// reload heap to check that the write is removed if data is invalid
|
||||
{
|
||||
blockstore_heap_t heap(&dsk, buffer_area.data(), 10);
|
||||
uint64_t entries_loaded;
|
||||
heap.load_blocks(0, dsk.meta_block_size, tmp.data(), false, entries_loaded);
|
||||
|
||||
int calls = 0;
|
||||
bool done = heap.recheck_small_writes([&](bool is_data, uint64_t offset, uint64_t len, uint8_t *buf, std::function<void()> cb)
|
||||
{
|
||||
calls++;
|
||||
if (len)
|
||||
{
|
||||
memset(buf, 0xaa, len);
|
||||
assert(cb);
|
||||
cb();
|
||||
}
|
||||
}, 1);
|
||||
assert(done);
|
||||
assert(calls == 2);
|
||||
|
||||
heap.finish_load();
|
||||
|
||||
auto mod = heap.get_recheck_modified_blocks();
|
||||
assert(mod.size() == 1);
|
||||
assert(mod[0] == 0);
|
||||
|
||||
// read object 1 - big_intent should be absent
|
||||
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||
heap_entry_t *obj = heap.read_entry(oid);
|
||||
assert(obj);
|
||||
assert(count_writes(heap, obj) == 1);
|
||||
assert(obj->lsn == 1);
|
||||
assert(obj->entry_type == BS_HEAP_BIG_WRITE|BS_HEAP_STABLE);
|
||||
assert(obj->version == 1);
|
||||
assert(obj->big_location(&heap) == 0x20000);
|
||||
}
|
||||
|
||||
printf("OK test_redirect_intent_csums\n");
|
||||
}
|
||||
|
||||
// FIXME: Add a test for big_intent, incl. explicit_complete with big_intent over big_write over deletion over big_write :)
|
||||
// FIXME: Add a test for redirect_intent
|
||||
|
||||
int main(int narg, char *args[])
|
||||
{
|
||||
@@ -1909,5 +2036,6 @@ int main(int narg, char *args[])
|
||||
test_intent_write(false);
|
||||
test_big_intent_csums();
|
||||
test_recalc_stats();
|
||||
test_redirect_intent_csums();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user