diff --git a/src/blockstore/blockstore_disk.cpp b/src/blockstore/blockstore_disk.cpp index c6e8d0a1..b1a1c0dd 100644 --- a/src/blockstore/blockstore_disk.cpp +++ b/src/blockstore/blockstore_disk.cpp @@ -172,10 +172,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)); } - 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); - clean_entry_size = sizeof(clean_disk_entry) + clean_dyn_size + 4 /*entry_csum*/; } void blockstore_disk_t::calc_lengths(bool skip_meta_check) @@ -224,9 +220,13 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check) } // required metadata size block_count = data_len / data_block_size; + 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); + clean_entry_size = sizeof(clean_disk_entry) + clean_dyn_size + 4 /*entry_csum*/; meta_len = (1 + (block_count - 1 + meta_block_size / clean_entry_size) / (meta_block_size / clean_entry_size)) * meta_block_size; - if (meta_format == BLOCKSTORE_META_FORMAT_V1 || - !meta_format && !skip_meta_check && meta_area_size < meta_len && !data_csum_type) + bool new_doesnt_fit = (!meta_format && !skip_meta_check && meta_area_size < meta_len && !data_csum_type); + if (meta_format == BLOCKSTORE_META_FORMAT_V1 || new_doesnt_fit) { 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) @@ -234,7 +234,11 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check) if (meta_format == BLOCKSTORE_META_FORMAT_V1 || meta_area_size >= meta_v0_len) { // Old metadata fits. - printf("Warning: Using old metadata format without checksums because the new format doesn't fit into provided area\n"); + if (new_doesnt_fit) + { + printf("Warning: Using old metadata format without checksums because the new format" + " doesn't fit into provided area (%lu bytes required, %lu bytes available)\n", meta_len, meta_area_size); + } clean_entry_size = clean_entry_v0_size; meta_len = meta_v0_len; meta_format = BLOCKSTORE_META_FORMAT_V1; @@ -246,7 +250,7 @@ void blockstore_disk_t::calc_lengths(bool skip_meta_check) meta_format = BLOCKSTORE_META_FORMAT_V2; 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"); + throw std::runtime_error("Metadata area is too small, need at least "+std::to_string(meta_len)+" bytes, have only "+std::to_string(meta_area_size)+" bytes"); } // requested journal size if (!skip_meta_check && cfg_journal_size > journal_len) diff --git a/src/blockstore/blockstore_disk.h b/src/blockstore/blockstore_disk.h index c4311c6c..6e6a1c4c 100644 --- a/src/blockstore/blockstore_disk.h +++ b/src/blockstore/blockstore_disk.h @@ -40,8 +40,8 @@ struct blockstore_disk_t uint64_t data_offset, data_device_sect, data_device_size, data_len; uint64_t journal_offset, journal_device_sect, journal_device_size, journal_len; - uint32_t block_order; - uint64_t block_count; + uint32_t block_order = 0; + uint64_t block_count = 0; uint32_t clean_entry_bitmap_size = 0, clean_entry_size = 0, clean_dyn_size = 0; void parse_config(std::map & config); diff --git a/src/blockstore/blockstore_init.cpp b/src/blockstore/blockstore_init.cpp index 5399e350..e27adde1 100644 --- a/src/blockstore/blockstore_init.cpp +++ b/src/blockstore/blockstore_init.cpp @@ -138,7 +138,11 @@ resume_1: exit(1); } hdr->header_csum = csum; - bs->dsk.meta_format = BLOCKSTORE_META_FORMAT_V2; + if (bs->dsk.meta_format != BLOCKSTORE_META_FORMAT_V2) + { + bs->dsk.meta_format = BLOCKSTORE_META_FORMAT_V2; + bs->dsk.calc_lengths(); + } } else if (hdr->version == BLOCKSTORE_META_FORMAT_V1) { @@ -146,11 +150,15 @@ resume_1: 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_format = BLOCKSTORE_META_FORMAT_V1; - printf("Warning: Starting with metadata in the old format without checksums, as stored on disk\n"); + if (bs->dsk.meta_format != BLOCKSTORE_META_FORMAT_V1 || + bs->dsk.data_csum_type != 0 || bs->dsk.csum_block_size != 0) + { + bs->dsk.data_csum_type = 0; + bs->dsk.csum_block_size = 0; + bs->dsk.meta_format = BLOCKSTORE_META_FORMAT_V1; + bs->dsk.calc_lengths(); + printf("Warning: Starting with metadata in the old format without checksums, as stored on disk\n"); + } } else if (hdr->version > BLOCKSTORE_META_FORMAT_V2) { @@ -338,7 +346,7 @@ bool blockstore_init_meta::handle_meta_block(uint8_t *buf, uint64_t entries_per_ 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 %ju is corrupt (checksum mismatch), skipping\n", done_cnt+i); + printf("Metadata entry %ju is corrupt (checksum mismatch: %08x vs %08x), skipping\n", done_cnt+i, *entry_csum, crc32c(0, entry, bs->dsk.clean_entry_size - 4)); // zero out the invalid entry, otherwise we'll hit "tried to overwrite non-zero metadata entry" later if (bs->inmemory_meta) { diff --git a/src/disk_tool/disk_tool_upgrade.cpp b/src/disk_tool/disk_tool_upgrade.cpp index 6b5c61a5..c00d0939 100644 --- a/src/disk_tool/disk_tool_upgrade.cpp +++ b/src/disk_tool/disk_tool_upgrade.cpp @@ -79,28 +79,59 @@ int disk_tool_t::upgrade_simple_unit(std::string unit) { // Resize data uint64_t blk = stoull_full(options["block_size"]); - blk = blk ? blk : 128*1024; + blk = blk ? blk : (1 << DEFAULT_DATA_BLOCK_ORDER); std::map resize; if (d_o < 4096 || m_is_d && m_o < 4096 && m_o < d_o || j_is_d && j_o < 4096 && j_o < d_o) { - resize["new_data_offset"] = d_o+blk; + d_o += blk; if (m_is_d && m_o < d_o) - resize["new_meta_offset"] = m_o+blk; + m_o += blk; if (j_is_d && j_o < d_o) - resize["new_journal_offset"] = j_o+blk; + j_o += blk; } if (!m_is_d && m_o < 4096) { - resize["new_meta_offset"] = m_o+4096; + m_o += 4096; if (j_is_m && m_o < j_o) - resize["new_journal_offset"] = j_o+4096; + j_o += 4096; } if (!j_is_d && !j_is_m && j_o < 4096) - resize["new_journal_offset"] = j_o+4096; + j_o += 4096; + if (options["meta_format"] == "" || options["meta_format"] == "1") + { + blockstore_disk_t dsk; + options["meta_format"] = std::to_string(BLOCKSTORE_META_FORMAT_V2); + try + { + dsk.parse_config(options); + dsk.open_data(); + dsk.open_meta(); + dsk.open_journal(); + dsk.calc_lengths(true); + dsk.close_all(); + } + catch (std::exception & e) + { + dsk.close_all(); + 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; + } + resize["new_data_offset"] = d_o; + resize["new_meta_offset"] = m_o; + resize["new_journal_offset"] = j_o; disk_tool_t resizer; resizer.options = options; for (auto & kv: resize) resizer.options[kv.first] = std::to_string(kv.second); + std::string cmd; + for (auto & kv: resizer.options) + if (kv.second != "") + cmd += " "+kv.first+" = "+kv.second+"\n"; + fprintf(stderr, "Running resize:\n%s", cmd.c_str()); if (resizer.raw_resize() != 0) { // FIXME: Resize with backup or journal