From 5e9e74be6158d2a0089a0b0943d7bb03949caab8 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 21 Jun 2018 14:46:34 -0700 Subject: [PATCH] libdm: Implement GetDmDevicePathByName(). This change implements the ability to get the path of a block device given a device-mapper device name. In addition, dmctl now has a "getpath" command to perform this query, as a shortcut for searching through /sys/block/*/dm/name. Bug: 110035986 Test: N/A Change-Id: I9ebd824fa800004f591fc02fc1b1950e0c7fba65 --- fs_mgr/libdm/dm.cpp | 14 ++++++++++++-- fs_mgr/libdm/include/libdm/dm.h | 5 +++-- fs_mgr/tools/dmctl.cpp | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index 8bd3b9de0..b96f4c1e2 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -17,6 +17,7 @@ #include "libdm/dm.h" #include +#include #include #include @@ -258,8 +259,17 @@ bool DeviceMapper::GetAvailableDevices(std::vector* devices) { // Accepts a device mapper device name (like system_a, vendor_b etc) and // returns the path to it's device node (or symlink to the device node) -std::string DeviceMapper::GetDmDevicePathByName(const std::string& /* name */) { - return ""; +bool DeviceMapper::GetDmDevicePathByName(const std::string& name, std::string* path) { + struct dm_ioctl io; + InitIo(&io, name); + if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) { + PLOG(ERROR) << "DM_DEV_STATUS failed for " << name; + return false; + } + + uint32_t dev_num = minor(io.dev); + *path = "/dev/block/dm-" + std::to_string(dev_num); + return true; } // private methods of DeviceMapper diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index 8d23b2cf0..60bceed94 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -104,8 +104,9 @@ class DeviceMapper final { bool GetAvailableDevices(std::vector* devices); // Returns the path to the device mapper device node in '/dev' corresponding to - // 'name'. - std::string GetDmDevicePathByName(const std::string& name); + // 'name'. If the device does not exist, false is returned, and the path + // parameter is not set. + bool GetDmDevicePathByName(const std::string& name, std::string* path); // The only way to create a DeviceMapper object. static DeviceMapper& Instance(); diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp index c15173f45..9d48b8c61 100644 --- a/fs_mgr/tools/dmctl.cpp +++ b/fs_mgr/tools/dmctl.cpp @@ -49,6 +49,7 @@ static int Usage(void) { std::cerr << " create [-ro] " << std::endl; std::cerr << " delete " << std::endl; std::cerr << " list " << std::endl; + std::cerr << " getpath " << std::endl; std::cerr << " help" << std::endl; std::cerr << std::endl; std::cerr << "Target syntax:" << std::endl; @@ -241,11 +242,30 @@ static int HelpCmdHandler(int /* argc */, char** /* argv */) { return 0; } +static int GetPathCmdHandler(int argc, char** argv) { + if (argc != 1) { + std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl; + return -EINVAL; + } + + DeviceMapper& dm = DeviceMapper::Instance(); + std::string path; + if (!dm.GetDmDevicePathByName(argv[0], &path)) { + std::cerr << "Could not query path of device \"" << argv[0] << "\"." << std::endl; + return -EINVAL; + } + std::cout << path << std::endl; + return 0; +} + static std::map> cmdmap = { + // clang-format off {"create", DmCreateCmdHandler}, {"delete", DmDeleteCmdHandler}, {"list", DmListCmdHandler}, {"help", HelpCmdHandler}, + {"getpath", GetPathCmdHandler}, + // clang-format on }; int main(int argc, char** argv) {