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>
This commit is contained in:
parent
958a669e58
commit
2d04ce3b5a
3 changed files with 49 additions and 7 deletions
|
@ -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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue