Merge changes Iae25434a,I13fd6699
* changes: libdm: Add LoopControl helpers for enabling direct IO. libdm: Add helpers for getting the device number of a dm device.
This commit is contained in:
commit
71b3afe620
6 changed files with 65 additions and 3 deletions
|
|
@ -46,6 +46,7 @@ cc_test {
|
|||
static_libs: [
|
||||
"libdm",
|
||||
"libbase",
|
||||
"libfs_mgr",
|
||||
"liblog",
|
||||
],
|
||||
srcs: [
|
||||
|
|
|
|||
|
|
@ -302,6 +302,26 @@ bool DeviceMapper::GetDmDevicePathByName(const std::string& name, std::string* p
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DeviceMapper::GetDeviceNumber(const std::string& name, dev_t* dev) {
|
||||
struct dm_ioctl io;
|
||||
InitIo(&io, name);
|
||||
if (ioctl(fd_, DM_DEV_STATUS, &io) < 0) {
|
||||
PLOG(WARNING) << "DM_DEV_STATUS failed for " << name;
|
||||
return false;
|
||||
}
|
||||
*dev = io.dev;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceMapper::GetDeviceString(const std::string& name, std::string* dev) {
|
||||
dev_t num;
|
||||
if (!GetDeviceNumber(name, &num)) {
|
||||
return false;
|
||||
}
|
||||
*dev = std::to_string(major(num)) + ":" + std::to_string(minor(num));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
|
||||
return GetTable(name, 0, table);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@ TEST(libdm, DmLinear) {
|
|||
// Define a 2-sector device, with each sector mapping to the first sector
|
||||
// of one of our loop devices.
|
||||
DmTable table;
|
||||
ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(0, 1, loop_a.device(), 0)));
|
||||
ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(1, 1, loop_b.device(), 0)));
|
||||
ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop_a.device(), 0));
|
||||
ASSERT_TRUE(table.Emplace<DmTargetLinear>(1, 1, loop_b.device(), 0));
|
||||
ASSERT_TRUE(table.valid());
|
||||
|
||||
TempDevice dev("libdm-test-dm-linear", table);
|
||||
|
|
@ -141,6 +141,16 @@ TEST(libdm, DmLinear) {
|
|||
ASSERT_FALSE(dev.path().empty());
|
||||
ASSERT_TRUE(dev.WaitForUdev());
|
||||
|
||||
auto& dm = DeviceMapper::Instance();
|
||||
|
||||
dev_t dev_number;
|
||||
ASSERT_TRUE(dm.GetDeviceNumber(dev.name(), &dev_number));
|
||||
ASSERT_NE(dev_number, 0);
|
||||
|
||||
std::string dev_string;
|
||||
ASSERT_TRUE(dm.GetDeviceString(dev.name(), &dev_string));
|
||||
ASSERT_FALSE(dev_string.empty());
|
||||
|
||||
// Note: a scope is needed to ensure that there are no open descriptors
|
||||
// when we go to close the device.
|
||||
{
|
||||
|
|
@ -157,7 +167,6 @@ TEST(libdm, DmLinear) {
|
|||
}
|
||||
|
||||
// Test GetTableStatus.
|
||||
DeviceMapper& dm = DeviceMapper::Instance();
|
||||
vector<DeviceMapper::TargetInfo> targets;
|
||||
ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
|
||||
ASSERT_EQ(targets.size(), 2);
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/types.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -111,6 +112,13 @@ class DeviceMapper final {
|
|||
// parameter is not set.
|
||||
bool GetDmDevicePathByName(const std::string& name, std::string* path);
|
||||
|
||||
// Returns the dev_t for the named device-mapper node.
|
||||
bool GetDeviceNumber(const std::string& name, dev_t* dev);
|
||||
|
||||
// Returns a major:minor string for the named device-mapper node, that can
|
||||
// be used as inputs to DmTargets that take a block device.
|
||||
bool GetDeviceString(const std::string& name, std::string* dev);
|
||||
|
||||
// The only way to create a DeviceMapper object.
|
||||
static DeviceMapper& Instance();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ class LoopControl final {
|
|||
// Detach the loop device given by 'loopdev' from the attached backing file.
|
||||
bool Detach(const std::string& loopdev) const;
|
||||
|
||||
// Enable Direct I/O on a loop device. This requires kernel 4.9+.
|
||||
static bool EnableDirectIo(int fd);
|
||||
|
||||
LoopControl(const LoopControl&) = delete;
|
||||
LoopControl& operator=(const LoopControl&) = delete;
|
||||
LoopControl& operator=(LoopControl&&) = default;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,27 @@ bool LoopControl::FindFreeLoopDevice(std::string* loopdev) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LoopControl::EnableDirectIo(int fd) {
|
||||
#if !defined(LOOP_SET_BLOCK_SIZE)
|
||||
static constexpr int LOOP_SET_BLOCK_SIZE = 0x4C09;
|
||||
#endif
|
||||
#if !defined(LOOP_SET_DIRECT_IO)
|
||||
static constexpr int LOOP_SET_DIRECT_IO = 0x4C08;
|
||||
#endif
|
||||
|
||||
// Note: the block size has to be >= the logical block size of the underlying
|
||||
// block device, *not* the filesystem block size.
|
||||
if (ioctl(fd, LOOP_SET_BLOCK_SIZE, 4096)) {
|
||||
PLOG(ERROR) << "Could not set loop device block size";
|
||||
return false;
|
||||
}
|
||||
if (ioctl(fd, LOOP_SET_DIRECT_IO, 1)) {
|
||||
PLOG(ERROR) << "Could not set loop direct IO";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LoopDevice::LoopDevice(int fd, bool auto_close) : fd_(fd), owns_fd_(auto_close) {
|
||||
Init();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue