Implement bitmap-granular (4k) metadata & data checksums

This commit is contained in:
Vitaliy Filippov
2023-07-13 01:49:45 +03:00
parent a0aac7eb2a
commit cc1f03971d
26 changed files with 738 additions and 174 deletions
+44 -6
View File
@@ -479,23 +479,43 @@ resume_1:
bs->ringloop->wakeup();
}
// Reads completed, submit writes and set bitmap bits
if (bs->dsk.clean_entry_bitmap_size)
if (bs->dsk.clean_entry_bitmap_size || bs->dsk.csum_block_size)
{
new_clean_bitmap = (bs->inmemory_meta
? (uint8_t*)meta_new.buf + meta_new.pos*bs->dsk.clean_entry_size + sizeof(clean_disk_entry)
: (uint8_t*)bs->clean_bitmap + (clean_loc >> bs->dsk.block_order)*(2*bs->dsk.clean_entry_bitmap_size));
if (clean_init_bitmap)
: (uint8_t*)bs->clean_dyn_data + (clean_loc >> bs->dsk.block_order)*bs->dsk.clean_dyn_size);
if (bs->dsk.clean_entry_bitmap_size && clean_init_bitmap)
{
// Initial internal bitmap bits from the big write
memset(new_clean_bitmap, 0, bs->dsk.clean_entry_bitmap_size);
bitmap_set(new_clean_bitmap, clean_bitmap_offset, clean_bitmap_len, bs->dsk.bitmap_granularity);
}
}
// Copy initial (big_write) data checksums
if (bs->dsk.csum_block_size && clean_init_bitmap)
{
uint8_t *new_clean_data_csum = (uint8_t*)new_clean_bitmap + 2*bs->dsk.clean_entry_bitmap_size +
clean_bitmap_offset / bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
uint64_t dyn_size = bs->dsk.dirty_dyn_size(clean_bitmap_len);
uint8_t *dyn_ptr = dyn_size > sizeof(void*) ? clean_init_data_csum : (uint8_t*)&clean_init_data_csum;
uint64_t csum_len = clean_bitmap_len / bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
memcpy(new_clean_data_csum, dyn_ptr + bs->dsk.clean_entry_bitmap_size, csum_len);
}
for (it = v.begin(); it != v.end(); it++)
{
// Set internal bitmap bits
if (new_clean_bitmap)
{
bitmap_set(new_clean_bitmap, it->offset, it->len, bs->dsk.bitmap_granularity);
}
// Copy small_write data checksums
if (bs->dsk.csum_block_size)
{
uint8_t *new_clean_data_csum = (uint8_t*)new_clean_bitmap + 2*bs->dsk.clean_entry_bitmap_size +
it->offset / bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
uint64_t csum_len = it->len / bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
memcpy(new_clean_data_csum, it->csum_buf, csum_len);
}
await_sqe(4);
data->iov = (struct iovec){ it->buf, (size_t)it->len };
data->callback = simple_callback_w;
@@ -590,9 +610,14 @@ resume_1:
// copy latest external bitmap/attributes
if (bs->dsk.clean_entry_bitmap_size)
{
void *bmp_ptr = bs->dsk.clean_entry_bitmap_size > sizeof(void*) ? dirty_end->second.bitmap : &dirty_end->second.bitmap;
memcpy((uint8_t*)(new_entry+1) + bs->dsk.clean_entry_bitmap_size, bmp_ptr, bs->dsk.clean_entry_bitmap_size);
uint64_t dyn_size = bs->dsk.dirty_dyn_size(dirty_end->second.len);
void *dyn_ptr = dyn_size > sizeof(void*) ? dirty_end->second.dyn_data : &dirty_end->second.dyn_data;
// copy bitmap
memcpy((uint8_t*)(new_entry+1) + bs->dsk.clean_entry_bitmap_size, dyn_ptr, bs->dsk.clean_entry_bitmap_size);
}
// calculate metadata entry checksum
uint32_t *new_entry_csum = (uint32_t*)((uint8_t*)new_entry + bs->dsk.clean_entry_size - 4);
*new_entry_csum = crc32c(0, new_entry, bs->dsk.clean_entry_size - 4);
}
await_sqe(6);
data->iov = (struct iovec){ meta_new.buf, bs->dsk.meta_block_size };
@@ -688,7 +713,9 @@ resume_1:
.size = sizeof(journal_entry_start),
.reserved = 0,
.journal_start = new_trim_pos,
.version = JOURNAL_VERSION,
.version = JOURNAL_VERSION_V2,
.data_csum_type = bs->dsk.data_csum_type,
.csum_block_size = bs->dsk.csum_block_size,
};
((journal_entry_start*)flusher->journal_superblock)->crc32 = je_crc32((journal_entry*)flusher->journal_superblock);
data->iov = (struct iovec){ flusher->journal_superblock, bs->dsk.journal_block_size };
@@ -791,6 +818,16 @@ bool journal_flusher_co::scan_dirty(int wait_base)
submit_len = it == v.end() || it->offset >= end_offset ? end_offset-offset : it->offset-offset;
it = v.insert(it, (copy_buffer_t){ .offset = offset, .len = submit_len });
copy_count++;
if (bs->dsk.csum_block_size)
{
uint64_t dyn_size = bs->dsk.dirty_dyn_size(dirty_it->second.len);
// FIXME Remove this > sizeof(void*) inline perversion from everywhere.
// I think it doesn't matter but I couldn't stop myself from implementing it :)
uint8_t *dyn_from = (uint8_t*)(dyn_size > sizeof(void*) ? dirty_it->second.dyn_data : &dirty_it->second.dyn_data) +
bs->dsk.clean_entry_bitmap_size +
(offset - dirty_it->second.offset) / bs->dsk.csum_block_size * (bs->dsk.data_csum_type & 0xFF);
it->csum_buf = dyn_from;
}
if (bs->journal.inmemory)
{
// Take it from memory, don't copy it
@@ -823,6 +860,7 @@ bool journal_flusher_co::scan_dirty(int wait_base)
clean_init_bitmap = true;
clean_bitmap_offset = dirty_it->second.offset;
clean_bitmap_len = dirty_it->second.len;
clean_init_data_csum = (uint8_t*)dirty_it->second.dyn_data;
skip_copy = true;
}
else if (IS_DELETE(dirty_it->second.state) && !skip_copy)