diff --git a/src/blockstore_disk.cpp b/src/blockstore_disk.cpp index 9a2373a5..0ea8a2e4 100644 --- a/src/blockstore_disk.cpp +++ b/src/blockstore_disk.cpp @@ -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) diff --git a/src/blockstore_disk.h b/src/blockstore_disk.h index 67a50837..a9c9c364 100644 --- a/src/blockstore_disk.h +++ b/src/blockstore_disk.h @@ -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; diff --git a/src/blockstore_flush.cpp b/src/blockstore_flush.cpp index bc9bf20d..c01e4be7 100644 --- a/src/blockstore_flush.cpp +++ b/src/blockstore_flush.cpp @@ -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, diff --git a/src/blockstore_init.cpp b/src/blockstore_init.cpp index 5eb81b75..c2175cdf 100644 --- a/src/blockstore_init.cpp +++ b/src/blockstore_init.cpp @@ -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); }