From a5768a8ef6777daa4b202656be8c2edf8a1af6a8 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Sun, 30 Nov 2025 22:18:23 +0300 Subject: [PATCH] Parse empty meta_format in superblock as v2 (fix updating from 2.x) --- src/blockstore/blockstore_disk.cpp | 30 ++++++++++++++++++++----- src/blockstore/blockstore_disk.h | 9 ++++---- src/disk_tool/disk_tool_prepare.cpp | 6 +++-- src/disk_tool/disk_tool_resize_auto.cpp | 2 +- src/disk_tool/disk_tool_upgrade.cpp | 2 +- src/test/test_blockstore.cpp | 1 + src/test/test_heap.cpp | 4 ++-- 7 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/blockstore/blockstore_disk.cpp b/src/blockstore/blockstore_disk.cpp index 11400803..15a17f45 100644 --- a/src/blockstore/blockstore_disk.cpp +++ b/src/blockstore/blockstore_disk.cpp @@ -203,10 +203,6 @@ void blockstore_disk_t::parse_config(std::map & config { throw std::runtime_error("journal_offset must be a multiple of journal_block_size = "+std::to_string(journal_block_size)); } - if (!meta_format) - { - meta_format = BLOCKSTORE_META_FORMAT_HEAP; - } if (meta_device == data_device) { disable_meta_fsync = disable_data_fsync; @@ -217,7 +213,7 @@ void blockstore_disk_t::parse_config(std::map & config } } -void blockstore_disk_t::calc_lengths() +void blockstore_disk_t::calc_lengths(bool skip_meta_check) { // data data_len = data_device_size - data_offset; @@ -266,6 +262,7 @@ void blockstore_disk_t::calc_lengths() clean_entry_bitmap_size = data_block_size / bitmap_granularity / 8; clean_dyn_size = clean_entry_bitmap_size*2 + (csum_block_size ? data_block_size/csum_block_size*(data_csum_type & 0xFF) : 0); +recalc: if (meta_format == BLOCKSTORE_META_FORMAT_HEAP) { uint32_t entries_per_block = meta_block_size / (sizeof(heap_big_write_t) + clean_dyn_size); @@ -276,11 +273,32 @@ void blockstore_disk_t::calc_lengths() clean_entry_size = 24 /*sizeof(clean_disk_entry)*/ + 2*clean_entry_bitmap_size; min_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 < min_meta_len) + { +too_small: + throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(min_meta_len)+ + " bytes, have only "+std::to_string(meta_area_size)+" bytes"); + } } - else if (meta_format == BLOCKSTORE_META_FORMAT_V2) + else if (meta_format == BLOCKSTORE_META_FORMAT_V2 || !meta_format) { + meta_format = BLOCKSTORE_META_FORMAT_V2; clean_entry_size = 24 /*sizeof(clean_disk_entry)*/ + clean_dyn_size + 4 /*entry_csum*/; min_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 < min_meta_len) + { + if (!data_csum_type) + { + printf("Warning: Using old metadata format without checksums because the new format" + " doesn't fit into provided area (%ju bytes required, %ju bytes available)\n", min_meta_len, meta_area_size); + meta_format = BLOCKSTORE_META_FORMAT_V1; + goto recalc; + } + else + { + goto too_small; + } + } } else { diff --git a/src/blockstore/blockstore_disk.h b/src/blockstore/blockstore_disk.h index 91e291c5..803b5a40 100644 --- a/src/blockstore/blockstore_disk.h +++ b/src/blockstore/blockstore_disk.h @@ -61,9 +61,10 @@ struct blockstore_disk_t uint64_t discard_granularity = 0; int meta_fd = -1, data_fd = -1, journal_fd = -1; - uint64_t meta_offset, meta_device_sect, meta_device_size, meta_area_size, min_meta_len, meta_format = 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; + uint64_t meta_offset = 0, meta_device_sect = 0, meta_device_size = 0, meta_area_size = 0, min_meta_len = 0; + uint64_t data_offset = 0, data_device_sect = 0, data_device_size = 0, data_len = 0; + uint64_t journal_offset = 0, journal_device_sect = 0, journal_device_size = 0, journal_len = 0; + uint64_t meta_format = 0; uint64_t block_count = 0; uint32_t clean_entry_bitmap_size = 0; @@ -75,7 +76,7 @@ struct blockstore_disk_t void open_data(); void open_meta(); void open_journal(); - void calc_lengths(); + void calc_lengths(bool skip_meta_check = false); void check_lengths(); void close_all(); int trim_data(std::function is_free); diff --git a/src/disk_tool/disk_tool_prepare.cpp b/src/disk_tool/disk_tool_prepare.cpp index d8f58eb5..70d9fd65 100644 --- a/src/disk_tool/disk_tool_prepare.cpp +++ b/src/disk_tool/disk_tool_prepare.cpp @@ -167,7 +167,7 @@ int disk_tool_t::prepare_one(std::map options, int is_ dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(); + dsk.calc_lengths(true); if (dsk.data_device == dsk.meta_device && !new_meta_len) { uint64_t new_meta_len = dsk.min_meta_len; @@ -586,7 +586,7 @@ int disk_tool_t::get_meta_partition(std::vector & ssds, std dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(); + dsk.calc_lengths(true); dsk.close_all(); meta_size = dsk.min_meta_len; } @@ -679,6 +679,8 @@ int disk_tool_t::prepare(std::vector devices) std::vector ssds; if (options.find("disable_data_fsync") == options.end()) options["disable_data_fsync"] = "auto"; + if (options["meta_format"] == "") + options["meta_format"] = std::to_string(BLOCKSTORE_META_FORMAT_HEAP); if (hybrid) { if (options.find("disable_meta_fsync") == options.end()) diff --git a/src/disk_tool/disk_tool_resize_auto.cpp b/src/disk_tool/disk_tool_resize_auto.cpp index ce07cc2d..3e04283a 100644 --- a/src/disk_tool/disk_tool_resize_auto.cpp +++ b/src/disk_tool/disk_tool_resize_auto.cpp @@ -62,7 +62,7 @@ int disk_tool_t::resize_data(std::string device) dsk.journal_fd = old_journal_fd; dsk.meta_fd = old_meta_fd; dsk.data_fd = old_data_fd; - dsk.calc_lengths(); + dsk.calc_lengths(true); dsk.journal_fd = -1; dsk.meta_fd = -1; dsk.data_fd = -1; diff --git a/src/disk_tool/disk_tool_upgrade.cpp b/src/disk_tool/disk_tool_upgrade.cpp index 5926bbcf..b79fbcf7 100644 --- a/src/disk_tool/disk_tool_upgrade.cpp +++ b/src/disk_tool/disk_tool_upgrade.cpp @@ -107,7 +107,7 @@ int disk_tool_t::upgrade_simple_unit(std::string unit) dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(); + dsk.calc_lengths(true); dsk.close_all(); } catch (std::exception & e) diff --git a/src/test/test_blockstore.cpp b/src/test/test_blockstore.cpp index 9eecf32d..cef438bc 100644 --- a/src/test/test_blockstore.cpp +++ b/src/test/test_blockstore.cpp @@ -70,6 +70,7 @@ struct bs_test_t config["log_level"] = "10"; config["data_csum_type"] = "crc32c"; config["csum_block_size"] = "4096"; + config["meta_format"] = "3"; } void init() diff --git a/src/test/test_heap.cpp b/src/test/test_heap.cpp index b074260d..8d5ac22a 100644 --- a/src/test/test_heap.cpp +++ b/src/test/test_heap.cpp @@ -122,7 +122,7 @@ void _test_init(blockstore_disk_t & dsk, bool csum, std::function buffer_area(dsk.journal_device_size); blockstore_heap_t heap(&dsk, buffer_area.data());