dmctl: add replace command

The replace command is used to substitute the current table of a
device-mapper with the provided one.
The new table will be available as soon as the command returns
successfully.

Bug: 137759376
Test: manual
Change-Id: Iaf258d9043fab3a8770702f4e1c8c0e583c81519
Signed-off-by: Alessio Balsini <balsini@google.com>
This commit is contained in:
Alessio Balsini 2019-08-01 01:46:36 +01:00
parent f7970cee69
commit 81d4ea79e2

View file

@ -197,19 +197,12 @@ class TargetParser final {
char** argv_;
};
static int DmCreateCmdHandler(int argc, char** argv) {
if (argc < 1) {
std::cerr << "Usage: dmctl create <dm-name> [-ro] <targets...>" << std::endl;
return -EINVAL;
}
std::string name = argv[0];
static bool parse_table_args(DmTable* table, int argc, char** argv) {
// Parse extended options first.
DmTable table;
int arg_index = 1;
while (arg_index < argc && argv[arg_index][0] == '-') {
if (strcmp(argv[arg_index], "-ro") == 0) {
table.set_readonly(true);
table->set_readonly(true);
arg_index++;
} else {
std::cerr << "Unrecognized option: " << argv[arg_index] << std::endl;
@ -221,15 +214,30 @@ static int DmCreateCmdHandler(int argc, char** argv) {
TargetParser parser(argc - arg_index, argv + arg_index);
while (parser.More()) {
std::unique_ptr<DmTarget> target = parser.Next();
if (!target || !table.AddTarget(std::move(target))) {
if (!target || !table->AddTarget(std::move(target))) {
return -EINVAL;
}
}
if (table.num_targets() == 0) {
if (table->num_targets() == 0) {
std::cerr << "Must define at least one target." << std::endl;
return -EINVAL;
}
return 0;
}
static int DmCreateCmdHandler(int argc, char** argv) {
if (argc < 1) {
std::cerr << "Usage: dmctl create <dm-name> [-ro] <targets...>" << std::endl;
return -EINVAL;
}
std::string name = argv[0];
DmTable table;
int ret = parse_table_args(&table, argc, argv);
if (ret) {
return ret;
}
DeviceMapper& dm = DeviceMapper::Instance();
if (!dm.CreateDevice(name, table)) {
@ -255,6 +263,27 @@ static int DmDeleteCmdHandler(int argc, char** argv) {
return 0;
}
static int DmReplaceCmdHandler(int argc, char** argv) {
if (argc < 1) {
std::cerr << "Usage: dmctl replace <dm-name> <targets...>" << std::endl;
return -EINVAL;
}
std::string name = argv[0];
DmTable table;
int ret = parse_table_args(&table, argc, argv);
if (ret) {
return ret;
}
DeviceMapper& dm = DeviceMapper::Instance();
if (!dm.LoadTableAndActivate(name, table)) {
std::cerr << "Failed to replace device-mapper table to: " << name << std::endl;
return -EIO;
}
return 0;
}
static int DmListTargets(DeviceMapper& dm, [[maybe_unused]] int argc,
[[maybe_unused]] char** argv) {
std::vector<DmTargetTypeInfo> targets;
@ -469,6 +498,7 @@ static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
// clang-format off
{"create", DmCreateCmdHandler},
{"delete", DmDeleteCmdHandler},
{"replace", DmReplaceCmdHandler},
{"list", DmListCmdHandler},
{"help", HelpCmdHandler},
{"getpath", GetPathCmdHandler},