From 9f8c6863219089f067ae8a42117ff80072cc0b30 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sat, 7 Feb 2026 15:05:55 +0300 Subject: [PATCH] Add a test for redirect_intent --- src/test/test_heap.cpp | 130 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/src/test/test_heap.cpp b/src/test/test_heap.cpp index 864e10d3..c40ad1ca 100644 --- a/src/test/test_heap.cpp +++ b/src/test/test_heap.cpp @@ -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 buffer_area(dsk.journal_device_size); + memset(buffer_area.data(), 0xab, 4096); + memset(buffer_area.data()+4096, 0xac, 4096); + + std::vector 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 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 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; }