summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandeep Patil <sspatil@google.com>2018-12-18 09:36:53 -0800
committerSandeep Patil <sspatil@google.com>2018-12-19 08:51:59 -0800
commit2d04ce3b5ab2f0ce80cdff54936b5b89cbeec5d6 (patch)
tree1cf5e08a065fb472f55347faa47ec5e1ca0af391
parent958a669e58ebd9ac6eed1e9423c020cb23a4a746 (diff)
downloadsystem_core-2d04ce3b5ab2f0ce80cdff54936b5b89cbeec5d6.tar.gz
system_core-2d04ce3b5ab2f0ce80cdff54936b5b89cbeec5d6.tar.bz2
system_core-2d04ce3b5ab2f0ce80cdff54936b5b89cbeec5d6.zip
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 <sspatil@google.com>
-rw-r--r--fs_mgr/libdm/dm.cpp15
-rw-r--r--fs_mgr/libdm/include/libdm/dm.h6
-rw-r--r--fs_mgr/tools/dmctl.cpp35
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<DmTargetTypeInfo>* targets) {
}
next += vers->next;
data_size -= vers->next;
- vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) + next);
+ vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(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<TargetInfo>* table) {
+ return GetTable(name, 0, table);
+}
+
+bool DeviceMapper::GetTableInfo(const std::string& name, std::vector<TargetInfo>* 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<TargetInfo>* table) {
char buffer[4096];
struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(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<TargetInf
return true;
}
-// private methods of DeviceMapper
void DeviceMapper::InitIo(struct dm_ioctl* io, const std::string& name) const {
CHECK(io != nullptr) << "nullptr passed to dm_ioctl initialization";
memset(io, 0, sizeof(*io));
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 91f8bb422..28e6e011c 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -128,6 +128,10 @@ class DeviceMapper final {
};
bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* 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<TargetInfo>* 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<TargetInfo>* 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 <string>
#include <vector>
+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 <dm-name> [-ro] <targets...>" << std::endl;
std::cerr << " delete <dm-name>" << std::endl;
- std::cerr << " list <devices | targets>" << std::endl;
+ std::cerr << " list <devices | targets> [-v]" << std::endl;
std::cerr << " getpath <dm-name>" << std::endl;
std::cerr << " table <dm-name>" << 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<DmTargetTypeInfo> 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<DmBlockDevice> 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<DeviceMapper::TargetInfo> 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<std::string, std::function<int(DeviceMapper&)>> listmap = {
+static const std::map<std::string, std::function<int(DeviceMapper&, int, char**)>> 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;