Fix checksum padding during flush

This commit is contained in:
Vitaliy Filippov
2025-11-23 19:08:24 +03:00
parent eec2f2b799
commit e379fc6df4
3 changed files with 48 additions and 65 deletions
+45 -61
View File
@@ -342,6 +342,13 @@ resume_24:
{ {
return false; 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); bs->heap->mark_object_compacted(cur_obj, compact_lsn);
// Done // Done
@@ -370,83 +377,53 @@ resume_15:
goto resume_0; 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; bs->find_holes(read_vec, 0, bs->dsk.data_block_size, [&](int & pos, uint32_t hole_start, uint32_t hole_end)
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++)
{ {
if (!(read_vec[i].copy_flags & COPY_BUF_COALESCED)) if (hole_start % bs->dsk.csum_block_size)
{ {
if (read_vec[i].offset > prev_end) 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))
{
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;
} }
} if ((hole_end % bs->dsk.csum_block_size) &&
if (prev_end > prev_begin && (!(hole_start % bs->dsk.csum_block_size) || (hole_end / bs->dsk.csum_block_size) != (hole_start / bs->dsk.csum_block_size)))
((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))
{ {
uint32_t blk_begin = (prev_begin - prev_begin%bs->dsk.csum_block_size); cb(pos, hole_end - (hole_end % bs->dsk.csum_block_size), hole_end);
if (blk_begin < big_start)
blk_begin = big_start;
cb(pos++, blk_begin, prev_begin);
r++;
} }
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() 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; read_to_fill_incomplete = true;
uint32_t blk_begin = (hole_start - hole_start % bs->dsk.csum_block_size); 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 = (blk_begin < big_start ? big_start : 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);
(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);
blk_begin < big_start ? big_start : blk_begin, if (!read_vec.size() || read_vec.back().copy_flags != copy_flags ||
(blk_begin + bs->dsk.csum_block_size) > big_end ? big_end : (blk_begin + bs->dsk.csum_block_size), read_vec.back().offset != blk_begin || read_vec.back().len != blk_end-blk_begin)
COPY_BUF_CSUM_FILL | (bs->perfect_csum_update ? 0 : COPY_BUF_SKIP_CSUM)); {
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]; 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){ read_vec.insert(read_vec.begin()+vec_pos, (copy_buffer_t){
.copy_flags = COPY_BUF_JOURNAL|COPY_BUF_COALESCED, .copy_flags = COPY_BUF_JOURNAL|COPY_BUF_COALESCED,
.offset = hole_start, .offset = hole_start,
.len = hole_end-hole_start, .len = hole_end - hole_start,
.buf = vec.buf + hole_start - vec.offset, .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 *bmp = end_wr->get_int_bitmap(bs->heap);
uint8_t *csums = end_wr->get_checksums(bs->heap); uint8_t *csums = end_wr->get_checksums(bs->heap);
// Clear bits // 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); if (vec.copy_flags & COPY_BUF_CSUM_FILL)
return 0; {
}); 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 // Update partial block checksums
for (auto & vec: read_vec) for (auto & vec: read_vec)
{ {
+1 -2
View File
@@ -60,8 +60,7 @@ class journal_flusher_co
friend class journal_flusher_t; 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 & pos, uint32_t hole_start, uint32_t hole_end)> cb);
void iterate_checksum_holes(std::function<void(int, uint32_t, uint32_t)> cb);
void fill_partial_checksum_blocks(); void fill_partial_checksum_blocks();
void free_buffers(); void free_buffers();
int check_and_punch_checksums(); 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; bool isset = false;
while (pos < end) while (pos < end)
{ {
uint32_t prev = pos;
if (bitmap) if (bitmap)
{ {
uint32_t prev = pos;
while (pos < end && pos < block_end) while (pos < end && pos < block_end)
{ {
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))))
@@ -696,7 +696,7 @@ bool blockstore_heap_t::calc_block_checksums(uint32_t *block_csums, uint8_t *bit
{ {
if (bad_block_cb) if (bad_block_cb)
{ {
bad_block_cb(block_end, *block_csums, block_crc); bad_block_cb(prev, *block_csums, block_crc);
res = false; res = false;
} }
else else