From bce357e2a59a06f0624c21ce7f5a491301b88c7e Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Mon, 13 Jun 2022 01:24:33 +0300 Subject: [PATCH] Do not read all metadata into memory when dumping --- src/CMakeLists.txt | 2 +- src/blockstore_impl.h | 6 +- src/blockstore_init.cpp | 12 +-- src/dump_meta.cpp | 164 ++++++++++++++++++++-------------------- 4 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b351e291..cdecb37d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -200,7 +200,7 @@ add_executable(vitastor-dump-journal # vitastor-dump-meta add_executable(vitastor-dump-meta - dump_meta.cpp + dump_meta.cpp rw_blocking.cpp ) if (${WITH_QEMU}) diff --git a/src/blockstore_impl.h b/src/blockstore_impl.h index 73be4f46..4847133e 100644 --- a/src/blockstore_impl.h +++ b/src/blockstore_impl.h @@ -90,13 +90,13 @@ #include "blockstore_journal.h" // "VITAstor" -#define BLOCKSTORE_META_MAGIC 0x726F747341544956l -#define BLOCKSTORE_META_VERSION 1 +#define BLOCKSTORE_META_MAGIC_V1 0x726F747341544956l +#define BLOCKSTORE_META_VERSION_V1 1 // metadata header (superblock) // FIXME: After adding the OSD superblock, add a key to metadata // and journal headers to check if they belong to the same OSD -struct __attribute__((__packed__)) blockstore_meta_header_t +struct __attribute__((__packed__)) blockstore_meta_header_v1_t { uint64_t zero; uint64_t magic; diff --git a/src/blockstore_init.cpp b/src/blockstore_init.cpp index dd848e24..99749c1a 100644 --- a/src/blockstore_init.cpp +++ b/src/blockstore_init.cpp @@ -71,10 +71,10 @@ resume_1: if (iszero((uint64_t*)metadata_buffer, bs->meta_block_size / sizeof(uint64_t))) { { - blockstore_meta_header_t *hdr = (blockstore_meta_header_t *)metadata_buffer; + blockstore_meta_header_v1_t *hdr = (blockstore_meta_header_v1_t *)metadata_buffer; hdr->zero = 0; - hdr->magic = BLOCKSTORE_META_MAGIC; - hdr->version = BLOCKSTORE_META_VERSION; + hdr->magic = BLOCKSTORE_META_MAGIC_V1; + hdr->version = BLOCKSTORE_META_VERSION_V1; hdr->meta_block_size = bs->meta_block_size; hdr->data_block_size = bs->block_size; hdr->bitmap_granularity = bs->bitmap_granularity; @@ -103,10 +103,10 @@ resume_1: } else { - blockstore_meta_header_t *hdr = (blockstore_meta_header_t *)metadata_buffer; + blockstore_meta_header_v1_t *hdr = (blockstore_meta_header_v1_t *)metadata_buffer; if (hdr->zero != 0 || - hdr->magic != BLOCKSTORE_META_MAGIC || - hdr->version != BLOCKSTORE_META_VERSION) + hdr->magic != BLOCKSTORE_META_MAGIC_V1 || + hdr->version != BLOCKSTORE_META_VERSION_V1) { printf( "Metadata is corrupt or old version.\n" diff --git a/src/dump_meta.cpp b/src/dump_meta.cpp index 19a8a5f6..7193c807 100644 --- a/src/dump_meta.cpp +++ b/src/dump_meta.cpp @@ -12,32 +12,9 @@ #include #include -#include "object_id.h" +#include "blockstore_impl.h" #include "osd_id.h" - -// "VITAstor" -#define BLOCKSTORE_META_MAGIC_V1 0x726F747341544956l -#define BLOCKSTORE_META_VERSION_V1 1 - -#define DIRECT_IO_ALIGNMENT 512 -#define MEM_ALIGNMENT 4096 - -struct __attribute__((__packed__)) clean_disk_entry_v0_t -{ - object_id oid; - uint64_t version; - uint8_t bitmap[]; -}; - -struct __attribute__((__packed__)) blockstore_meta_header_v1_t -{ - uint64_t zero; - uint64_t magic; - uint64_t version; - uint32_t meta_block_size; - uint32_t data_block_size; - uint32_t bitmap_granularity; -}; +#include "rw_blocking.h" struct meta_dumper_t { @@ -47,6 +24,8 @@ struct meta_dumper_t uint64_t meta_len; uint64_t meta_pos; int fd; + + int dump(); }; int main(int argc, char *argv[]) @@ -62,108 +41,129 @@ int main(int argc, char *argv[]) self.meta_block_size = strtoul(argv[b+1], NULL, 10); self.meta_offset = strtoull(argv[b+2], NULL, 10); self.meta_len = strtoull(argv[b+3], NULL, 10); - if (self.meta_block_size % DIRECT_IO_ALIGNMENT) + return self.dump(); +} + +int meta_dumper_t::dump() +{ + if (this->meta_block_size % DIRECT_IO_ALIGNMENT) { printf("Invalid metadata block size\n"); return 1; } - self.fd = open(self.meta_device, O_DIRECT|O_RDONLY); - if (self.fd == -1) + this->fd = open(this->meta_device, O_DIRECT|O_RDONLY); + if (this->fd == -1) { printf("Failed to open metadata device\n"); return 1; } - // Read all metadata into memory - void *data = memalign(MEM_ALIGNMENT, self.meta_len); - if (!data) - { - printf("Failed to allocate %lu MB of memory\n", self.meta_len/1024/1024); - close(self.fd); - return 1; - } - while (self.meta_pos < self.meta_len) - { - int r = pread(self.fd, data+self.meta_pos, self.meta_len-self.meta_pos, self.meta_offset+self.meta_pos); - assert(r > 0); - self.meta_pos += r; - } - close(self.fd); + int buf_size = 1024*1024; + if (buf_size % this->meta_block_size) + buf_size = 8*this->meta_block_size; + if (buf_size > this->meta_len) + buf_size = this->meta_len; + void *data = memalign_or_die(MEM_ALIGNMENT, buf_size); + lseek64(this->fd, this->meta_offset, 0); + read_blocking(this->fd, data, buf_size); // Check superblock blockstore_meta_header_v1_t *hdr = (blockstore_meta_header_v1_t *)data; if (hdr->zero == 0 && hdr->magic == BLOCKSTORE_META_MAGIC_V1 && hdr->version == BLOCKSTORE_META_VERSION_V1) { - // Vitastor 0.6-0.7 - static array of clean_disk_entry_v0_t with bitmaps - if (hdr->meta_block_size != self.meta_block_size) + // Vitastor 0.6-0.7 - static array of clean_disk_entry with bitmaps + if (hdr->meta_block_size != this->meta_block_size) { - printf("Using block size %u bytes based on information from the superblock\n", hdr->meta_block_size); - self.meta_block_size = hdr->meta_block_size; + printf("Using block size of %u bytes based on information from the superblock\n", hdr->meta_block_size); + this->meta_block_size = hdr->meta_block_size; + if (buf_size % this->meta_block_size) + { + buf_size = 8*this->meta_block_size; + free(data); + data = memalign_or_die(MEM_ALIGNMENT, buf_size); + } } + this->meta_offset += this->meta_block_size; + this->meta_len -= this->meta_block_size; uint64_t clean_entry_bitmap_size = hdr->data_block_size / hdr->bitmap_granularity / 8; - uint64_t clean_entry_size = sizeof(clean_disk_entry_v0_t) + 2*clean_entry_bitmap_size; + uint64_t clean_entry_size = sizeof(clean_disk_entry) + 2*clean_entry_bitmap_size; uint64_t block_num = 0; printf( "{\"version\":\"0.6\",\"meta_block_size\":%u,\"data_block_size\":%u,\"bitmap_granularity\":%u,\"entries\":[\n", hdr->meta_block_size, hdr->data_block_size, hdr->bitmap_granularity ); bool first = true; - for (uint64_t meta_pos = self.meta_block_size; meta_pos < self.meta_len; meta_pos += self.meta_block_size) + lseek64(this->fd, this->meta_offset, 0); + while (this->meta_pos < this->meta_len) { - for (uint64_t ioff = 0; ioff < self.meta_block_size-clean_entry_size; ioff += clean_entry_size, block_num++) + uint64_t read_len = buf_size < this->meta_len-this->meta_pos ? buf_size : this->meta_len-this->meta_pos; + read_blocking(this->fd, data, read_len); + this->meta_pos += read_len; + for (uint64_t blk = 0; blk < read_len; blk += this->meta_block_size) { - clean_disk_entry_v0_t *entry = (clean_disk_entry_v0_t*)(data + meta_pos + ioff); - if (entry->oid.inode) + for (uint64_t ioff = 0; ioff < this->meta_block_size-clean_entry_size; ioff += clean_entry_size, block_num++) { - printf( + clean_disk_entry *entry = (clean_disk_entry*)(data + blk + ioff); + if (entry->oid.inode) + { + printf( #define ENTRY_FMT "{\"block\":%lu,\"pool\":%u,\"inode\":%lu,\"stripe\":%lu,\"version\":%lu,\"bitmap\":\"" - (first ? ENTRY_FMT : (",\n" ENTRY_FMT)), + (first ? ENTRY_FMT : (",\n" ENTRY_FMT)), #undef ENTRY_FMT - block_num, INODE_POOL(entry->oid.inode), INODE_NO_POOL(entry->oid.inode), - entry->oid.stripe, entry->version - ); - first = false; - for (uint64_t i = 0; i < clean_entry_bitmap_size; i++) - { - printf("%02x", entry->bitmap[i]); + block_num, INODE_POOL(entry->oid.inode), INODE_NO_POOL(entry->oid.inode), + entry->oid.stripe, entry->version + ); + first = false; + for (uint64_t i = 0; i < clean_entry_bitmap_size; i++) + { + printf("%02x", entry->bitmap[i]); + } + printf("\",\"ext_bitmap\":\""); + for (uint64_t i = 0; i < clean_entry_bitmap_size; i++) + { + printf("%02x", entry->bitmap[clean_entry_bitmap_size + i]); + } + printf("\"}"); } - printf("\",\"ext_bitmap\":\""); - for (uint64_t i = 0; i < clean_entry_bitmap_size; i++) - { - printf("%02x", entry->bitmap[clean_entry_bitmap_size + i]); - } - printf("\"}"); } } } - printf("]}\n"); + printf("\n]}\n"); } else { - // Vitastor 0.4-0.5 - static array of clean_disk_entry_v0_t - uint64_t clean_entry_size = sizeof(clean_disk_entry_v0_t); + // Vitastor 0.4-0.5 - static array of clean_disk_entry + uint64_t clean_entry_size = sizeof(clean_disk_entry); uint64_t block_num = 0; - printf("{\"version\":\"0.5\",\"meta_block_size\":%u,\"entries\":[\n", self.meta_block_size); + printf("{\"version\":\"0.5\",\"meta_block_size\":%u,\"entries\":[\n", this->meta_block_size); bool first = true; - for (uint64_t meta_pos = 0; meta_pos < self.meta_len; meta_pos += self.meta_block_size) + while (this->meta_pos < this->meta_len) { - for (uint64_t ioff = 0; ioff < self.meta_block_size-clean_entry_size; ioff += clean_entry_size, block_num++) + uint64_t read_len = buf_size < this->meta_len-this->meta_pos ? buf_size : this->meta_len-this->meta_pos; + read_blocking(this->fd, data, read_len); + this->meta_pos += read_len; + for (uint64_t blk = 0; blk < read_len; blk += this->meta_block_size) { - clean_disk_entry_v0_t *entry = (clean_disk_entry_v0_t*)(data + meta_pos + ioff); - if (entry->oid.inode) + for (uint64_t ioff = 0; ioff < this->meta_block_size-clean_entry_size; ioff += clean_entry_size, block_num++) { - printf( + clean_disk_entry *entry = (clean_disk_entry*)(data + blk + ioff); + if (entry->oid.inode) + { + printf( #define ENTRY_FMT "{\"block\":%lu,\"pool\":%u,\"inode\":%lu,\"stripe\":%lu,\"version\":%lu}" - (first ? ENTRY_FMT : (",\n" ENTRY_FMT)), + (first ? ENTRY_FMT : (",\n" ENTRY_FMT)), #undef ENTRY_FMT - block_num, INODE_POOL(entry->oid.inode), INODE_NO_POOL(entry->oid.inode), - entry->oid.stripe, entry->version - ); - first = false; + block_num, INODE_POOL(entry->oid.inode), INODE_NO_POOL(entry->oid.inode), + entry->oid.stripe, entry->version + ); + first = false; + } } } } - printf("]}\n"); + printf("\n]}\n"); } free(data); + close(this->fd); + return 0; }