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/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 aa70b9f..9c51921 100644
--- a/persistent-data/space-maps/disk.cc
+++ b/persistent-data/space-maps/disk.cc
@@ -794,4 +794,15 @@ persistent_data::index_validator() {
return bcache::validator::ptr(new index_block_validator());
}
+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 775ef7b..9edef6b 100644
--- a/persistent-data/space-maps/disk.h
+++ b/persistent-data/space-maps/disk.h
@@ -37,11 +37,14 @@ namespace persistent_data {
checked_space_map::ptr
open_metadata_sm(transaction_manager &tm, void *root);
- bcache::validator::ptr
- bitmap_validator();
+ bcache::validator::ptr bitmap_validator();
- bcache::validator::ptr
- index_validator();
+ bcache::validator::ptr index_validator();
+
+ // 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 9ba0614..0cca245 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,16 +240,12 @@ 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_.flags_,
md->sb_.version_,
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) {