Add backwards compatibility with non-checksum metadata and journal formats

hotfix-1.0.0
Vitaliy Filippov 2023-01-09 00:28:39 +03:00
parent 7d532880c3
commit a166147110
4 changed files with 80 additions and 21 deletions

View File

@ -193,7 +193,23 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check)
meta_len = (1 + (block_count - 1 + meta_block_size / clean_entry_size) / (meta_block_size / clean_entry_size)) * meta_block_size;
if (!skip_meta_check && meta_area_size < meta_len)
{
throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(meta_len)+" bytes");
if (!data_csum_type && !meta_version)
{
uint64_t clean_entry_v0_size = sizeof(clean_disk_entry) + 2*clean_entry_bitmap_size;
uint64_t meta_v0_len = (1 + (block_count - 1 + meta_block_size / clean_entry_v0_size)
/ (meta_block_size / clean_entry_v0_size)) * meta_block_size;
if (meta_area_size >= meta_v0_len)
{
// Old metadata fits.
clean_entry_size = clean_entry_v0_size;
meta_len = meta_v0_len;
meta_version = BLOCKSTORE_META_VERSION_V1;
}
}
if (meta_area_size < meta_len)
{
throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(meta_len)+" bytes");
}
}
// requested journal size
if (!skip_meta_check && cfg_journal_size > journal_len)

View File

@ -33,7 +33,7 @@ struct blockstore_disk_t
bool disable_flock = false;
int meta_fd = -1, data_fd = -1, journal_fd = -1;
uint64_t meta_offset, meta_device_sect, meta_device_size, meta_len;
uint64_t meta_offset, meta_device_sect, meta_device_size, meta_len, meta_version = 0;
uint64_t data_offset, data_device_sect, data_device_size, data_len;
uint64_t journal_offset, journal_device_sect, journal_device_size, journal_len;

View File

@ -665,9 +665,12 @@ void journal_flusher_co::update_metadata_entry()
new_entry->version = cur.version;
if (!bs->inmemory_meta)
memcpy(&new_entry->bitmap, new_clean_bitmap, bs->dsk.clean_dyn_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);
if (bs->dsk.meta_version >= BLOCKSTORE_META_VERSION_V2)
{
// 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);
}
}
}
@ -807,9 +810,12 @@ bool journal_flusher_co::clear_incomplete_csum_block_bits(int wait_base)
calc_block_checksums(new_data_csums, true);
if (!bs->inmemory_meta)
memcpy(&new_entry->bitmap, new_clean_bitmap, bs->dsk.clean_dyn_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);
if (bs->dsk.meta_version >= BLOCKSTORE_META_VERSION_V2)
{
// 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);
}
}
// Write and fsync the modified metadata entry
resume_2:
@ -1364,7 +1370,8 @@ bool journal_flusher_co::trim_journal(int wait_base)
.crc32 = 0,
.magic = JOURNAL_MAGIC,
.type = JE_START,
.size = sizeof(journal_entry_start),
.size = ((!bs->dsk.data_csum_type && ((journal_entry_start*)flusher->journal_superblock)->version == JOURNAL_VERSION_V1)
? (uint32_t)JE_START_V1_SIZE : (uint32_t)JE_START_V2_SIZE),
.reserved = 0,
.journal_start = new_trim_pos,
.version = JOURNAL_VERSION_V2,

View File

