diff --git a/README.md b/README.md index d23dae5..005ae50 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,28 @@ Once you've done this you can run the tests with a simple: Or specific tests with: cucumber features/thin_restore -n 'print help' + + +Dump Metadata +============= + +To dump the metadata of a live thin pool, you must first create a snapshot of +the metadata: + + $ dmsetup message vg001-mythinpool-tpool 0 reserve_metadata_snap + +Extract the metadata: + + $ sudo bin/thin_dump -m /dev/mapper/vg001-mythinpool_tmeta + + + + + + + + + +Finally, release the root: + + $ dmsetup message vg001-mythinpool-tpool 0 release_metadata_snap diff --git a/VERSION b/VERSION index 5070360..1f969e9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.2-rc5 +0.6.2-rc7 diff --git a/man8/thin_ls.8 b/man8/thin_ls.8 index 7d5081b..47607c6 100644 --- a/man8/thin_ls.8 +++ b/man8/thin_ls.8 @@ -19,8 +19,8 @@ This tool cannot be run on live metadata unless the \fB\-\-metadata\-snap\fP opt .IP "\fB\-o, \-\-format\fP" Give a comma separated list of the fields to be output. Valid fields are: DEV, MAPPED_BLOCKS, EXCLUSIVE_BLOCKS, SHARED_BLOCKS, MAPPED_SECTORS, -EXCLUSIVE_SECTORS, SHARED_SECTORS, MAPPED, EXCLUSIVE, SHARED, TRANSACTION -CREATE_TIME, SNAP_TIME +EXCLUSIVE_SECTORS, SHARED_SECTORS, MAPPED_BYTES, EXCLUSIVE_BYTES, +SHARED_BYTES, MAPPED, EXCLUSIVE, SHARED, TRANSACTION CREATE_TIME, SNAP_TIME .IP "\fB\-\-no\-headers\fP" Don't output headers. diff --git a/persistent-data/space-maps/disk.cc b/persistent-data/space-maps/disk.cc index e915eb4..9b1f9cc 100644 --- a/persistent-data/space-maps/disk.cc +++ b/persistent-data/space-maps/disk.cc @@ -773,4 +773,15 @@ persistent_data::open_metadata_sm(transaction_manager &tm, void *root) checked_space_map::ptr(new sm_disk(store, tm, v)))); } +block_address +persistent_data::get_nr_blocks_in_data_sm(transaction_manager &tm, void *root) +{ + sm_root_disk d; + sm_root v; + + ::memcpy(&d, root, sizeof(d)); + sm_root_traits::unpack(d, v); + return v.nr_blocks_; +} + //---------------------------------------------------------------- diff --git a/persistent-data/space-maps/disk.h b/persistent-data/space-maps/disk.h index 0a69f04..cb747e8 100644 --- a/persistent-data/space-maps/disk.h +++ b/persistent-data/space-maps/disk.h @@ -36,6 +36,11 @@ namespace persistent_data { checked_space_map::ptr open_metadata_sm(transaction_manager &tm, void *root); + + // Get the number of data blocks with minimal IO. Used when + // repairing to avoid the bulk of the space maps. + block_address + get_nr_blocks_in_data_sm(transaction_manager &tm, void *root); } //---------------------------------------------------------------- diff --git a/thin-provisioning/metadata_dumper.cc b/thin-provisioning/metadata_dumper.cc index 0c0fbe4..7bb9361 100644 --- a/thin-provisioning/metadata_dumper.cc +++ b/thin-provisioning/metadata_dumper.cc @@ -185,8 +185,13 @@ namespace { d.creation_time_, d.snapshotted_time_); - emit_mappings(tree_root); - + try { + emit_mappings(tree_root); + } catch (exception &e) { + cerr << e.what(); + e_->end_device(); + throw; + } e_->end_device(); } else if (!repair_) { @@ -211,6 +216,19 @@ namespace { bool repair_; mapping_tree_detail::damage_visitor::ptr damage_policy_; }; + + block_address get_nr_blocks(metadata::ptr md) { + if (md->data_sm_) + return md->data_sm_->get_nr_blocks(); + + else if (md->sb_.blocknr_ == superblock_detail::SUPERBLOCK_LOCATION) + // grab from the root structure of the space map + return get_nr_blocks_in_data_sm(*md->tm_, &md->sb_.data_space_map_root_); + + else + // metadata snap, we really don't know + return 0ull; + } } //---------------------------------------------------------------- @@ -222,14 +240,10 @@ thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, bool repair) device_tree_detail::damage_visitor::ptr dd_policy(details_damage_policy(repair)); walk_device_tree(*md->details_, de, *dd_policy); - // metadata snap doesn't have the space maps so we don't know how - // many data blocks there are. - block_address nr_data_blocks = md->data_sm_ ? md->data_sm_->get_nr_blocks() : 0; - e->begin_superblock("", md->sb_.time_, md->sb_.trans_id_, md->sb_.data_block_size_, - nr_data_blocks, + get_nr_blocks(md), boost::optional()); { diff --git a/thin-provisioning/thin_ls.cc b/thin-provisioning/thin_ls.cc index 869c7cf..4e0b97d 100644 --- a/thin-provisioning/thin_ls.cc +++ b/thin-provisioning/thin_ls.cc @@ -109,6 +109,10 @@ namespace { EXCLUSIVE_SECTORS, SHARED_SECTORS, + MAPPED_BYTES, + EXCLUSIVE_BYTES, + SHARED_BYTES, + MAPPED, EXCLUSIVE, SHARED, @@ -128,6 +132,10 @@ namespace { "EXCLUSIVE_SECTORS", "SHARED_SECTORS", + "MAPPED_BYTES", + "EXCLUSIVE_BYTES", + "SHARED_BYTES", + "MAPPED", "EXCLUSIVE", "SHARED", @@ -298,6 +306,8 @@ namespace { *it == SHARED_BLOCKS || *it == EXCLUSIVE_SECTORS || *it == SHARED_SECTORS || + *it == EXCLUSIVE_BYTES || + *it == SHARED_BYTES || *it == EXCLUSIVE || *it == SHARED) return true; @@ -375,6 +385,20 @@ namespace { grid.field((it->second.mapped_blocks_ - exclusive) * block_size); break; + case MAPPED_BYTES: + grid.field(it->second.mapped_blocks_ * block_size * + disk_unit_multiplier(UNIT_SECTOR)); + break; + + case EXCLUSIVE_BYTES: + grid.field(exclusive * block_size * + disk_unit_multiplier(UNIT_SECTOR)); + break; + + case SHARED_BYTES: + grid.field((it->second.mapped_blocks_ - exclusive) * block_size * + disk_unit_multiplier(UNIT_SECTOR)); + break; case MAPPED: grid.field( diff --git a/thin-provisioning/thin_repair.cc b/thin-provisioning/thin_repair.cc index 194f431..2741b78 100644 --- a/thin-provisioning/thin_repair.cc +++ b/thin-provisioning/thin_repair.cc @@ -23,7 +23,8 @@ namespace { emitter::ptr e = create_restore_emitter(new_md); block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY); - metadata::ptr old_md(new metadata(old_bm, false)); // we don't need to read the space maps + + metadata::ptr old_md(new metadata(old_bm, false)); metadata_dump(old_md, e, true); } catch (std::exception &e) {