From 2d04ce3b5ab2f0ce80cdff54936b5b89cbeec5d6 Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Tue, 18 Dec 2018 09:36:53 -0800 Subject: [PATCH] dmctl: Add verbose 'dmctl list devices' This adds an option to list device mapper devices including their current target table. Useful to be included in bugreport to map the logical partitions metadata with actual device mapper setup. Bug: 120916687 Test: dmctl list devices -v Change-Id: I091666506d24372d1e111ffa1c0256c8bbff0c5e Signed-off-by: Sandeep Patil --- fs_mgr/libdm/dm.cpp | 15 ++++++++++++-- fs_mgr/libdm/include/libdm/dm.h | 6 ++++++ fs_mgr/tools/dmctl.cpp | 35 ++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index c4b57c778..d9786add1 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -203,7 +203,8 @@ bool DeviceMapper::GetAvailableTargets(std::vector* targets) { } next += vers->next; data_size -= vers->next; - vers = reinterpret_cast(static_cast(buffer.get()) + next); + vers = reinterpret_cast(static_cast(buffer.get()) + + next); } return true; @@ -288,12 +289,23 @@ bool DeviceMapper::GetDmDevicePathByName(const std::string& name, std::string* p } bool DeviceMapper::GetTableStatus(const std::string& name, std::vector* table) { + return GetTable(name, 0, table); +} + +bool DeviceMapper::GetTableInfo(const std::string& name, std::vector* table) { + return GetTable(name, DM_STATUS_TABLE_FLAG, table); +} + +// private methods of DeviceMapper +bool DeviceMapper::GetTable(const std::string& name, uint32_t flags, + std::vector* table) { char buffer[4096]; struct dm_ioctl* io = reinterpret_cast(buffer); InitIo(io, name); io->data_size = sizeof(buffer); io->data_start = sizeof(*io); + io->flags = flags; if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) { PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name; return false; @@ -327,7 +339,6 @@ bool DeviceMapper::GetTableStatus(const std::string& name, std::vector* table); + // Identical to GetTableStatus, except also retrives the active table for the device + // mapper device from the kernel. + bool GetTableInfo(const std::string& name, std::vector* table); + private: // Maximum possible device mapper targets registered in the kernel. // This is only used to read the list of targets from kernel so we allocate @@ -140,6 +144,8 @@ class DeviceMapper final { // limit we are imposing here of 256. static constexpr uint32_t kMaxPossibleDmDevices = 256; + bool GetTable(const std::string& name, uint32_t flags, std::vector* table); + void InitIo(struct dm_ioctl* io, const std::string& name = std::string()) const; DeviceMapper(); diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp index f78093bdf..3b6ff9b95 100644 --- a/fs_mgr/tools/dmctl.cpp +++ b/fs_mgr/tools/dmctl.cpp @@ -36,6 +36,8 @@ #include #include +using namespace std::literals::string_literals; + using DeviceMapper = ::android::dm::DeviceMapper; using DmTable = ::android::dm::DmTable; using DmTarget = ::android::dm::DmTarget; @@ -51,7 +53,7 @@ static int Usage(void) { std::cerr << "commands:" << std::endl; std::cerr << " create [-ro] " << std::endl; std::cerr << " delete " << std::endl; - std::cerr << " list " << std::endl; + std::cerr << " list [-v]" << std::endl; std::cerr << " getpath " << std::endl; std::cerr << " table " << std::endl; std::cerr << " help" << std::endl; @@ -197,7 +199,8 @@ static int DmDeleteCmdHandler(int argc, char** argv) { return 0; } -static int DmListTargets(DeviceMapper& dm) { +static int DmListTargets(DeviceMapper& dm, [[maybe_unused]] int argc, + [[maybe_unused]] char** argv) { std::vector targets; if (!dm.GetAvailableTargets(&targets)) { std::cerr << "Failed to read available device mapper targets" << std::endl; @@ -218,7 +221,7 @@ static int DmListTargets(DeviceMapper& dm) { return 0; } -static int DmListDevices(DeviceMapper& dm) { +static int DmListDevices(DeviceMapper& dm, int argc, char** argv) { std::vector devices; if (!dm.GetAvailableDevices(&devices)) { std::cerr << "Failed to read available device mapper devices" << std::endl; @@ -230,15 +233,37 @@ static int DmListDevices(DeviceMapper& dm) { return 0; } + bool verbose = (argc && (argv[0] == "-v"s)); for (const auto& dev : devices) { std::cout << std::left << std::setw(20) << dev.name() << " : " << dev.Major() << ":" << dev.Minor() << std::endl; + if (verbose) { + std::vector table; + if (!dm.GetTableInfo(dev.name(), &table)) { + std::cerr << "Could not query table status for device \"" << dev.name() << "\"." + << std::endl; + return -EINVAL; + } + + uint32_t target_num = 1; + for (const auto& target : table) { + std::cout << " target#" << target_num << ": "; + std::cout << target.spec.sector_start << "-" + << (target.spec.sector_start + target.spec.length) << ": " + << target.spec.target_type; + if (!target.data.empty()) { + std::cout << ", " << target.data; + } + std::cout << std::endl; + target_num++; + } + } } return 0; } -static const std::map> listmap = { +static const std::map> listmap = { {"targets", DmListTargets}, {"devices", DmListDevices}, }; @@ -251,7 +276,7 @@ static int DmListCmdHandler(int argc, char** argv) { DeviceMapper& dm = DeviceMapper::Instance(); for (const auto& l : listmap) { - if (l.first == argv[0]) return l.second(dm); + if (l.first == argv[0]) return l.second(dm, argc - 1, argv + 1); } std::cerr << "Invalid argument to \'dmctl list\': " << argv[0] << std::endl;