@ -123,6 +123,14 @@ resume_1:
);
exit(1);
}
if (bs->dsk.meta_version && bs->dsk.meta_version != hdr->version)
{
printf(
"Metadata format version is %lu on disk, but %lu is currently selected in OSD configuration.\n"
" Please upgrade using vitastor-disk.\n", hdr->version, bs->dsk.meta_version
);
exit(1);
}
if (hdr->version == BLOCKSTORE_META_VERSION_V2)
{
uint32_t csum = hdr->header_csum;
@ -133,12 +141,18 @@ resume_1:
exit(1);
}
hdr->header_csum = csum;
bs->dsk.meta_version = BLOCKSTORE_META_VERSION_V2;
}
else if (hdr->version == BLOCKSTORE_META_VERSION_V1)
{
hdr->data_csum_type = 0;
hdr->csum_block_size = 0;
hdr->header_csum = 0;
// Enable compatibility mode - entries without checksums
bs->dsk.clean_entry_size = sizeof(clean_disk_entry) + bs->dsk.clean_entry_bitmap_size*2;
bs->dsk.meta_len = (1 + (bs->dsk.block_count - 1 + bs->dsk.meta_block_size / bs->dsk.clean_entry_size)
/ (bs->dsk.meta_block_size / bs->dsk.clean_entry_size)) * bs->dsk.meta_block_size;
bs->dsk.meta_version = BLOCKSTORE_META_VERSION_V1;
}
else if (hdr->version > BLOCKSTORE_META_VERSION_V2)
{
@ -156,10 +170,12 @@ resume_1:
{
printf(
"Configuration stored in metadata superblock"
" (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u)"
" differs from OSD configuration (%lu/%u/%lu).\n",
" (meta_block_size=%u, data_block_size=%u, bitmap_granularity=%u, data_csum_type=%u, csum_block_size=%u)"
" differs from OSD configuration (%lu/%u/%lu, %u/%u).\n",
hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity,
bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity
hdr->data_csum_type, hdr->csum_block_size,
bs->dsk.meta_block_size, bs->dsk.data_block_size, bs->dsk.bitmap_granularity,
bs->dsk.data_csum_type, bs->dsk.csum_block_size
);
exit(1);
}
@ -310,12 +326,15 @@ bool blockstore_init_meta::handle_meta_block(uint8_t *buf, uint64_t entries_per_
clean_disk_entry *entry = (clean_disk_entry*)(buf + i*bs->dsk.clean_entry_size);
if (entry->oid.inode > 0)
{
// Check entry crc32
uint32_t *entry_csum = (uint32_t*)((uint8_t*)entry + bs->dsk.clean_entry_size - 4);
if (*entry_csum != crc32c(0, entry, bs->dsk.clean_entry_size - 4))
if (bs->dsk.meta_version >= BLOCKSTORE_META_VERSION_V2)
{
printf("Metadata entry %lu is corrupt (checksum mismatch), skipping\n", done_cnt+i);
continue;
// Check entry crc32
uint32_t *entry_csum = (uint32_t*)((uint8_t*)entry + bs->dsk.clean_entry_size - 4);
if (*entry_csum != crc32c(0, entry, bs->dsk.clean_entry_size - 4))
{
printf("Metadata entry %lu is corrupt (checksum mismatch), skipping\n", done_cnt+i);
continue;
}
}
if (!bs->inmemory_meta && bs->dsk.clean_entry_bitmap_size)
{
@ -536,13 +555,30 @@ resume_1:
fprintf(stderr, "First entry of the journal is corrupt or unsupported\n");
exit(1);
}
if (je_start->size == JE_START_V0_SIZE || je_start->version != JOURNAL_VERSION_V2)
if (je_start->size == JE_START_V0_SIZE ||
(je_start->version != JOURNAL_VERSION_V1 || je_start->size != JE_START_V1_SIZE) &&
(je_start->version != JOURNAL_VERSION_V2 || je_start->size != JE_START_V2_SIZE))
{
// FIXME: Support v1 too
fprintf(
stderr, "The code only supports journal version %d, but it is %lu on disk."
stderr, "The code only supports journal versions 2 and 1, but it is %lu on disk."
" Please use vitastor-disk to rewrite the journal\n",
JOURNAL_VERSION_V2, je_start->size == JE_START_V0_SIZE ? 0 : je_start->version
je_start->size == JE_START_V0_SIZE ? 0 : je_start->version
);
exit(1);
}
if (je_start->version == JOURNAL_VERSION_V1)
{
je_start->data_csum_type = 0;
je_start->csum_block_size = 0;
}
if (je_start->data_csum_type != bs->dsk.data_csum_type ||
je_start->csum_block_size != bs->dsk.csum_block_size)
{
printf(
"Configuration stored in journal superblock (data_csum_type=%u, csum_block_size=%u)"
" differs from OSD configuration (%u/%u).\n",
je_start->data_csum_type, je_start->csum_block_size,
bs->dsk.data_csum_type, bs->dsk.csum_block_size
);
exit(1);
}