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>
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 4fb0b83..2738457 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -197,19 +197,12 @@
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 @@
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 @@
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 @@
// clang-format off
{"create", DmCreateCmdHandler},
{"delete", DmDeleteCmdHandler},
+ {"replace", DmReplaceCmdHandler},
{"list", DmListCmdHandler},
{"help", HelpCmdHandler},
{"getpath", GetPathCmdHandler},