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
This commit is contained in:
David Anderson 2018-06-21 14:46:34 -07:00
parent 8ddd105545
commit 5e9e74be61
3 changed files with 35 additions and 4 deletions

View File

@ -17,6 +17,7 @@
#include "libdm/dm.h"
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <android-base/macros.h>
@ -258,8 +259,17 @@ bool DeviceMapper::GetAvailableDevices(std::vector<DmBlockDevice>* 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

View File

@ -104,8 +104,9 @@ class DeviceMapper final {
bool GetAvailableDevices(std::vector<DmBlockDevice>* 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();

View File

@ -49,6 +49,7 @@ static int Usage(void) {
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 << " getpath <dm-name>" << 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<std::string, std::function<int(int, char**)>> cmdmap = {
// clang-format off
{"create", DmCreateCmdHandler},
{"delete", DmDeleteCmdHandler},
{"list", DmListCmdHandler},
{"help", HelpCmdHandler},
{"getpath", GetPathCmdHandler},
// clang-format on
};
int main(int argc, char** argv) {