diff --git a/src/blockstore/blockstore_disk.cpp b/src/blockstore/blockstore_disk.cpp index 726dc485..8935bca7 100644 --- a/src/blockstore/blockstore_disk.cpp +++ b/src/blockstore/blockstore_disk.cpp @@ -9,6 +9,7 @@ #include "blockstore.h" #include "ondisk_formats.h" #include "blockstore_disk.h" +#include "blockstore_heap.h" #include "str_util.h" #include "allocator.h" @@ -208,6 +209,10 @@ 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; @@ -218,7 +223,7 @@ void blockstore_disk_t::parse_config(std::map & config } } -void blockstore_disk_t::calc_lengths(bool skip_meta_check) +void blockstore_disk_t::calc_lengths() { // data data_len = data_device_size - data_offset; @@ -267,16 +272,37 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check) 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); - uint32_t entries_per_block = ((meta_block_size-meta_block_target_free_space) / - (24 /*sizeof(heap_object_t)*/ + 33 /*sizeof(heap_write_t)*/ + clean_dyn_size)); - min_meta_len = (block_count+entries_per_block-1) / entries_per_block * meta_block_size; - meta_format = BLOCKSTORE_META_FORMAT_HEAP; - if (!skip_meta_check && meta_area_size < min_meta_len) + if (meta_format == BLOCKSTORE_META_FORMAT_HEAP) + { + uint32_t entries_per_block = ((meta_block_size-meta_block_target_free_space) / + (sizeof(heap_object_t) + sizeof(heap_write_t) + clean_dyn_size)); + min_meta_len = (block_count+entries_per_block-1) / entries_per_block * meta_block_size; + } + else if (meta_format == BLOCKSTORE_META_FORMAT_V1) + { + 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; + } + else if (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; + } + else + { + throw std::runtime_error("meta_format = "+std::to_string(meta_format)+" is not supported"); + } +} + +void blockstore_disk_t::check_lengths() +{ + if (meta_area_size < min_meta_len) { 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"); } // requested journal size - if (!skip_meta_check && cfg_journal_size > journal_len) + if (cfg_journal_size > journal_len) { throw std::runtime_error("Requested journal_size is too large"); } diff --git a/src/blockstore/blockstore_disk.h b/src/blockstore/blockstore_disk.h index 55de03cd..e90a2cfa 100644 --- a/src/blockstore/blockstore_disk.h +++ b/src/blockstore/blockstore_disk.h @@ -76,7 +76,8 @@ struct blockstore_disk_t void open_data(); void open_meta(); void open_journal(); - void calc_lengths(bool skip_meta_check = false); + void calc_lengths(); + void check_lengths(); void close_all(); int trim_data(std::function is_free); diff --git a/src/blockstore/blockstore_init.cpp b/src/blockstore/blockstore_init.cpp index a8e5b6ff..6cb9ab40 100644 --- a/src/blockstore/blockstore_init.cpp +++ b/src/blockstore/blockstore_init.cpp @@ -147,6 +147,12 @@ resume_1: exit(1); } bs->heap->set_compacted_lsn(hdr->compacted_lsn); + if (bs->dsk.meta_format != hdr->version) + { + bs->dsk.meta_format = hdr->version; + bs->dsk.calc_lengths(); + } + bs->dsk.check_lengths(); } if (bs->dsk.inmemory_journal) { diff --git a/src/disk_tool/disk_tool.cpp b/src/disk_tool/disk_tool.cpp index 47aee0b6..dba7c9b9 100644 --- a/src/disk_tool/disk_tool.cpp +++ b/src/disk_tool/disk_tool.cpp @@ -374,7 +374,7 @@ int main(int argc, char *argv[]) { self.dsk.meta_block_size = strtoul(cmd[2], NULL, 10); self.dsk.meta_offset = strtoull(cmd[3], NULL, 10); - self.dsk.meta_len = strtoull(cmd[4], NULL, 10); + self.dsk.meta_area_size = strtoull(cmd[4], NULL, 10); } else { @@ -404,7 +404,7 @@ int main(int argc, char *argv[]) return 1; self.new_meta_device = self.dsk.meta_device; self.new_meta_offset = self.dsk.meta_offset; - self.new_meta_len = self.dsk.meta_len; + self.new_meta_len = self.dsk.meta_area_size; } std::string json_err; json11::Json meta = json11::Json::parse(read_all_fd(0), json_err); diff --git a/src/disk_tool/disk_tool_discard.cpp b/src/disk_tool/disk_tool_discard.cpp index 1b5b3e96..29dd9dcf 100644 --- a/src/disk_tool/disk_tool_discard.cpp +++ b/src/disk_tool/disk_tool_discard.cpp @@ -83,7 +83,7 @@ int disk_tool_t::trim_data(std::string device) return r; } // Trim - r = dsk.trim_data(data_alloc); + r = dsk.trim_data([&](uint64_t block_num) { return data_alloc->get(block_num); }); dsk.close_all(); return r == 0; } diff --git a/src/disk_tool/disk_tool_meta.cpp b/src/disk_tool/disk_tool_meta.cpp index fde838db..11bb8e5c 100644 --- a/src/disk_tool/disk_tool_meta.cpp +++ b/src/disk_tool/disk_tool_meta.cpp @@ -32,15 +32,16 @@ int disk_tool_t::process_meta(std::function int buf_size = 1024*1024; if (buf_size % dsk.meta_block_size) buf_size = 8*dsk.meta_block_size; - if (buf_size > dsk.meta_len) - buf_size = dsk.meta_len; void *data = memalign_or_die(MEM_ALIGNMENT, buf_size); - lseek64(dsk.meta_fd, dsk.meta_offset, 0); - read_blocking(dsk.meta_fd, data, dsk.meta_block_size); // Check superblock blockstore_meta_header_v2_t *hdr = (blockstore_meta_header_v2_t *)data; + lseek64(dsk.meta_fd, dsk.meta_offset, 0); + read_blocking(dsk.meta_fd, hdr, dsk.meta_block_size); if (hdr->zero == 0 && hdr->magic == BLOCKSTORE_META_MAGIC_V1) { + dsk.meta_format = hdr->version; + dsk.calc_lengths(); + dsk.check_lengths(); if (hdr->version == BLOCKSTORE_META_FORMAT_V1) { // Vitastor 0.6-0.8 - static array of clean_disk_entry with bitmaps @@ -80,15 +81,6 @@ int disk_tool_t::process_meta(std::function { fprintf(stderr, "Using block size of %u bytes based on information from the superblock\n", hdr->meta_block_size); dsk.meta_block_size = hdr->meta_block_size; - if (buf_size % dsk.meta_block_size) - { - buf_size = 8*dsk.meta_block_size; - void *new_data = memalign_or_die(MEM_ALIGNMENT, buf_size); - memcpy(new_data, data, dsk.meta_block_size); - free(data); - data = new_data; - hdr = (blockstore_meta_header_v2_t *)data; - } } dsk.meta_format = hdr->version; dsk.data_block_size = hdr->data_block_size; @@ -102,14 +94,15 @@ int disk_tool_t::process_meta(std::function *(hdr->data_csum_type & 0xff)) : 0) + (dsk.meta_format == BLOCKSTORE_META_FORMAT_V2 ? 4 /*entry_csum*/ : 0); + // Read uint64_t block_num = 0; hdr_fn(hdr); hdr = NULL; meta_pos = dsk.meta_block_size; lseek64(dsk.meta_fd, dsk.meta_offset+meta_pos, 0); - while (meta_pos < dsk.meta_len) + while (meta_pos < dsk.meta_area_size) { - uint64_t read_len = buf_size < dsk.meta_len-meta_pos ? buf_size : dsk.meta_len-meta_pos; + uint64_t read_len = buf_size < dsk.meta_area_size-meta_pos ? buf_size : dsk.meta_area_size-meta_pos; read_blocking(dsk.meta_fd, data, read_len); meta_pos += read_len; for (uint64_t blk = 0; blk < read_len; blk += dsk.meta_block_size) @@ -136,14 +129,15 @@ int disk_tool_t::process_meta(std::function } else { - // Vitastor 0.4-0.5 - static array of clean_disk_entry + // Vitastor 0.4-0.5 - static array of clean_disk_entry without header + lseek64(dsk.meta_fd, dsk.meta_offset, 0); dsk.clean_entry_bitmap_size = 0; dsk.clean_entry_size = sizeof(clean_disk_entry); uint64_t block_num = 0; hdr_fn(NULL); - while (meta_pos < dsk.meta_len) + while (meta_pos < dsk.meta_area_size) { - uint64_t read_len = buf_size < dsk.meta_len-meta_pos ? buf_size : dsk.meta_len-meta_pos; + uint64_t read_len = buf_size < dsk.meta_area_size-meta_pos ? buf_size : dsk.meta_area_size-meta_pos; read_blocking(dsk.meta_fd, data, read_len); meta_pos += read_len; for (uint64_t blk = 0; blk < read_len; blk += dsk.meta_block_size) @@ -181,7 +175,7 @@ int disk_tool_t::dump_load_check_superblock(const std::string & device) dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(true); + dsk.calc_lengths(); } catch (std::exception & e) { @@ -228,7 +222,7 @@ void disk_tool_t::dump_meta_header(blockstore_meta_header_v2_t *hdr) } else { - printf("{\"version\":\"0.5\",\"meta_block_size\":%ju,\"entries\":[\n", dsk.meta_block_size); + printf("{\"version\":\"0.5\",\"meta_block_size\":%u,\"entries\":[\n", dsk.meta_block_size); } first_entry = true; } diff --git a/src/disk_tool/disk_tool_prepare.cpp b/src/disk_tool/disk_tool_prepare.cpp index 0463dba0..842c28b2 100644 --- a/src/disk_tool/disk_tool_prepare.cpp +++ b/src/disk_tool/disk_tool_prepare.cpp @@ -72,6 +72,10 @@ int disk_tool_t::prepare_one(std::map options, int is_ options["disable_"+dev+"_fsync"] = "1"; } } + if (options["meta_format"] == "") + { + options["meta_format"] = std::to_string(BLOCKSTORE_META_FORMAT_HEAP); + } if (options["meta_device"] == "" || options["meta_device"] == options["data_device"]) { options["disable_meta_fsync"] = options["disable_data_fsync"]; @@ -108,6 +112,7 @@ int disk_tool_t::prepare_one(std::map options, int is_ if (options.find("autosync_writes") == options.end()) options["autosync_writes"] = "512"; } + uint64_t new_meta_len = parse_size(options["meta_len"]); json11::Json::object sb; blockstore_disk_t dsk; try @@ -121,22 +126,22 @@ int disk_tool_t::prepare_one(std::map options, int is_ dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(true); + dsk.calc_lengths(); sb = json11::Json::object { + { "meta_format", options["meta_format"] }, { "data_device", options["data_device"] }, { "meta_device", options["meta_device"] }, { "journal_device", options["journal_device"] }, { "block_size", (uint64_t)dsk.data_block_size }, - { "meta_block_size", dsk.meta_block_size }, - { "journal_block_size", dsk.journal_block_size }, + { "meta_block_size", (uint64_t)dsk.meta_block_size }, + { "journal_block_size", (uint64_t)dsk.journal_block_size }, { "data_size", dsk.cfg_data_size }, { "disk_alignment", (uint64_t)dsk.disk_alignment }, - { "bitmap_granularity", dsk.bitmap_granularity }, + { "bitmap_granularity", (uint64_t)dsk.bitmap_granularity }, { "disable_device_lock", dsk.disable_flock }, { "journal_offset", 4096 }, - { "meta_offset", 4096 + (dsk.meta_device == dsk.journal_device ? dsk.journal_len : 0) }, - { "data_offset", 4096 + (dsk.data_device == dsk.meta_device ? dsk.meta_len : 0) + - (dsk.data_device == dsk.journal_device ? dsk.journal_len : 0) }, + { "meta_offset", dsk.meta_offset }, + { "data_offset", dsk.data_offset + (new_meta_len ? 0 : (dsk.meta_format == BLOCKSTORE_META_FORMAT_HEAP ? dsk.min_meta_len*2 : dsk.min_meta_len)) }, { "journal_no_same_sector_overwrites", !is_hdd || is_hybrid }, { "journal_sector_buffer_count", 1024 }, { "disable_data_fsync", json_is_true(options["disable_data_fsync"]) }, @@ -180,7 +185,7 @@ int disk_tool_t::prepare_one(std::map options, int is_ } sb["osd_num"] = osd_num; // Zero out metadata and journal - if (write_zero(dsk.meta_fd, sb["meta_offset"].uint64_value(), dsk.meta_len) != 0 || + if (write_zero(dsk.meta_fd, sb["meta_offset"].uint64_value(), dsk.meta_area_size) != 0 || write_zero(dsk.journal_fd, sb["journal_offset"].uint64_value(), dsk.journal_len) != 0) { fprintf(stderr, "Failed to zero out metadata or journal: %s\n", strerror(errno)); @@ -527,9 +532,9 @@ int disk_tool_t::get_meta_partition(std::vector & ssds, std dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(true); + dsk.calc_lengths(); dsk.close_all(); - meta_size = dsk.meta_len; + meta_size = dsk.min_meta_len; } catch (std::exception & e) { diff --git a/src/disk_tool/disk_tool_resize.cpp b/src/disk_tool/disk_tool_resize.cpp index ed2e9f67..8b0b6be2 100644 --- a/src/disk_tool/disk_tool_resize.cpp +++ b/src/disk_tool/disk_tool_resize.cpp @@ -140,7 +140,7 @@ int disk_tool_t::resize_parse_params() new_data_offset == dsk.data_offset && new_data_len == dsk.data_len && new_meta_offset == dsk.meta_offset && - (new_meta_len == dsk.meta_len || new_meta_len == 0) && + (new_meta_len == dsk.meta_area_size || new_meta_len == 0) && new_journal_offset == dsk.journal_offset && new_journal_len == dsk.journal_len && options.find("force") == options.end()) diff --git a/src/disk_tool/disk_tool_resize_auto.cpp b/src/disk_tool/disk_tool_resize_auto.cpp index bac65039..07a2e84d 100644 --- a/src/disk_tool/disk_tool_resize_auto.cpp +++ b/src/disk_tool/disk_tool_resize_auto.cpp @@ -29,7 +29,7 @@ int disk_tool_t::resize_data(std::string device) dsk.open_data(); dsk.open_meta(); dsk.open_journal(); - dsk.calc_lengths(true); + dsk.calc_lengths(); } catch (std::exception & e) { @@ -61,7 +61,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(true); + dsk.calc_lengths(); dsk.journal_fd = -1; dsk.meta_fd = -1; dsk.data_fd = -1; @@ -83,7 +83,7 @@ int disk_tool_t::resize_data(std::string device) ? move_options["new_meta_device"] : dsk.meta_device; // Calculate new data & meta offsets new_data_offset = 4096 + (new_journal_device == dsk.data_device ? new_journal_len : 0) + - (new_meta_device == dsk.data_device ? dsk.meta_len : 0); + (new_meta_device == dsk.data_device ? dsk.meta_area_size : 0); new_data_offset += ((dsk.data_offset-new_data_offset) % dsk.data_block_size); if (new_data_offset != dsk.data_offset) move_options["new_data_offset"] = std::to_string(new_data_offset); @@ -236,7 +236,7 @@ int disk_tool_t::resize_parse_move_meta(std::map & mov auto new_journal_device = move_options.find("new_journal_device") != move_options.end() ? move_options["new_journal_device"] : dsk.journal_device; move_options["new_meta_device"] = dsk.data_device; - move_options["new_meta_len"] = std::to_string(dsk.meta_len); + move_options["new_meta_len"] = std::to_string(dsk.meta_area_size); } else { @@ -260,7 +260,7 @@ int disk_tool_t::resize_parse_move_meta(std::map & mov fprintf(stderr, "metadata is already on a partition of %s\n", options["move_meta"].c_str()); return 0; } - new_meta_len = ((dsk.meta_len+1024*1024-1)/1024/1024)*1024*1024; + new_meta_len = ((dsk.meta_area_size+1024*1024-1)/1024/1024)*1024*1024; if (!dry_run) { auto devinfos = collect_devices({ real_dev }); diff --git a/src/disk_tool/disk_tool_upgrade.cpp b/src/disk_tool/disk_tool_upgrade.cpp index c00d0939..5926bbcf 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(true); + dsk.calc_lengths(); dsk.close_all(); } catch (std::exception & e) @@ -116,9 +116,8 @@ int disk_tool_t::upgrade_simple_unit(std::string unit) fprintf(stderr, "Error: %s\n", e.what()); return 1; } - options.erase("meta_format"); - if (m_is_d && m_o < d_o && d_o-m_o < dsk.meta_len) - d_o += ((dsk.meta_len - (d_o-m_o) + blk-1) / blk) * blk; + if (m_is_d && m_o < d_o && d_o-m_o < dsk.min_meta_len) + d_o += ((dsk.min_meta_len - (d_o-m_o) + blk-1) / blk) * blk; } resize["new_data_offset"] = d_o; resize["new_meta_offset"] = m_o;