From 5dbc679e16db124ae501861091fa7a2a45d650b0 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 5 Jul 2026 14:09:32 +0300 Subject: [PATCH] Fix padded block checksums - v2 --- src/blockstore/blockstore_heap.cpp | 3 +- src/test/test_blockstore.cpp | 71 ++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/blockstore/blockstore_heap.cpp b/src/blockstore/blockstore_heap.cpp index bd7257fa..1ab37d01 100644 --- a/src/blockstore/blockstore_heap.cpp +++ b/src/blockstore/blockstore_heap.cpp @@ -1139,7 +1139,6 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit { bool res = true; uint32_t pos = start; - uint32_t block_start = (start/dsk->csum_block_size)*dsk->csum_block_size; uint32_t block_end = (start/dsk->csum_block_size + 1)*dsk->csum_block_size; uint32_t block_crc = 0; bool isset = false; @@ -1154,7 +1153,7 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit while (pos < end && pos < block_end && !(bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8)))) pos += dsk->bitmap_granularity; // zero padding at the beginning or at the end of the block is not counted - if (pos > prev && prev > block_start && pos < block_end) + if (pos > prev && prev > blk_start && pos < block_end) block_crc = crc32c_pad(block_crc, NULL, 0, pos-prev, 0); prev = pos; while (pos < end && pos < block_end && (bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8)))) diff --git a/src/test/test_blockstore.cpp b/src/test/test_blockstore.cpp index b7df70cc..c179c394 100644 --- a/src/test/test_blockstore.cpp +++ b/src/test/test_blockstore.cpp @@ -57,6 +57,19 @@ struct bs_test_t } } + void force_compaction() + { + bs->flusher->dump_diagnostics(); + bs->flusher->request_trim(); + while (bs->heap->get_compact_queue_size()) + ringloop->loop(); + while (bs->flusher->is_active()) + ringloop->loop(); + bs->flusher->release_trim(); + // Check that compaction succeeded + assert(!bs->heap->get_to_compact_count()); + } + void default_cfg() { config["data_device"] = "./test_data.bin"; @@ -330,15 +343,7 @@ static void test_fsync(bool separate_meta) assert(is_zero(op2.buf+24*1024, 104*1024)); // Trigger & wait compaction - test.bs->flusher->dump_diagnostics(); - test.bs->flusher->request_trim(); - while (test.bs->heap->get_compact_queue_size()) - test.ringloop->loop(); - while (test.bs->flusher->is_active()) - test.ringloop->loop(); - test.bs->flusher->release_trim(); - // Check that compaction succeeded - assert(!test.bs->heap->get_to_compact_count()); + test.force_compaction(); // Restart and check data again test.destroy_bs(); @@ -447,6 +452,7 @@ static void test_padded_csum_intent(bool perfect) assert(!test.bs->heap->prev(wr)); // Trigger & wait compaction + test.bs->flusher->dump_diagnostics(); test.bs->flusher->request_trim(); while (test.bs->heap->get_compact_queue_size()) test.ringloop->loop(); @@ -666,14 +672,7 @@ static void test_compact_rollback() assert(op.retval == 0); // Trigger & wait compaction - test.bs->flusher->request_trim(); - while (test.bs->heap->get_compact_queue_size()) - test.ringloop->loop(); - while (test.bs->flusher->is_active()) - test.ringloop->loop(); - test.bs->flusher->release_trim(); - // Check that compaction succeeded - assert(!test.bs->heap->get_to_compact_count()); + test.force_compaction(); // Check that the object does not exist printf("checking that the object does not exist\n"); @@ -845,7 +844,7 @@ static void test_padded_csum_sparse_leading_hole() // Initial write at offset=20K, len=4K on a fresh object. // The csum block is [16K..32K); granule [16K..20K) is a leading hole. - printf("writing\n"); + printf("writing 20+4K\n"); blockstore_op_t op; op.opcode = BS_OP_WRITE_STABLE; op.oid = { .inode = 1, .stripe = 0 }; @@ -874,6 +873,42 @@ static void test_padded_csum_sparse_leading_hole() assert(memcheck(op2.buf+20*1024, 0xaa, 4*1024)); assert(is_zero(op2.buf+24*1024, 104*1024)); + // Part 2 - add 2 more small writes + printf("writing 24+4K\n"); + op.version = 2; + op.offset = 24*1024; + test.exec_op(&op); + assert(op.retval == op.len); + + printf("writing 36+4K\n"); + op.version = 3; + op.offset = 36*1024; + test.exec_op(&op); + assert(op.retval == op.len); + + printf("reading uncompacted\n"); + op2.version = UINT64_MAX; + test.exec_op(&op2); + assert(op2.retval == op2.len); + assert(is_zero(op2.buf, 20*1024)); + assert(memcheck(op2.buf+20*1024, 0xaa, 8*1024)); + assert(is_zero(op2.buf+28*1024, 8*1024)); + assert(memcheck(op2.buf+36*1024, 0xaa, 4*1024)); + assert(is_zero(op2.buf+40*1024, 88*1024)); + + // Trigger & wait compaction + test.force_compaction(); + + printf("reading compacted\n"); + op2.version = UINT64_MAX; + test.exec_op(&op2); + assert(op2.retval == op2.len); + assert(is_zero(op2.buf, 20*1024)); + assert(memcheck(op2.buf+20*1024, 0xaa, 8*1024)); + assert(is_zero(op2.buf+28*1024, 8*1024)); + assert(memcheck(op2.buf+36*1024, 0xaa, 4*1024)); + assert(is_zero(op2.buf+40*1024, 88*1024)); + free(op.buf); free(op2.buf); }