diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp index c8c2d8355..21255df5f 100644 --- a/fs_mgr/libdm/Android.bp +++ b/fs_mgr/libdm/Android.bp @@ -46,6 +46,7 @@ cc_test { static_libs: [ "libdm", "libbase", + "libfs_mgr", "liblog", ], srcs: [ diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index c2917a4b0..788039d60 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -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* table) { return GetTable(name, 0, table); } diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp index dc47c33b0..62199233b 100644 --- a/fs_mgr/libdm/dm_test.cpp +++ b/fs_mgr/libdm/dm_test.cpp @@ -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(0, 1, loop_a.device(), 0))); - ASSERT_TRUE(table.AddTarget(make_unique(1, 1, loop_b.device(), 0))); + ASSERT_TRUE(table.Emplace(0, 1, loop_a.device(), 0)); + ASSERT_TRUE(table.Emplace(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 targets; ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets)); ASSERT_EQ(targets.size(), 2); diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index d7e8aa91c..3d223e37d 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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(); diff --git a/fs_mgr/libdm/include/libdm/loop_control.h b/fs_mgr/libdm/include/libdm/loop_control.h index e6e83f40e..6b4c2d8fc 100644 --- a/fs_mgr/libdm/include/libdm/loop_control.h +++ b/fs_mgr/libdm/include/libdm/loop_control.h @@ -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; diff --git a/fs_mgr/libdm/loop_control.cpp b/fs_mgr/libdm/loop_control.cpp index 0beb1a63e..16bf4b038 100644 --- a/fs_mgr/libdm/loop_control.cpp +++ b/fs_mgr/libdm/loop_control.cpp @@ -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(); }