Add some ftests, and fixup whitespace from Nikhil's work
This commit is contained in:
parent
cb055c90e5
commit
5f2c3bed69
@ -101,7 +101,7 @@ SOURCE=\
|
|||||||
thin-provisioning/metadata_checker.cc \
|
thin-provisioning/metadata_checker.cc \
|
||||||
thin-provisioning/metadata_counter.cc \
|
thin-provisioning/metadata_counter.cc \
|
||||||
thin-provisioning/metadata_dumper.cc \
|
thin-provisioning/metadata_dumper.cc \
|
||||||
thin-provisioning/override_emitter.cc \
|
thin-provisioning/override_emitter.cc \
|
||||||
thin-provisioning/pool_stream.cc \
|
thin-provisioning/pool_stream.cc \
|
||||||
thin-provisioning/restore_emitter.cc \
|
thin-provisioning/restore_emitter.cc \
|
||||||
thin-provisioning/rmap_visitor.cc \
|
thin-provisioning/rmap_visitor.cc \
|
||||||
|
@ -46,6 +46,9 @@ Options:
|
|||||||
{-h|--help}
|
{-h|--help}
|
||||||
{-i|--input} <input xml file>
|
{-i|--input} <input xml file>
|
||||||
{-o|--output} <output device or file>
|
{-o|--output} <output device or file>
|
||||||
|
{--transaction-id} <natural>
|
||||||
|
{--data-block-size} <natural>
|
||||||
|
{--nr-data-blocks} <natural>
|
||||||
{-q|--quiet}
|
{-q|--quiet}
|
||||||
{-V|--version}")
|
{-V|--version}")
|
||||||
|
|
||||||
|
@ -216,6 +216,33 @@
|
|||||||
(run-ok-rcv (stdout _) (thin-restore "-i" xml "-o" md "--quiet")
|
(run-ok-rcv (stdout _) (thin-restore "-i" xml "-o" md "--quiet")
|
||||||
(assert-eof stdout)))))
|
(assert-eof stdout)))))
|
||||||
|
|
||||||
|
(define-scenario (thin-restore override transaction-id)
|
||||||
|
"thin_restore obeys the --transaction-id override"
|
||||||
|
(with-empty-metadata (md)
|
||||||
|
(with-thin-xml (xml)
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-restore "--transaction-id 2345" "-i" xml "-o" md)
|
||||||
|
(assert-eof stderr))
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-dump md)
|
||||||
|
(assert-matches ".*transaction=\"2345\"" stdout)))))
|
||||||
|
|
||||||
|
(define-scenario (thin-restore override data-block-size)
|
||||||
|
"thin_restore obeys the --data-block-size override"
|
||||||
|
(with-empty-metadata (md)
|
||||||
|
(with-thin-xml (xml)
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-restore "--data-block-size 8192" "-i" xml "-o" md)
|
||||||
|
(assert-eof stderr))
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-dump md)
|
||||||
|
(assert-matches ".*data_block_size=\"8192\"" stdout)))))
|
||||||
|
|
||||||
|
(define-scenario (thin-restore override nr-data-blocks)
|
||||||
|
"thin_restore obeys the --nr-data-blocks override"
|
||||||
|
(with-empty-metadata (md)
|
||||||
|
(with-thin-xml (xml)
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-restore "--nr-data-blocks 234500" "-i" xml "-o" md)
|
||||||
|
(assert-eof stderr))
|
||||||
|
(run-ok-rcv (stdout stderr) (thin-dump md)
|
||||||
|
(assert-matches ".*nr_data_blocks=\"234500\"" stdout)))))
|
||||||
|
|
||||||
;;;-----------------------------------------------------------
|
;;;-----------------------------------------------------------
|
||||||
;;; thin_dump scenarios
|
;;; thin_dump scenarios
|
||||||
;;;-----------------------------------------------------------
|
;;;-----------------------------------------------------------
|
||||||
|
@ -39,8 +39,8 @@ OPTIONS
|
|||||||
This option may be specified multiple times to select more than one thin
|
This option may be specified multiple times to select more than one thin
|
||||||
device.
|
device.
|
||||||
|
|
||||||
--transaction-id {natural} Override the transaction id given in the input xml.
|
--transaction-id {natural} Override the transaction id given in the input xml.
|
||||||
--data-block-size {natural} Override the data block size given in the input xml.
|
--data-block-size {natural} Override the data block size given in the input xml.
|
||||||
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
||||||
|
|
||||||
--skip-mappings Do not dump the mappings.
|
--skip-mappings Do not dump the mappings.
|
||||||
|
@ -21,8 +21,8 @@ OPTIONS
|
|||||||
If a file is used for output, then it must be preallocated, and large
|
If a file is used for output, then it must be preallocated, and large
|
||||||
enough to hold the metadata.
|
enough to hold the metadata.
|
||||||
|
|
||||||
--transaction-id {natural} Override the transaction id given in the input xml.
|
--transaction-id {natural} Override the transaction id given in the input xml.
|
||||||
--data-block-size {natural} Override the data block size given in the input xml.
|
--data-block-size {natural} Override the data block size given in the input xml.
|
||||||
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
|
@ -23,8 +23,8 @@ OPTIONS
|
|||||||
If a file is used for output, then it must be preallocated, and large
|
If a file is used for output, then it must be preallocated, and large
|
||||||
enough to hold the metadata.
|
enough to hold the metadata.
|
||||||
|
|
||||||
--transaction-id {natural} Override the transaction id given in the input xml.
|
--transaction-id {natural} Override the transaction id given in the input xml.
|
||||||
--data-block-size {natural} Override the data block size given in the input xml.
|
--data-block-size {natural} Override the data block size given in the input xml.
|
||||||
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
--nr-data-blocks {natural} Override the nr data blocks given in the input xml.
|
||||||
|
|
||||||
EXAMPLE
|
EXAMPLE
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
using namespace base;
|
using namespace base;
|
||||||
using namespace thin_provisioning;
|
using namespace thin_provisioning;
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -276,20 +276,19 @@ namespace {
|
|||||||
|
|
||||||
class gatherer {
|
class gatherer {
|
||||||
public:
|
public:
|
||||||
gatherer(block_manager<> &bm)
|
gatherer(block_manager<> &bm)
|
||||||
: bm_(bm),
|
: bm_(bm),
|
||||||
referenced_(bm.get_nr_blocks(), false),
|
referenced_(bm.get_nr_blocks(), false),
|
||||||
examined_(bm.get_nr_blocks(), false) {
|
examined_(bm.get_nr_blocks(), false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct roots {
|
struct roots {
|
||||||
block_address mapping_root;
|
block_address mapping_root;
|
||||||
block_address detail_root;
|
block_address detail_root;
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
};
|
};
|
||||||
|
|
||||||
optional<roots>
|
|
||||||
|
|
||||||
|
optional<roots>
|
||||||
find_best_roots(transaction_manager &tm) {
|
find_best_roots(transaction_manager &tm) {
|
||||||
vector<node_info> mapping_roots;
|
vector<node_info> mapping_roots;
|
||||||
vector<node_info> device_roots;
|
vector<node_info> device_roots;
|
||||||
@ -304,16 +303,16 @@ namespace {
|
|||||||
|
|
||||||
auto info = get_info(b);
|
auto info = get_info(b);
|
||||||
|
|
||||||
if (info.valid) {
|
if (info.valid) {
|
||||||
if (info.type == TOP_LEVEL) {
|
if (info.type == TOP_LEVEL) {
|
||||||
mapping_roots.push_back(info);
|
mapping_roots.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (info.type == DEVICE_DETAILS) {
|
else if (info.type == DEVICE_DETAILS) {
|
||||||
device_roots.push_back(info);
|
device_roots.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SHOW_WORKING
|
#if SHOW_WORKING
|
||||||
cerr << "mapping candidates (" << mapping_roots.size() << "):\n";
|
cerr << "mapping candidates (" << mapping_roots.size() << "):\n";
|
||||||
@ -332,27 +331,27 @@ namespace {
|
|||||||
cerr << "(" << p.first << ", " << p.second << ")\n";
|
cerr << "(" << p.first << ", " << p.second << ")\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pairs.size())
|
if (pairs.size())
|
||||||
return mk_roots(pairs[0]);
|
return mk_roots(pairs[0]);
|
||||||
else
|
else
|
||||||
return optional<roots>();
|
return optional<roots>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t get_time(block_address b) const {
|
uint32_t get_time(block_address b) const {
|
||||||
auto i = lookup_info(b);
|
auto i = lookup_info(b);
|
||||||
return i ? i->age : 0;
|
return i ? i->age : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
roots mk_roots(pair<block_address, block_address> const &p) {
|
roots mk_roots(pair<block_address, block_address> const &p) {
|
||||||
roots r;
|
roots r;
|
||||||
|
|
||||||
r.mapping_root = p.second;
|
r.mapping_root = p.second;
|
||||||
r.detail_root = p.first;
|
r.detail_root = p.first;
|
||||||
r.time = max<block_address>(get_time(p.first), get_time(p.second));
|
r.time = max<block_address>(get_time(p.first), get_time(p.second));
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_eq(set<uint32_t> const &lhs, set<uint32_t> const &rhs) {
|
bool set_eq(set<uint32_t> const &lhs, set<uint32_t> const &rhs) {
|
||||||
for (auto v : lhs)
|
for (auto v : lhs)
|
||||||
@ -624,14 +623,13 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<node_info> lookup_info(block_address b) const {
|
optional<node_info> lookup_info(block_address b) const {
|
||||||
auto it = infos_.find(b);
|
auto it = infos_.find(b);
|
||||||
if (it == infos_.end())
|
if (it == infos_.end())
|
||||||
return optional<node_info>();
|
return optional<node_info>();
|
||||||
|
|
||||||
return optional<node_info>(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return optional<node_info>(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
block_manager<> &bm_;
|
block_manager<> &bm_;
|
||||||
vector<bool> referenced_;
|
vector<bool> referenced_;
|
||||||
@ -779,102 +777,102 @@ namespace {
|
|||||||
return 0ull;
|
return 0ull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
void
|
emit_trees_(block_manager<>::ptr bm, superblock_detail::superblock const &sb,
|
||||||
emit_trees_(block_manager<>::ptr bm, superblock_detail::superblock const &sb,
|
|
||||||
emitter::ptr e, override_options const &ropts)
|
emitter::ptr e, override_options const &ropts)
|
||||||
{
|
{
|
||||||
metadata md(bm, sb);
|
metadata md(bm, sb);
|
||||||
dump_options opts;
|
dump_options opts;
|
||||||
details_extractor de(opts);
|
details_extractor de(opts);
|
||||||
device_tree_detail::damage_visitor::ptr dd_policy(details_damage_policy(true));
|
device_tree_detail::damage_visitor::ptr dd_policy(details_damage_policy(true));
|
||||||
walk_device_tree(*md.details_, de, *dd_policy);
|
walk_device_tree(*md.details_, de, *dd_policy);
|
||||||
|
|
||||||
e->begin_superblock("", sb.time_,
|
e->begin_superblock("", sb.time_,
|
||||||
sb.trans_id_,
|
sb.trans_id_,
|
||||||
sb.flags_,
|
sb.flags_,
|
||||||
sb.version_,
|
sb.version_,
|
||||||
sb.data_block_size_,
|
sb.data_block_size_,
|
||||||
get_nr_blocks(md),
|
get_nr_blocks(md),
|
||||||
boost::optional<block_address>());
|
boost::optional<block_address>());
|
||||||
|
|
||||||
{
|
{
|
||||||
mapping_tree_detail::damage_visitor::ptr md_policy(mapping_damage_policy(true));
|
mapping_tree_detail::damage_visitor::ptr md_policy(mapping_damage_policy(true));
|
||||||
mapping_tree_emit_visitor mte(opts, *md.tm_, e, de.get_details(), mapping_damage_policy(true));
|
mapping_tree_emit_visitor mte(opts, *md.tm_, e, de.get_details(), mapping_damage_policy(true));
|
||||||
walk_mapping_tree(*md.mappings_top_level_, mte, *md_policy);
|
walk_mapping_tree(*md.mappings_top_level_, mte, *md_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
e->end_superblock();
|
e->end_superblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
find_better_roots_(block_manager<>::ptr bm, superblock_detail::superblock &sb)
|
find_better_roots_(block_manager<>::ptr bm, superblock_detail::superblock &sb)
|
||||||
{
|
{
|
||||||
// We assume the superblock is wrong, and find the best roots
|
// We assume the superblock is wrong, and find the best roots
|
||||||
// for ourselves. We've had a few cases where people have
|
// for ourselves. We've had a few cases where people have
|
||||||
// activated a pool on multiple hosts at once, which results in
|
// activated a pool on multiple hosts at once, which results in
|
||||||
// the superblock being over written.
|
// the superblock being over written.
|
||||||
gatherer g(*bm);
|
gatherer g(*bm);
|
||||||
auto tm = open_tm(bm, superblock_detail::SUPERBLOCK_LOCATION);
|
auto tm = open_tm(bm, superblock_detail::SUPERBLOCK_LOCATION);
|
||||||
auto p = g.find_best_roots(*tm);
|
auto p = g.find_best_roots(*tm);
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
sb.metadata_snap_ = 0;
|
sb.metadata_snap_ = 0;
|
||||||
sb.time_ = p->time;
|
sb.time_ = p->time;
|
||||||
sb.device_details_root_ = p->detail_root;
|
sb.device_details_root_ = p->detail_root;
|
||||||
sb.data_mapping_root_ = p->mapping_root;
|
sb.data_mapping_root_ = p->mapping_root;
|
||||||
sb.metadata_nr_blocks_ = bm->get_nr_blocks();
|
sb.metadata_nr_blocks_ = bm->get_nr_blocks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
superblock_detail::superblock
|
|
||||||
recreate_superblock(override_options const &opts)
|
|
||||||
{
|
|
||||||
superblock_detail::superblock sb;
|
|
||||||
memset(&sb, 0, sizeof(sb));
|
|
||||||
|
|
||||||
// FIXME: we need to get this by walking both the mapping and device trees.
|
|
||||||
sb.time_ = 100000;
|
|
||||||
|
|
||||||
|
|
||||||
sb.trans_id_ = opts.get_transaction_id();
|
|
||||||
sb.version_ = superblock_detail::METADATA_VERSION;
|
|
||||||
sb.data_block_size_ = opts.get_data_block_size();
|
|
||||||
|
|
||||||
// Check that this has been overridden.
|
superblock_detail::superblock
|
||||||
opts.get_nr_data_blocks();
|
recreate_superblock(override_options const &opts)
|
||||||
|
{
|
||||||
|
superblock_detail::superblock sb;
|
||||||
|
memset(&sb, 0, sizeof(sb));
|
||||||
|
|
||||||
return sb;
|
// FIXME: we need to get this by walking both the mapping and device trees.
|
||||||
}
|
sb.time_ = 100000;
|
||||||
|
|
||||||
optional<superblock_detail::superblock>
|
|
||||||
maybe_read_superblock(block_manager<>::ptr bm)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
auto sb = read_superblock(bm);
|
|
||||||
return optional<superblock_detail::superblock>(sb);
|
|
||||||
} catch (...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return optional<superblock_detail::superblock>();
|
sb.trans_id_ = opts.get_transaction_id();
|
||||||
}
|
sb.version_ = superblock_detail::METADATA_VERSION;
|
||||||
|
sb.data_block_size_ = opts.get_data_block_size();
|
||||||
|
|
||||||
void
|
// Check that this has been overridden.
|
||||||
metadata_repair_(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts)
|
opts.get_nr_data_blocks();
|
||||||
{
|
|
||||||
auto msb = maybe_read_superblock(bm);
|
|
||||||
if (!msb)
|
|
||||||
msb = recreate_superblock(opts);
|
|
||||||
|
|
||||||
auto tm = open_tm(bm, superblock_detail::SUPERBLOCK_LOCATION);
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
if (!get_dev_ids(*tm, msb->device_details_root_) ||
|
optional<superblock_detail::superblock>
|
||||||
!get_map_ids(*tm, msb->data_mapping_root_))
|
maybe_read_superblock(block_manager<>::ptr bm)
|
||||||
find_better_roots_(bm, *msb);
|
{
|
||||||
|
try {
|
||||||
|
auto sb = read_superblock(bm);
|
||||||
|
return optional<superblock_detail::superblock>(sb);
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
|
||||||
emit_trees_(bm, *msb, e, opts);
|
return optional<superblock_detail::superblock>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
metadata_repair_(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts)
|
||||||
|
{
|
||||||
|
auto msb = maybe_read_superblock(bm);
|
||||||
|
if (!msb)
|
||||||
|
msb = recreate_superblock(opts);
|
||||||
|
|
||||||
|
auto tm = open_tm(bm, superblock_detail::SUPERBLOCK_LOCATION);
|
||||||
|
|
||||||
|
if (!get_dev_ids(*tm, msb->device_details_root_) ||
|
||||||
|
!get_map_ids(*tm, msb->data_mapping_root_))
|
||||||
|
find_better_roots_(bm, *msb);
|
||||||
|
|
||||||
|
emit_trees_(bm, *msb, e, opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -906,15 +904,15 @@ thin_provisioning::metadata_dump(metadata::ptr md, emitter::ptr e, dump_options
|
|||||||
void
|
void
|
||||||
thin_provisioning::metadata_repair(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts)
|
thin_provisioning::metadata_repair(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
metadata_repair_(bm, e, opts);
|
metadata_repair_(bm, e, opts);
|
||||||
|
|
||||||
} catch (override_error const &e) {
|
} catch (override_error const &e) {
|
||||||
ostringstream out;
|
ostringstream out;
|
||||||
out << "The following field needs to be provided on the command line due to corruption in the superblock: "
|
out << "The following field needs to be provided on the command line due to corruption in the superblock: "
|
||||||
<< e.what();
|
<< e.what();
|
||||||
throw runtime_error(out.str());
|
throw runtime_error(out.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -47,8 +47,7 @@ namespace thin_provisioning {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool skip_mappings_;
|
bool skip_mappings_;
|
||||||
override_options overrides_;
|
override_options overrides_;
|
||||||
|
|
||||||
|
|
||||||
using dev_set = std::set<uint64_t>;
|
using dev_set = std::set<uint64_t>;
|
||||||
using maybe_dev_set = boost::optional<dev_set>;
|
using maybe_dev_set = boost::optional<dev_set>;
|
||||||
@ -61,10 +60,10 @@ namespace thin_provisioning {
|
|||||||
// corruption encountered will cause an exception to be thrown.
|
// corruption encountered will cause an exception to be thrown.
|
||||||
void metadata_dump(metadata::ptr md, emitter::ptr e, dump_options const &opts);
|
void metadata_dump(metadata::ptr md, emitter::ptr e, dump_options const &opts);
|
||||||
|
|
||||||
// We have to provide a different interface for repairing, since
|
// We have to provide a different interface for repairing, since
|
||||||
// the superblock itself may be corrupt, so we wont be able
|
// the superblock itself may be corrupt, so we wont be able
|
||||||
// to create the metadata object.
|
// to create the metadata object.
|
||||||
void metadata_repair(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts);
|
void metadata_repair(block_manager<>::ptr bm, emitter::ptr e, override_options const &opts);
|
||||||
|
|
||||||
// Only used by ll_restore, so we leave the repair arg
|
// Only used by ll_restore, so we leave the repair arg
|
||||||
void metadata_dump_subtree(metadata::ptr md, emitter::ptr e, bool repair, uint64_t subtree_root);
|
void metadata_dump_subtree(metadata::ptr md, emitter::ptr e, bool repair, uint64_t subtree_root);
|
||||||
|
@ -23,72 +23,72 @@ using namespace thin_provisioning;
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class override_emitter : public emitter {
|
class override_emitter : public emitter {
|
||||||
public:
|
public:
|
||||||
override_emitter(emitter::ptr inner, override_options const &opts)
|
override_emitter(emitter::ptr inner, override_options const &opts)
|
||||||
: inner_(inner),
|
: inner_(inner),
|
||||||
opts_(opts) {
|
opts_(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void begin_superblock(std::string const &uuid,
|
virtual void begin_superblock(std::string const &uuid,
|
||||||
uint64_t time,
|
uint64_t time,
|
||||||
uint64_t trans_id,
|
uint64_t trans_id,
|
||||||
boost::optional<uint32_t> flags,
|
boost::optional<uint32_t> flags,
|
||||||
boost::optional<uint32_t> version,
|
boost::optional<uint32_t> version,
|
||||||
uint32_t data_block_size,
|
uint32_t data_block_size,
|
||||||
uint64_t nr_data_blocks,
|
uint64_t nr_data_blocks,
|
||||||
boost::optional<uint64_t> metadata_snap) {
|
boost::optional<uint64_t> metadata_snap) {
|
||||||
inner_->begin_superblock(uuid, time, opts_.get_transaction_id(trans_id),
|
inner_->begin_superblock(uuid, time, opts_.get_transaction_id(trans_id),
|
||||||
flags, version, opts_.get_data_block_size(data_block_size),
|
flags, version, opts_.get_data_block_size(data_block_size),
|
||||||
opts_.get_nr_data_blocks(nr_data_blocks),
|
opts_.get_nr_data_blocks(nr_data_blocks),
|
||||||
metadata_snap);
|
metadata_snap);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void end_superblock() {
|
virtual void end_superblock() {
|
||||||
inner_->end_superblock();
|
inner_->end_superblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void begin_device(uint32_t dev,
|
virtual void begin_device(uint32_t dev,
|
||||||
uint64_t mapped_blocks,
|
uint64_t mapped_blocks,
|
||||||
uint64_t trans_id,
|
uint64_t trans_id,
|
||||||
uint64_t creation_time,
|
uint64_t creation_time,
|
||||||
uint64_t snap_time) {
|
uint64_t snap_time) {
|
||||||
inner_->begin_device(dev, mapped_blocks, trans_id, creation_time, snap_time);
|
inner_->begin_device(dev, mapped_blocks, trans_id, creation_time, snap_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void end_device() {
|
virtual void end_device() {
|
||||||
inner_->end_device();
|
inner_->end_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void begin_named_mapping(std::string const &name) {
|
virtual void begin_named_mapping(std::string const &name) {
|
||||||
inner_->begin_named_mapping(name);
|
inner_->begin_named_mapping(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void end_named_mapping() {
|
virtual void end_named_mapping() {
|
||||||
inner_->end_named_mapping();
|
inner_->end_named_mapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void identifier(std::string const &name) {
|
virtual void identifier(std::string const &name) {
|
||||||
inner_->identifier(name);
|
inner_->identifier(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void range_map(uint64_t origin_begin, uint64_t data_begin, uint32_t time, uint64_t len) {
|
virtual void range_map(uint64_t origin_begin, uint64_t data_begin, uint32_t time, uint64_t len) {
|
||||||
inner_->range_map(origin_begin, data_begin, time, len);
|
inner_->range_map(origin_begin, data_begin, time, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) {
|
virtual void single_map(uint64_t origin_block, uint64_t data_block, uint32_t time) {
|
||||||
inner_->single_map(origin_block, data_block, time);
|
inner_->single_map(origin_block, data_block, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
emitter::ptr inner_;
|
emitter::ptr inner_;
|
||||||
override_options opts_;
|
override_options opts_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
emitter::ptr thin_provisioning::create_override_emitter(emitter::ptr inner, override_options const &opts)
|
emitter::ptr thin_provisioning::create_override_emitter(emitter::ptr inner, override_options const &opts)
|
||||||
{
|
{
|
||||||
return emitter::ptr(new override_emitter(inner, opts));
|
return emitter::ptr(new override_emitter(inner, opts));
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -28,56 +28,57 @@
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace thin_provisioning {
|
namespace thin_provisioning {
|
||||||
struct override_error : public std::runtime_error {
|
struct override_error : public std::runtime_error {
|
||||||
override_error(std::string const &str)
|
override_error(std::string const &str)
|
||||||
: std::runtime_error(str) {
|
: std::runtime_error(str) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct override_options {
|
struct override_options {
|
||||||
uint64_t get_transaction_id() const {
|
uint64_t get_transaction_id() const {
|
||||||
if (!transaction_id_)
|
if (!transaction_id_)
|
||||||
bad_override_("transaction id");
|
bad_override_("transaction id");
|
||||||
|
|
||||||
return *transaction_id_;
|
return *transaction_id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t get_transaction_id(uint64_t dflt) const {
|
uint64_t get_transaction_id(uint64_t dflt) const {
|
||||||
return transaction_id_ ? *transaction_id_ : dflt;
|
return transaction_id_ ? *transaction_id_ : dflt;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_data_block_size() const {
|
uint32_t get_data_block_size() const {
|
||||||
if (!data_block_size_)
|
if (!data_block_size_)
|
||||||
bad_override_("data block size");
|
bad_override_("data block size");
|
||||||
|
|
||||||
return *data_block_size_;
|
return *data_block_size_;
|
||||||
}
|
}
|
||||||
uint32_t get_data_block_size(uint32_t dflt) const {
|
|
||||||
return data_block_size_ ? *data_block_size_ : dflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t get_nr_data_blocks() const {
|
uint32_t get_data_block_size(uint32_t dflt) const {
|
||||||
if (!nr_data_blocks_)
|
return data_block_size_ ? *data_block_size_ : dflt;
|
||||||
bad_override_("nr data blocks");
|
}
|
||||||
|
|
||||||
return *nr_data_blocks_;
|
uint64_t get_nr_data_blocks() const {
|
||||||
}
|
if (!nr_data_blocks_)
|
||||||
|
bad_override_("nr data blocks");
|
||||||
|
|
||||||
uint64_t get_nr_data_blocks(uint64_t dflt) const {
|
return *nr_data_blocks_;
|
||||||
return nr_data_blocks_ ? *nr_data_blocks_ : dflt;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<uint64_t> transaction_id_;
|
uint64_t get_nr_data_blocks(uint64_t dflt) const {
|
||||||
boost::optional<uint32_t> data_block_size_;
|
return nr_data_blocks_ ? *nr_data_blocks_ : dflt;
|
||||||
boost::optional<uint64_t> nr_data_blocks_;
|
}
|
||||||
|
|
||||||
private:
|
boost::optional<uint64_t> transaction_id_;
|
||||||
void bad_override_(std::string const &field) const {
|
boost::optional<uint32_t> data_block_size_;
|
||||||
throw override_error(field);
|
boost::optional<uint64_t> nr_data_blocks_;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
emitter::ptr create_override_emitter(emitter::ptr inner, override_options const &opts);
|
private:
|
||||||
|
void bad_override_(std::string const &field) const {
|
||||||
|
throw override_error(field);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
emitter::ptr create_override_emitter(emitter::ptr inner, override_options const &opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -156,7 +156,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
metadata::ptr md_;
|
metadata::ptr md_;
|
||||||
override_options opts_;
|
override_options opts_;
|
||||||
|
|
||||||
bool in_superblock_;
|
bool in_superblock_;
|
||||||
block_address nr_data_blocks_;
|
block_address nr_data_blocks_;
|
||||||
|
@ -97,8 +97,7 @@ namespace thin_provisioning {
|
|||||||
|
|
||||||
block_address const SUPERBLOCK_LOCATION = 0;
|
block_address const SUPERBLOCK_LOCATION = 0;
|
||||||
uint32_t const SUPERBLOCK_MAGIC = 27022010;
|
uint32_t const SUPERBLOCK_MAGIC = 27022010;
|
||||||
uint32_t const METADATA_VERSION = 2;
|
uint32_t const METADATA_VERSION = 2;
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------
|
//--------------------------------
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "thin-provisioning/human_readable_format.h"
|
#include "thin-provisioning/human_readable_format.h"
|
||||||
#include "thin-provisioning/metadata.h"
|
#include "thin-provisioning/metadata.h"
|
||||||
#include "thin-provisioning/metadata_dumper.h"
|
#include "thin-provisioning/metadata_dumper.h"
|
||||||
|
#include "thin-provisioning/override_emitter.h"
|
||||||
#include "thin-provisioning/shared_library_emitter.h"
|
#include "thin-provisioning/shared_library_emitter.h"
|
||||||
#include "thin-provisioning/xml_format.h"
|
#include "thin-provisioning/xml_format.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
@ -84,35 +85,34 @@ namespace {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dump_(string const &path, ostream &out, struct flags &flags) {
|
int dump_(string const &path, ostream &out, struct flags &flags) {
|
||||||
try {
|
try {
|
||||||
emitter::ptr inner = create_emitter(flags.format, out);
|
emitter::ptr inner = create_emitter(flags.format, out);
|
||||||
emitter::ptr e = create_override_emitter(inner, flags.opts.overrides_);
|
emitter::ptr e = create_override_emitter(inner, flags.opts.overrides_);
|
||||||
|
|
||||||
if (flags.repair) {
|
if (flags.repair) {
|
||||||
auto bm = open_bm(path, block_manager<>::READ_ONLY, true);
|
auto bm = open_bm(path, block_manager<>::READ_ONLY, true);
|
||||||
metadata_repair(bm, e, flags.opts.overrides_);
|
metadata_repair(bm, e, flags.opts.overrides_);
|
||||||
} else {
|
} else {
|
||||||
metadata::ptr md = open_metadata(path, flags);
|
metadata::ptr md = open_metadata(path, flags);
|
||||||
metadata_dump(md, e, flags.opts);
|
metadata_dump(md, e, flags.opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
cerr << e.what() << endl;
|
cerr << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dump(string const &path, char const *output, struct flags &flags) {
|
|
||||||
if (output) {
|
|
||||||
ofstream out(output);
|
|
||||||
return dump_(path, out, flags);
|
|
||||||
} else
|
|
||||||
return dump_(path, cout, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int dump(string const &path, char const *output, struct flags &flags) {
|
||||||
|
if (output) {
|
||||||
|
ofstream out(output);
|
||||||
|
return dump_(path, out, flags);
|
||||||
|
} else
|
||||||
|
return dump_(path, cout, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -156,6 +156,9 @@ thin_dump_cmd::run(int argc, char **argv)
|
|||||||
{ "repair", no_argument, NULL, 'r'},
|
{ "repair", no_argument, NULL, 'r'},
|
||||||
{ "dev-id", required_argument, NULL, 1 },
|
{ "dev-id", required_argument, NULL, 1 },
|
||||||
{ "skip-mappings", no_argument, NULL, 2 },
|
{ "skip-mappings", no_argument, NULL, 2 },
|
||||||
|
{ "transaction-id", required_argument, NULL, 3 },
|
||||||
|
{ "data-block-size", required_argument, NULL, 4 },
|
||||||
|
{ "nr-data-blocks", required_argument, NULL, 5 },
|
||||||
{ "version", no_argument, NULL, 'V'},
|
{ "version", no_argument, NULL, 'V'},
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
@ -207,17 +210,17 @@ thin_dump_cmd::run(int argc, char **argv)
|
|||||||
flags.opts.skip_mappings_ = true;
|
flags.opts.skip_mappings_ = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
flags.opts.overrides_.transaction_id_ = parse_uint64(optarg, "transaction id");
|
flags.opts.overrides_.transaction_id_ = parse_uint64(optarg, "transaction id");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
flags.opts.overrides_.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
flags.opts.overrides_.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
flags.opts.overrides_.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
flags.opts.overrides_.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "base/output_file_requirements.h"
|
#include "base/output_file_requirements.h"
|
||||||
#include "persistent-data/file_utils.h"
|
#include "persistent-data/file_utils.h"
|
||||||
#include "thin-provisioning/commands.h"
|
#include "thin-provisioning/commands.h"
|
||||||
|
#include "thin-provisioning/override_emitter.h"
|
||||||
#include "human_readable_format.h"
|
#include "human_readable_format.h"
|
||||||
#include "metadata_dumper.h"
|
#include "metadata_dumper.h"
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
@ -17,28 +18,28 @@ using namespace std;
|
|||||||
using namespace thin_provisioning;
|
using namespace thin_provisioning;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int repair(string const &old_path, string const &new_path, override_options const &opts) {
|
int repair(string const &old_path, string const &new_path, override_options const &opts) {
|
||||||
bool metadata_touched = false;
|
bool metadata_touched = false;
|
||||||
try {
|
try {
|
||||||
// block size gets updated by the restorer
|
// block size gets updated by the restorer
|
||||||
block_manager<>::ptr new_bm = open_bm(new_path, block_manager<>::READ_WRITE);
|
block_manager<>::ptr new_bm = open_bm(new_path, block_manager<>::READ_WRITE);
|
||||||
file_utils::check_file_exists(old_path, false);
|
file_utils::check_file_exists(old_path, false);
|
||||||
metadata_touched = true;
|
metadata_touched = true;
|
||||||
metadata::ptr new_md(new metadata(new_bm, metadata::CREATE, 128, 0));
|
metadata::ptr new_md(new metadata(new_bm, metadata::CREATE, 128, 0));
|
||||||
emitter::ptr inner = create_restore_emitter(new_md);
|
emitter::ptr inner = create_restore_emitter(new_md);
|
||||||
emitter::ptr e = create_override_emitter(inner, opts);
|
emitter::ptr e = create_override_emitter(inner, opts);
|
||||||
block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY);
|
block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY);
|
||||||
metadata_repair(old_bm, e, opts);
|
metadata_repair(old_bm, e, opts);
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
if (metadata_touched)
|
if (metadata_touched)
|
||||||
file_utils::zero_superblock(new_path);
|
file_utils::zero_superblock(new_path);
|
||||||
cerr << e.what() << endl;
|
cerr << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -51,15 +52,15 @@ thin_repair_cmd::thin_repair_cmd()
|
|||||||
void
|
void
|
||||||
thin_repair_cmd::usage(std::ostream &out) const
|
thin_repair_cmd::usage(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << "Usage: " << get_name() << " [options] {device|file}" << endl
|
out << "Usage: " << get_name() << " [options] {device|file}" << endl
|
||||||
<< "Options:" << endl
|
<< "Options:" << endl
|
||||||
<< " {-h|--help}" << endl
|
<< " {-h|--help}" << endl
|
||||||
<< " {-i|--input} <input metadata (binary format)>" << endl
|
<< " {-i|--input} <input metadata (binary format)>" << endl
|
||||||
<< " {-o|--output} <output metadata (binary format)>" << endl
|
<< " {-o|--output} <output metadata (binary format)>" << endl
|
||||||
<< " {--transaction-id} <natural>" << endl
|
<< " {--transaction-id} <natural>" << endl
|
||||||
<< " {--data-block-size} <natural>" << endl
|
<< " {--data-block-size} <natural>" << endl
|
||||||
<< " {--nr-data-blocks} <natural>" << endl
|
<< " {--nr-data-blocks} <natural>" << endl
|
||||||
<< " {-V|--version}" << endl;
|
<< " {-V|--version}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -67,56 +68,55 @@ thin_repair_cmd::run(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
boost::optional<string> input_path, output_path;
|
boost::optional<string> input_path, output_path;
|
||||||
override_options opts;
|
override_options opts;
|
||||||
|
|
||||||
const char shortopts[] = "hi:o:V";
|
const char shortopts[] = "hi:o:V";
|
||||||
|
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
{ "help", no_argument, NULL, 'h'},
|
{ "help", no_argument, NULL, 'h'},
|
||||||
{ "input", required_argument, NULL, 'i'},
|
{ "input", required_argument, NULL, 'i'},
|
||||||
{ "output", required_argument, NULL, 'o'},
|
{ "output", required_argument, NULL, 'o'},
|
||||||
{ "transaction-id", required_argument, NULL, 1},
|
{ "transaction-id", required_argument, NULL, 1},
|
||||||
{ "data-block-size", required_argument, NULL, 2},
|
{ "data-block-size", required_argument, NULL, 2},
|
||||||
{ "nr-data-blocks", required_argument, NULL, 3},
|
{ "nr-data-blocks", required_argument, NULL, 3},
|
||||||
{ "version", no_argument, NULL, 'V'},
|
{ "version", no_argument, NULL, 'V'},
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(cout);
|
usage(cout);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
input_path = optarg;
|
input_path = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
output_path = optarg;
|
output_path = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
opts.transaction_id_ = parse_uint64(optarg, "transaction id");
|
opts.transaction_id_ = parse_uint64(optarg, "transaction id");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
opts.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
opts.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
opts.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
opts.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!input_path) {
|
if (!input_path) {
|
||||||
cerr << "no input file provided" << endl;
|
cerr << "no input file provided" << endl;
|
||||||
@ -133,8 +133,7 @@ thin_repair_cmd::run(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return repair(*input_path, *output_path, opts);
|
return repair(*input_path, *output_path, opts);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -45,28 +45,28 @@ using namespace thin_provisioning;
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int restore(string const &backup_file, string const &dev, bool quiet, override_options const &opts) {
|
int restore(string const &backup_file, string const &dev, bool quiet, override_options const &opts) {
|
||||||
bool metadata_touched = false;
|
bool metadata_touched = false;
|
||||||
try {
|
try {
|
||||||
// The block size gets updated by the restorer.
|
// The block size gets updated by the restorer.
|
||||||
block_manager<>::ptr bm(open_bm(dev, block_manager<>::READ_WRITE));
|
block_manager<>::ptr bm(open_bm(dev, block_manager<>::READ_WRITE));
|
||||||
file_utils::check_file_exists(backup_file);
|
file_utils::check_file_exists(backup_file);
|
||||||
metadata_touched = true;
|
metadata_touched = true;
|
||||||
metadata::ptr md(new metadata(bm, metadata::CREATE, 128, 0));
|
metadata::ptr md(new metadata(bm, metadata::CREATE, 128, 0));
|
||||||
emitter::ptr inner = create_restore_emitter(md);
|
emitter::ptr inner = create_restore_emitter(md);
|
||||||
emitter::ptr restorer = create_override_emitter(inner, opts);
|
emitter::ptr restorer = create_override_emitter(inner, opts);
|
||||||
|
|
||||||
parse_xml(backup_file, restorer, quiet);
|
parse_xml(backup_file, restorer, quiet);
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
if (metadata_touched)
|
if (metadata_touched)
|
||||||
file_utils::zero_superblock(dev);
|
file_utils::zero_superblock(dev);
|
||||||
cerr << e.what() << endl;
|
cerr << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
@ -79,99 +79,98 @@ thin_restore_cmd::thin_restore_cmd()
|
|||||||
void
|
void
|
||||||
thin_restore_cmd::usage(std::ostream &out) const
|
thin_restore_cmd::usage(std::ostream &out) const
|
||||||
{
|
{
|
||||||
out << "Usage: " << get_name() << " [options]" << endl
|
out << "Usage: " << get_name() << " [options]" << endl
|
||||||
<< "Options:" << endl
|
<< "Options:" << endl
|
||||||
<< " {-h|--help}" << endl
|
<< " {-h|--help}" << endl
|
||||||
<< " {-i|--input} <input xml file>" << endl
|
<< " {-i|--input} <input xml file>" << endl
|
||||||
<< " {-o|--output} <output device or file>" << endl
|
<< " {-o|--output} <output device or file>" << endl
|
||||||
<< " {--transaction-id} <natural>" << endl
|
<< " {--transaction-id} <natural>" << endl
|
||||||
<< " {--data-block-size} <natural>" << endl
|
<< " {--data-block-size} <natural>" << endl
|
||||||
<< " {--nr-data-blocks} <natural>" << endl
|
<< " {--nr-data-blocks} <natural>" << endl
|
||||||
<< " {-q|--quiet}" << endl
|
<< " {-q|--quiet}" << endl
|
||||||
<< " {-V|--version}" << endl;
|
<< " {-V|--version}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
thin_restore_cmd::run(int argc, char **argv)
|
thin_restore_cmd::run(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
const char *shortopts = "hi:o:qV";
|
const char *shortopts = "hi:o:qV";
|
||||||
string input, output;
|
string input, output;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
override_options opts;
|
override_options opts;
|
||||||
|
|
||||||
const struct option longopts[] = {
|
const struct option longopts[] = {
|
||||||
{ "help", no_argument, NULL, 'h'},
|
{ "help", no_argument, NULL, 'h'},
|
||||||
{ "input", required_argument, NULL, 'i' },
|
{ "input", required_argument, NULL, 'i' },
|
||||||
{ "output", required_argument, NULL, 'o'},
|
{ "output", required_argument, NULL, 'o'},
|
||||||
{ "transaction-id", required_argument, NULL, 1},
|
{ "transaction-id", required_argument, NULL, 1},
|
||||||
{ "data-block-size", required_argument, NULL, 2},
|
{ "data-block-size", required_argument, NULL, 2},
|
||||||
{ "nr-data-blocks", required_argument, NULL, 3},
|
{ "nr-data-blocks", required_argument, NULL, 3},
|
||||||
{ "quiet", no_argument, NULL, 'q'},
|
{ "quiet", no_argument, NULL, 'q'},
|
||||||
{ "version", no_argument, NULL, 'V'},
|
{ "version", no_argument, NULL, 'V'},
|
||||||
{ NULL, no_argument, NULL, 0 }
|
{ NULL, no_argument, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(cout);
|
usage(cout);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
input = optarg;
|
input = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
output = optarg;
|
output = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
opts.transaction_id_ = parse_uint64(optarg, "transaction id");
|
opts.transaction_id_ = parse_uint64(optarg, "transaction id");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
opts.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
opts.data_block_size_ = static_cast<uint32_t>(parse_uint64(optarg, "data block size"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
opts.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
opts.nr_data_blocks_ = parse_uint64(optarg, "nr data blocks");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'q':
|
case 'q':
|
||||||
quiet = true;
|
quiet = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != optind) {
|
if (argc != optind) {
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.empty()) {
|
if (input.empty()) {
|
||||||
cerr << "No input file provided." << endl << endl;
|
cerr << "No input file provided." << endl << endl;
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.empty()) {
|
if (output.empty()) {
|
||||||
cerr << "No output file provided." << endl << endl;
|
cerr << "No output file provided." << endl << endl;
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} else
|
||||||
check_output_file_requirements(output);
|
check_output_file_requirements(output);
|
||||||
|
|
||||||
return restore(input, output, quiet, opts);
|
return restore(input, output, quiet, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user