Loading fs_mgr/libdm/dm.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ #include "utility.h" #ifndef DM_DEFERRED_REMOVE #define DM_DEFERRED_REMOVE (1 << 17) #endif namespace android { namespace dm { Loading Loading @@ -133,6 +137,25 @@ bool DeviceMapper::DeleteDevice(const std::string& name) { return DeleteDevice(name, 0ms); } bool DeviceMapper::DeleteDeviceDeferred(const std::string& name) { struct dm_ioctl io; InitIo(&io, name); io.flags |= DM_DEFERRED_REMOVE; if (ioctl(fd_, DM_DEV_REMOVE, &io)) { PLOG(ERROR) << "DM_DEV_REMOVE with DM_DEFERRED_REMOVE failed for [" << name << "]"; return false; } return true; } bool DeviceMapper::DeleteDeviceIfExistsDeferred(const std::string& name) { if (GetState(name) == DmDeviceState::INVALID) { return true; } return DeleteDeviceDeferred(name); } static std::string GenerateUuid() { uuid_t uuid_bytes; uuid_generate(uuid_bytes); Loading fs_mgr/libdm/dm_test.cpp +62 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <libdm/dm.h> #include <libdm/loop_control.h> #include "test_util.h" #include "utility.h" using namespace std; using namespace std::chrono_literals; Loading Loading @@ -617,3 +618,64 @@ TEST(libdm, GetParentBlockDeviceByPath) { auto sub_block_device = dm.GetParentBlockDeviceByPath(dev.path()); ASSERT_EQ(loop.device(), *sub_block_device); } TEST(libdm, DeleteDeviceDeferredNoReferences) { unique_fd tmp(CreateTempFile("file_1", 4096)); ASSERT_GE(tmp, 0); LoopDevice loop(tmp, 10s); ASSERT_TRUE(loop.valid()); DmTable table; ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0)); ASSERT_TRUE(table.valid()); TempDevice dev("libdm-test-dm-linear", table); ASSERT_TRUE(dev.valid()); DeviceMapper& dm = DeviceMapper::Instance(); std::string path; ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path)); ASSERT_EQ(0, access(path.c_str(), F_OK)); ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear")); ASSERT_TRUE(WaitForFileDeleted(path, 5s)); ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear")); ASSERT_NE(0, access(path.c_str(), F_OK)); ASSERT_EQ(ENOENT, errno); } TEST(libdm, DeleteDeviceDeferredWaitsForLastReference) { unique_fd tmp(CreateTempFile("file_1", 4096)); ASSERT_GE(tmp, 0); LoopDevice loop(tmp, 10s); ASSERT_TRUE(loop.valid()); DmTable table; ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0)); ASSERT_TRUE(table.valid()); TempDevice dev("libdm-test-dm-linear", table); ASSERT_TRUE(dev.valid()); DeviceMapper& dm = DeviceMapper::Instance(); std::string path; ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path)); ASSERT_EQ(0, access(path.c_str(), F_OK)); { // Open a reference to block device. unique_fd fd(TEMP_FAILURE_RETRY(open(dev.path().c_str(), O_RDONLY | O_CLOEXEC))); ASSERT_GE(fd.get(), 0); ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear")); ASSERT_EQ(0, access(path.c_str(), F_OK)); } // After release device will be removed. ASSERT_TRUE(WaitForFileDeleted(path, 5s)); ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear")); ASSERT_NE(0, access(path.c_str(), F_OK)); ASSERT_EQ(ENOENT, errno); } fs_mgr/libdm/include/libdm/dm.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,12 @@ class DeviceMapper final { bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms); bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms); // Enqueues a deletion of device mapper device with the given name once last reference is // closed. // Returns 'true' on success, false otherwise. bool DeleteDeviceDeferred(const std::string& name); bool DeleteDeviceIfExistsDeferred(const std::string& name); // Fetches and returns the complete state of the underlying device mapper // device with given name. std::optional<Info> GetDetailedInfo(const std::string& name) const; Loading Loading
fs_mgr/libdm/dm.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,10 @@ #include "utility.h" #ifndef DM_DEFERRED_REMOVE #define DM_DEFERRED_REMOVE (1 << 17) #endif namespace android { namespace dm { Loading Loading @@ -133,6 +137,25 @@ bool DeviceMapper::DeleteDevice(const std::string& name) { return DeleteDevice(name, 0ms); } bool DeviceMapper::DeleteDeviceDeferred(const std::string& name) { struct dm_ioctl io; InitIo(&io, name); io.flags |= DM_DEFERRED_REMOVE; if (ioctl(fd_, DM_DEV_REMOVE, &io)) { PLOG(ERROR) << "DM_DEV_REMOVE with DM_DEFERRED_REMOVE failed for [" << name << "]"; return false; } return true; } bool DeviceMapper::DeleteDeviceIfExistsDeferred(const std::string& name) { if (GetState(name) == DmDeviceState::INVALID) { return true; } return DeleteDeviceDeferred(name); } static std::string GenerateUuid() { uuid_t uuid_bytes; uuid_generate(uuid_bytes); Loading
fs_mgr/libdm/dm_test.cpp +62 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include <libdm/dm.h> #include <libdm/loop_control.h> #include "test_util.h" #include "utility.h" using namespace std; using namespace std::chrono_literals; Loading Loading @@ -617,3 +618,64 @@ TEST(libdm, GetParentBlockDeviceByPath) { auto sub_block_device = dm.GetParentBlockDeviceByPath(dev.path()); ASSERT_EQ(loop.device(), *sub_block_device); } TEST(libdm, DeleteDeviceDeferredNoReferences) { unique_fd tmp(CreateTempFile("file_1", 4096)); ASSERT_GE(tmp, 0); LoopDevice loop(tmp, 10s); ASSERT_TRUE(loop.valid()); DmTable table; ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0)); ASSERT_TRUE(table.valid()); TempDevice dev("libdm-test-dm-linear", table); ASSERT_TRUE(dev.valid()); DeviceMapper& dm = DeviceMapper::Instance(); std::string path; ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path)); ASSERT_EQ(0, access(path.c_str(), F_OK)); ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear")); ASSERT_TRUE(WaitForFileDeleted(path, 5s)); ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear")); ASSERT_NE(0, access(path.c_str(), F_OK)); ASSERT_EQ(ENOENT, errno); } TEST(libdm, DeleteDeviceDeferredWaitsForLastReference) { unique_fd tmp(CreateTempFile("file_1", 4096)); ASSERT_GE(tmp, 0); LoopDevice loop(tmp, 10s); ASSERT_TRUE(loop.valid()); DmTable table; ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0)); ASSERT_TRUE(table.valid()); TempDevice dev("libdm-test-dm-linear", table); ASSERT_TRUE(dev.valid()); DeviceMapper& dm = DeviceMapper::Instance(); std::string path; ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path)); ASSERT_EQ(0, access(path.c_str(), F_OK)); { // Open a reference to block device. unique_fd fd(TEMP_FAILURE_RETRY(open(dev.path().c_str(), O_RDONLY | O_CLOEXEC))); ASSERT_GE(fd.get(), 0); ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear")); ASSERT_EQ(0, access(path.c_str(), F_OK)); } // After release device will be removed. ASSERT_TRUE(WaitForFileDeleted(path, 5s)); ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear")); ASSERT_NE(0, access(path.c_str(), F_OK)); ASSERT_EQ(ENOENT, errno); }
fs_mgr/libdm/include/libdm/dm.h +6 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,12 @@ class DeviceMapper final { bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms); bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms); // Enqueues a deletion of device mapper device with the given name once last reference is // closed. // Returns 'true' on success, false otherwise. bool DeleteDeviceDeferred(const std::string& name); bool DeleteDeviceIfExistsDeferred(const std::string& name); // Fetches and returns the complete state of the underlying device mapper // device with given name. std::optional<Info> GetDetailedInfo(const std::string& name) const; Loading