Fix padded block checksums - v2

This commit is contained in:
Vitaliy Filippov
2026-07-05 14:09:57 +03:00
parent d48864a6be
commit 5dbc679e16
2 changed files with 54 additions and 20 deletions
+1 -2
View File
@@ -1139,7 +1139,6 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
{ {
bool res = true; bool res = true;
uint32_t pos = start; 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_end = (start/dsk->csum_block_size + 1)*dsk->csum_block_size;
uint32_t block_crc = 0; uint32_t block_crc = 0;
bool isset = false; 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)))) while (pos < end && pos < block_end && !(bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8))))
pos += dsk->bitmap_granularity; pos += dsk->bitmap_granularity;
// zero padding at the beginning or at the end of the block is not counted // 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); block_crc = crc32c_pad(block_crc, NULL, 0, pos-prev, 0);
prev = pos; prev = pos;
while (pos < end && pos < block_end && (bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8)))) while (pos < end && pos < block_end && (bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8))))
+53 -18
View File
@@ -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() void default_cfg()
{ {
config["data_device"] = "./test_data.bin"; 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)); assert(is_zero(op2.buf+24*1024, 104*1024));
// Trigger & wait compaction // Trigger & wait compaction
test.bs->flusher->dump_diagnostics(); test.force_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());
// Restart and check data again // Restart and check data again
test.destroy_bs(); test.destroy_bs();
@@ -447,6 +452,7 @@ static void test_padded_csum_intent(bool perfect)
assert(!test.bs->heap->prev(wr)); assert(!test.bs->heap->prev(wr));
// Trigger & wait compaction // Trigger & wait compaction
test.bs->flusher->dump_diagnostics();
test.bs->flusher->request_trim(); test.bs->flusher->request_trim();
while (test.bs->heap->get_compact_queue_size()) while (test.bs->heap->get_compact_queue_size())
test.ringloop->loop(); test.ringloop->loop();
@@ -666,14 +672,7 @@ static void test_compact_rollback()
assert(op.retval == 0); assert(op.retval == 0);
// Trigger & wait compaction // Trigger & wait compaction
test.bs->flusher->request_trim(); test.force_compaction();
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());
// Check that the object does not exist // Check that the object does not exist
printf("checking that the object does not exist\n"); 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. // Initial write at offset=20K, len=4K on a fresh object.
// The csum block is [16K..32K); granule [16K..20K) is a leading hole. // 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; blockstore_op_t op;
op.opcode = BS_OP_WRITE_STABLE; op.opcode = BS_OP_WRITE_STABLE;
op.oid = { .inode = 1, .stripe = 0 }; 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(memcheck(op2.buf+20*1024, 0xaa, 4*1024));
assert(is_zero(op2.buf+24*1024, 104*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(op.buf);
free(op2.buf); free(op2.buf);
} }