Fix checksum padding during flush

This commit is contained in:
Vitaliy Filippov
2025-12-02 01:52:12 +03:00
parent 57d83ecf7c
commit 4a0720a231
3 changed files with 48 additions and 65 deletions
+45 -61
View File
@@ -342,6 +342,13 @@ resume_24:
{
return false;
}
// Recheck the object because it could be invalidated again
cur_obj = bs->heap->read_entry(cur_oid, &modified_block);
if (!cur_obj)
{
// Abort compaction
goto resume_0;
}
}
bs->heap->mark_object_compacted(cur_obj, compact_lsn);
// Done
@@ -370,83 +377,53 @@ resume_15:
goto resume_0;
}
void journal_flusher_co::iterate_partial_overwrites(std::function<int(int, uint32_t, uint32_t)> cb)
void journal_flusher_co::iterate_checksum_holes(std::function<void(int & pos, uint32_t hole_start, uint32_t hole_end)> cb)
{
int prev = 0;
uint32_t prev_begin = 0, prev_end = 0;
for (int i = 0; i < read_vec.size() && !(read_vec[i].copy_flags & COPY_BUF_CSUM_FILL); i++)
bs->find_holes(read_vec, 0, bs->dsk.data_block_size, [&](int & pos, uint32_t hole_start, uint32_t hole_end)
{
if (!(read_vec[i].copy_flags & COPY_BUF_COALESCED))
if (hole_start % bs->dsk.csum_block_size)
{
if (read_vec[i].offset > prev_end)
{
if (prev_end > prev_begin &&
((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start ||
(prev_end % bs->dsk.csum_block_size) && prev_end < big_end))
{
i += cb(prev, prev_begin, prev_end);
}
prev = i;
prev_begin = read_vec[i].offset;
}
prev_end = read_vec[i].offset + read_vec[i].len;
uint32_t blk_end = hole_start - (hole_start % bs->dsk.csum_block_size) + bs->dsk.csum_block_size;
cb(pos, hole_start, hole_end < blk_end ? hole_end : blk_end);
}
}
if (prev_end > prev_begin &&
((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start ||
(prev_end % bs->dsk.csum_block_size) && prev_end < big_end))
{
cb(prev, prev_begin, prev_end);
}
}
void journal_flusher_co::iterate_checksum_holes(std::function<void(int, uint32_t, uint32_t)> cb)
{
iterate_partial_overwrites([&](int pos, uint32_t prev_begin, uint32_t prev_end)
{
int r = 0;
if ((prev_begin % bs->dsk.csum_block_size) && prev_begin > big_start &&
(prev_begin / bs->dsk.csum_block_size) != (prev_end / bs->dsk.csum_block_size))
if ((hole_end % bs->dsk.csum_block_size) &&
(!(hole_start % bs->dsk.csum_block_size) || (hole_end / bs->dsk.csum_block_size) != (hole_start / bs->dsk.csum_block_size)))
{
uint32_t blk_begin = (prev_begin - prev_begin%bs->dsk.csum_block_size);
if (blk_begin < big_start)
blk_begin = big_start;
cb(pos++, blk_begin, prev_begin);
r++;
cb(pos, hole_end - (hole_end % bs->dsk.csum_block_size), hole_end);
}
if ((prev_end % bs->dsk.csum_block_size) && prev_end < big_end)
{
uint32_t blk_end = prev_end - (prev_end % bs->dsk.csum_block_size) + bs->dsk.csum_block_size;
if (blk_end > big_end)
blk_end = big_end;
cb(++pos, prev_end, blk_end);
r++;
}
return r;
});
}
void journal_flusher_co::fill_partial_checksum_blocks()
{
iterate_checksum_holes([&](int vec_pos, uint32_t hole_start, uint32_t hole_end)
iterate_checksum_holes([&](int & vec_pos, uint32_t hole_start, uint32_t hole_end)
{
read_to_fill_incomplete = true;
uint32_t blk_begin = (hole_start - hole_start % bs->dsk.csum_block_size);
bs->prepare_disk_read(read_vec, read_vec.size(), cur_obj, end_wr,
blk_begin < big_start ? big_start : blk_begin,
(blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size),
blk_begin < big_start ? big_start : blk_begin,
(blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size),
COPY_BUF_CSUM_FILL | (bs->perfect_csum_update ? 0 : COPY_BUF_SKIP_CSUM));
blk_begin = (blk_begin < big_start ? big_start : blk_begin);
uint32_t blk_end = (blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size);
uint32_t copy_flags = COPY_BUF_CSUM_FILL | (bs->perfect_csum_update ? 0 : COPY_BUF_SKIP_CSUM);
if (!read_vec.size() || read_vec.back().copy_flags != copy_flags ||
read_vec.back().offset != blk_begin || read_vec.back().len != blk_end-blk_begin)
{
read_vec.push_back((copy_buffer_t){
.copy_flags = COPY_BUF_DATA | copy_flags,
.offset = blk_begin,
.len = blk_end - blk_begin,
.disk_offset = end_wr->location + blk_begin,
.disk_len = blk_end - blk_begin,
.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, blk_end - blk_begin),
.wr_lsn = end_wr->lsn,
});
}
auto & vec = read_vec[read_vec.size()-1];
if (!vec.buf)
vec.buf = (uint8_t*)memalign_or_die(MEM_ALIGNMENT, vec.disk_len);
read_vec.insert(read_vec.begin()+vec_pos, (copy_buffer_t){
.copy_flags = COPY_BUF_JOURNAL|COPY_BUF_COALESCED,
.offset = hole_start,
.len = hole_end-hole_start,
.len = hole_end - hole_start,
.buf = vec.buf + hole_start - vec.offset,
});
vec_pos++;
});
}
@@ -525,11 +502,18 @@ int journal_flusher_co::check_and_punch_checksums()
uint8_t *bmp = end_wr->get_int_bitmap(bs->heap);
uint8_t *csums = end_wr->get_checksums(bs->heap);
// Clear bits
iterate_partial_overwrites([&](int pos, uint32_t start, uint32_t end)
for (auto & vec: read_vec)
{
bitmap_clear(bmp, start, end-start, bs->dsk.bitmap_granularity);
return 0;
});
if (vec.copy_flags & COPY_BUF_CSUM_FILL)
{
break;
}
if (!(vec.copy_flags & COPY_BUF_COALESCED) &&
((vec.offset % bs->dsk.csum_block_size) || (vec.len % bs->dsk.csum_block_size)))
{
bitmap_clear(bmp, vec.offset, vec.len, bs->dsk.bitmap_granularity);
}
}
// Update partial block checksums
for (auto & vec: read_vec)
{
+1 -2
View File
@@ -60,8 +60,7 @@ class journal_flusher_co
friend class journal_flusher_t;
void iterate_partial_overwrites(std::function<int(int, uint32_t, uint32_t)> cb);
void iterate_checksum_holes(std::function<void(int, uint32_t, uint32_t)> cb);
void iterate_checksum_holes(std::function<void(int & pos, uint32_t hole_start, uint32_t hole_end)> cb);
void fill_partial_checksum_blocks();
void free_buffers();
int check_and_punch_checksums();
+2 -2
View File
@@ -661,9 +661,9 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
bool isset = false;
while (pos < end)
{
uint32_t prev = pos;
if (bitmap)
{
uint32_t prev = pos;
while (pos < end && pos < block_end)
{
while (pos < end && pos < block_end && !(bitmap[pos/dsk->bitmap_granularity/8] & (1 << ((pos/dsk->bitmap_granularity) % 8))))
@@ -696,7 +696,7 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
{
if (bad_block_cb)
{
bad_block_cb(block_end, *block_csums, block_crc);
bad_block_cb(prev, *block_csums, block_crc);
res = false;
}
else