diff --git a/Makefile.in b/Makefile.in index 11267cc..8067de9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -106,7 +106,8 @@ SOURCE=\ DEVTOOLS_SOURCE=\ thin-provisioning/thin_generate_metadata.cc \ thin-provisioning/variable_chunk_stream.cc \ - thin-provisioning/thin_show_metadata.cc + thin-provisioning/thin_show_metadata.cc \ + ui/ui.cc ifeq ("@DEVTOOLS@", "yes") SOURCE+=$(DEVTOOLS_SOURCE) @@ -133,6 +134,10 @@ CXXFLAGS+=@LFS_FLAGS@ INCLUDES+=-I$(TOP_BUILDDIR) -I$(TOP_DIR) -I$(TOP_DIR)/thin-provisioning LIBS:=-laio -lexpat +ifeq ("@DEVTOOLS@", "yes") +LIBS+=-lncurses +endif + ifeq ("@STATIC_CXX@", "yes") CXXLIB+=-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic -Wl,--as-needed else diff --git a/VERSION b/VERSION index e6d527c..e1bde80 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.2-rc3 +0.7.0-dev diff --git a/thin-provisioning/superblock.cc b/thin-provisioning/superblock.cc index 9258b53..4f4f844 100644 --- a/thin-provisioning/superblock.cc +++ b/thin-provisioning/superblock.cc @@ -146,22 +146,32 @@ namespace thin_provisioning { } } - superblock_detail::superblock read_superblock(block_manager<>::ptr bm, block_address location) + superblock_detail::superblock read_superblock(block_manager<> const &bm, block_address location) { using namespace superblock_detail; superblock sb; - block_manager<>::read_ref r = bm->read_lock(location, superblock_validator()); + block_manager<>::read_ref r = bm.read_lock(location, superblock_validator()); superblock_disk const *sbd = reinterpret_cast(r.data()); superblock_traits::unpack(*sbd, sb); return sb; } + superblock_detail::superblock read_superblock(block_manager<>::ptr bm, block_address location) + { + return read_superblock(*bm, location); + } + superblock_detail::superblock read_superblock(block_manager<>::ptr bm) { return read_superblock(bm, SUPERBLOCK_LOCATION); } + superblock_detail::superblock read_superblock(block_manager<> const &bm) + { + return read_superblock(bm, SUPERBLOCK_LOCATION); + } + void write_superblock(block_manager<>::ptr bm, superblock_detail::superblock const &sb) { block_manager<>::write_ref w = bm->write_lock(SUPERBLOCK_LOCATION, superblock_validator()); diff --git a/thin-provisioning/superblock.h b/thin-provisioning/superblock.h index f527a15..5e1ba2c 100644 --- a/thin-provisioning/superblock.h +++ b/thin-provisioning/superblock.h @@ -128,6 +128,8 @@ namespace thin_provisioning { // FIXME: should we put init_superblock in here too? + // FIXME: make the bm const, and pass by reference rather than ptr + superblock_detail::superblock read_superblock(persistent_data::block_manager<> const &bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm); superblock_detail::superblock read_superblock(persistent_data::block_manager<>::ptr bm, persistent_data::block_address location); diff --git a/thin-provisioning/thin_show_metadata.cc b/thin-provisioning/thin_show_metadata.cc index 2a7140a..5d181c0 100644 --- a/thin-provisioning/thin_show_metadata.cc +++ b/thin-provisioning/thin_show_metadata.cc @@ -5,6 +5,7 @@ #include "thin-provisioning/commands.h" #include "thin-provisioning/metadata.h" #include "thin-provisioning/superblock.h" +#include "ui/ui.h" #include "version.h" #include @@ -12,82 +13,282 @@ #include #include #include +#include using namespace persistent_data; using namespace sm_disk_detail; using namespace std; using namespace thin_provisioning; +using namespace ui; //---------------------------------------------------------------- namespace { - bool is_superblock(block_manager<>::read_ref &rr) { - using namespace superblock_detail; + class examiner { + public: + examiner(string const &name, int colour_pair, char rep) + : name_(name), + colour_pair_(colour_pair), + rep_(rep) { + } - 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; + virtual ~examiner() {} + virtual bool recognise(block_manager<>::read_ref rr) const = 0; +// virtual void render_block(text_ui &ui, block_manager<>::read_ref rr) = 0; + + string const &get_name() const { + return name_; + } + + int get_color_pair() const { + return colour_pair_; + } + + char get_rep() const { + return rep_; + } + + private: + string name_; + int colour_pair_; + char rep_; + }; + + class raw_examiner : public examiner { + public: + raw_examiner() + : examiner("raw", 5, '?') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { 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_manager<>::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; + class superblock_examiner : public examiner { + public: + superblock_examiner() + : examiner("superblock", 1, 'S') { } - } + + virtual bool recognise(block_manager<>::read_ref rr) const { + 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; + } + }; + + class bitmap_examiner : public examiner { + public: + bitmap_examiner() + : examiner("bitmap", 2, ':') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { + 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); + } + }; + + class index_examiner : public examiner { + public: + index_examiner() + : examiner("index", 3, 'i') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { + 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_); + } + }; + + + class btree_examiner : public examiner { + public: + btree_examiner(string const &name, int colour_pair, char c) + : examiner(name, colour_pair, c) { + } + + bool is_btree_node(block_manager<>::read_ref rr) const { + 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); + } + }; + + class dev_detail_examiner : public btree_examiner { + public: + dev_detail_examiner() + : btree_examiner("dev_details", 4, 'd') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { + if (!btree_examiner::is_btree_node(rr)) + return false; + + using namespace btree_detail; + + disk_node const *data = reinterpret_cast(rr.data()); + node_header const *n = &data->header; + return to_cpu(n->value_size) == sizeof(device_tree_detail::device_details_disk); + } + }; + + class ref_count_examiner : public btree_examiner { + public: + ref_count_examiner() + : btree_examiner("ref_count node", 6, 'r') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { + if (!btree_examiner::is_btree_node(rr)) + return false; + + using namespace btree_detail; + + disk_node const *data = reinterpret_cast(rr.data()); + node_header const *n = &data->header; + return to_cpu(n->value_size) == sizeof(uint32_t); + } + }; + + class mapping_examiner : public btree_examiner { + public: + mapping_examiner() + : btree_examiner("mapping node", 7, 'm') { + } + + virtual bool recognise(block_manager<>::read_ref rr) const { + if (!btree_examiner::is_btree_node(rr)) + return false; + + using namespace btree_detail; + + disk_node const *data = reinterpret_cast(rr.data()); + node_header const *n = &data->header; + return to_cpu(n->value_size) == sizeof(uint64_t); + } + }; + + class main_dialog { + public: + main_dialog(text_ui &ui, + block_manager<> const &bm) + : ui_(ui), + bm_(bm), + raw_examiner_(new raw_examiner()) { + + examiners_.push_back(shared_ptr(new superblock_examiner())); + examiners_.push_back(shared_ptr(new bitmap_examiner())); + examiners_.push_back(shared_ptr(new index_examiner())); + examiners_.push_back(shared_ptr(new dev_detail_examiner())); + examiners_.push_back(shared_ptr(new ref_count_examiner())); + examiners_.push_back(shared_ptr(new mapping_examiner())); + } + + void run() { + auto line_length = 80; + for (block_address b = 0; b < 2000; b++) { + block_manager<>::read_ref rr = bm_.read_lock(b); + + if (!(b % line_length)) { + if (b > 0) + printw("\n"); + + printw("%8llu: ", b); + } + + auto e = find_examiner(rr); + attron(COLOR_PAIR(e->get_color_pair())); + printw("%c", e->get_rep()); + attroff(COLOR_PAIR(e->get_color_pair())); + } + + printw("\n"); + show_superblock(); + } + + private: + void show_superblock() { + auto sb = read_superblock(bm_); + + printw("\n\nSuperblock at 0\n"); + printw("data mapping root: %llu\n", sb.data_mapping_root_); + printw("device details root: %llu\n", sb.device_details_root_); + printw("data block size: %u\n", sb.data_block_size_); + printw("metadata nr blocks: %llu\n", sb.metadata_nr_blocks_); + } + + shared_ptr &find_examiner(block_manager<>::read_ref const &rr) { + for (shared_ptr &e : examiners_) { + if (e->recognise(rr)) + return e; + } + + return raw_examiner_; + } + + text_ui &ui_; + block_manager<> const &bm_; + list> examiners_; + shared_ptr raw_examiner_; + + +#if 0 + void show_superblock(text_ui &ui, superblock_detail::superblock const &sb) { + } + + void show_blocks(text_ui &ui, string const &dev) { + metadata md(bm); + + show_superblock(ui, md.sb_); + +#if 0 + 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; + } +#endif + } +#endif + }; } //---------------------------------------------------------------- @@ -135,7 +336,25 @@ thin_show_metadata_cmd::run(int argc, char **argv) } try { - show_blocks(argv[optind]); + ui::text_ui ui; + + block_manager<>::ptr bm = open_bm(argv[optind], block_manager<>::READ_ONLY, true); + main_dialog dialog(ui, *bm); + dialog.run(); +#if 0 +// show_blocks(ui, argv[optind]); +#endif + + +#if 0 + attron(COLOR_PAIR(1)); + printw("Hello, "); + attron(A_BOLD); + printw("world!\n"); + attroff(A_BOLD); + attroff(COLOR_PAIR(1)); +#endif + getch(); } catch (std::exception const &e) { cerr << e.what() << endl; diff --git a/ui/ui.cc b/ui/ui.cc new file mode 100644 index 0000000..2df3d6e --- /dev/null +++ b/ui/ui.cc @@ -0,0 +1,36 @@ +#include "ui/ui.h" + +#include + +using namespace ui; + +//---------------------------------------------------------------- + +text_ui::text_ui() +{ + initscr(); + noecho(); + + start_color(); + init_pair(1, COLOR_RED, COLOR_BLACK); + init_pair(2, COLOR_YELLOW, COLOR_BLACK); + init_pair(3, COLOR_BLUE, COLOR_BLACK); + init_pair(4, COLOR_GREEN, COLOR_BLACK); + init_pair(5, COLOR_YELLOW, COLOR_BLACK); + init_pair(6, COLOR_BLACK, COLOR_RED); + init_pair(7, COLOR_WHITE, COLOR_BLACK); + +} + +text_ui::~text_ui() +{ + endwin(); +} + +void +text_ui::refresh() +{ + refresh(); +} + +//---------------------------------------------------------------- diff --git a/ui/ui.h b/ui/ui.h new file mode 100644 index 0000000..75a2808 --- /dev/null +++ b/ui/ui.h @@ -0,0 +1,20 @@ +#ifndef UI_UI_H + +#include + +//---------------------------------------------------------------- + +namespace ui { + class text_ui { + public: + text_ui(); + ~text_ui(); + + void refresh(); + }; +}; + + +//---------------------------------------------------------------- + +#endif