From 38f8195a99606deb1d3ab25ab423a28528558317 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Wed, 19 Feb 2014 15:01:07 +0000 Subject: [PATCH] thin_show_blocks --- .gitignore | 1 + Makefile.in | 9 +- persistent-data/space-maps/disk.cc | 4 - persistent-data/space-maps/disk_structures.h | 3 + thin-provisioning/thin_show_blocks.cc | 139 +++++++++++++++++++ 5 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 thin-provisioning/thin_show_blocks.cc diff --git a/.gitignore b/.gitignore index fd2504f..c7afaf0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ thin_restore thin_repair thin_rmap thin_metadata_size +thin_show_blocks cache_check cache_dump diff --git a/Makefile.in b/Makefile.in index ca23474..70628a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,7 +35,8 @@ PROGRAMS=\ thin_restore \ thin_repair \ thin_rmap \ - thin_metadata_size + thin_metadata_size \ + thin_show_blocks all: $(PROGRAMS) @@ -162,6 +163,7 @@ lib/libpdata.a: $(PDATA_OBJECTS) # Thin provisioning tools THIN_DEBUG_SOURCE=$(SOURCE) +THIN_SHOW_BLOCKS_SOURCE=$(SOURCE) THIN_DUMP_SOURCE=$(SOURCE) THIN_REPAIR_SOURCE=$(SOURCE) THIN_RESTORE_SOURCE=$(SOURCE) @@ -209,6 +211,7 @@ THIN_RMAP_SOURCE=\ thin-provisioning/superblock.cc THIN_DEBUG_OBJECTS=$(subst .cc,.o,$(THIN_DEBUG_SOURCE)) +THIN_SHOW_BLOCKS_OBJECTS=$(subst .cc,.o,$(THIN_SHOW_BLOCKS_SOURCE)) THIN_DUMP_OBJECTS=$(subst .cc,.o,$(THIN_DUMP_SOURCE)) THIN_REPAIR_OBJECTS=$(subst .cc,.o,$(THIN_REPAIR_SOURCE)) THIN_RESTORE_OBJECTS=$(subst .cc,.o,$(THIN_RESTORE_SOURCE)) @@ -219,6 +222,10 @@ thin_debug: $(THIN_DEBUG_OBJECTS) thin-provisioning/thin_debug.o @echo " [LD] $@" $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) +thin_show_blocks: $(THIN_SHOW_BLOCKS_OBJECTS) thin-provisioning/thin_show_blocks.o + @echo " [LD] $@" + $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) + thin_repair: $(THIN_REPAIR_OBJECTS) thin-provisioning/thin_repair.o @echo " [LD] $@" $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) diff --git a/persistent-data/space-maps/disk.cc b/persistent-data/space-maps/disk.cc index 0c851f6..7192151 100644 --- a/persistent-data/space-maps/disk.cc +++ b/persistent-data/space-maps/disk.cc @@ -35,8 +35,6 @@ using namespace sm_disk_detail; //---------------------------------------------------------------- namespace { - uint64_t const BITMAP_CSUM_XOR = 240779; - struct bitmap_block_validator : public block_manager<>::validator { virtual void check(buffer<> const &b, block_address location) const { bitmap_header const *data = reinterpret_cast(&b); @@ -61,8 +59,6 @@ namespace { //-------------------------------- - uint64_t const INDEX_CSUM_XOR = 160478; - // FIXME: factor out the common code in these validators struct index_block_validator : public block_manager<>::validator { virtual void check(buffer<> const &b, block_address location) const { diff --git a/persistent-data/space-maps/disk_structures.h b/persistent-data/space-maps/disk_structures.h index 1429d36..e9ae8f6 100644 --- a/persistent-data/space-maps/disk_structures.h +++ b/persistent-data/space-maps/disk_structures.h @@ -110,6 +110,9 @@ namespace persistent_data { le32 not_used; le64 blocknr; } __attribute__ ((packed)); + + uint64_t const BITMAP_CSUM_XOR = 240779; + uint64_t const INDEX_CSUM_XOR = 160478; } } diff --git a/thin-provisioning/thin_show_blocks.cc b/thin-provisioning/thin_show_blocks.cc new file mode 100644 index 0000000..61debd7 --- /dev/null +++ b/thin-provisioning/thin_show_blocks.cc @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include + +#include "persistent-data/checksum.h" +#include "persistent-data/data-structures/btree.h" +#include "persistent-data/file_utils.h" +#include "persistent-data/space-maps/disk_structures.h" +#include "thin-provisioning/metadata.h" +#include "thin-provisioning/superblock.h" +#include "version.h" + +using namespace persistent_data; +using namespace std; +using namespace sm_disk_detail; +using namespace thin_provisioning; + +//---------------------------------------------------------------- + +namespace { + bool is_superblock(block_manager<>::read_ref &rr) { + using namespace superblock_detail; + + superblock_disk const *sbd = reinterpret_cast(&rr.data()); + if (to_cpu(sbd->magic_) == SUPERBLOCK_MAGIC) { + superblock sb; + superblock_traits::unpack(*sbd, sb); + cout << "metadata nr blocks: " << sb.metadata_nr_blocks_ << endl; + + return true; + } + + return false; + } + + bool is_bitmap_block(block_manager<>::read_ref &rr) { + bitmap_header const *data = reinterpret_cast(&rr.data()); + crc32c sum(BITMAP_CSUM_XOR); + sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t)); + return sum.get_sum() == to_cpu(data->csum); + } + + bool is_index_block(block_manager<>::read_ref &rr) { + metadata_index const *mi = reinterpret_cast(&rr.data()); + crc32c sum(INDEX_CSUM_XOR); + sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t)); + return sum.get_sum() == to_cpu(mi->csum_); + } + + bool is_btree_node(block_manager<>::read_ref &rr) { + using namespace btree_detail; + + disk_node const *data = reinterpret_cast(&rr.data()); + node_header const *n = &data->header; + crc32c sum(BTREE_CSUM_XOR); + sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t)); + return sum.get_sum() == to_cpu(n->csum); + } + + void show_blocks(string const &dev) { + block_manager<>::ptr bm = open_bm(dev, block_io<>::READ_ONLY); + + metadata md(bm, metadata::OPEN); + cout << "Metadata space map: nr_blocks = " << md.metadata_sm_->get_nr_blocks() + << ", nr_free_blocks = " << md.metadata_sm_->get_nr_free() + << endl; + cout << "Data space map: nr_blocks = " << md.data_sm_->get_nr_blocks() + << ", nr_free_blocks = " << md.data_sm_->get_nr_free() + << endl; + + block_address nr_blocks = bm->get_nr_blocks(); + for (block_address b = 0; b < nr_blocks; b++) { + block_manager<>::read_ref rr = bm->read_lock(b); + + if (is_superblock(rr)) + cout << b << ": superblock" << endl; + + else if (is_bitmap_block(rr)) + cout << b << ": bitmap block" << endl; + + else if (is_btree_node(rr)) + cout << b << ": btree_node" << endl; + + else + cout << b << ": unknown" << endl; + } + } + + void usage(ostream &out, string const &progname) { + out << "Usage: " << progname << " {device|file}" << endl + << "Options:" << endl + << " {-h|--help}" << endl + << " {-V|--version}" << endl; + } +} + +//---------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int c; + const char shortopts[] = "hV"; + const struct option longopts[] = { + { "help", no_argument, NULL, 'h'}, + { "version", no_argument, NULL, 'V'}, + { NULL, no_argument, NULL, 0 } + }; + + while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + switch(c) { + case 'h': + usage(cout, basename(argv[0])); + return 0; + + case 'V': + cerr << THIN_PROVISIONING_TOOLS_VERSION << endl; + return 0; + } + } + + if (argc == optind) { + usage(cerr, basename(argv[0])); + exit(1); + } + + try { + show_blocks(argv[optind]); + + } catch (std::exception const &e) { + cerr << e.what() << endl; + return 1; + } + + return 0; +} + +//----------------------------------------------------------------