Skip to content

Commit a35d50c

Browse files
nioffeAndroid (Google) Code Review
authored andcommitted
Merge "libdm: Add DeleteDeviceDeferred API" into sc-dev
2 parents b9637b0 + 8c427b9 commit a35d50c

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

fs_mgr/libdm/dm.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
#include "utility.h"
3737

38+
#ifndef DM_DEFERRED_REMOVE
39+
#define DM_DEFERRED_REMOVE (1 << 17)
40+
#endif
41+
3842
namespace android {
3943
namespace dm {
4044

@@ -133,6 +137,25 @@ bool DeviceMapper::DeleteDevice(const std::string& name) {
133137
return DeleteDevice(name, 0ms);
134138
}
135139

140+
bool DeviceMapper::DeleteDeviceDeferred(const std::string& name) {
141+
struct dm_ioctl io;
142+
InitIo(&io, name);
143+
144+
io.flags |= DM_DEFERRED_REMOVE;
145+
if (ioctl(fd_, DM_DEV_REMOVE, &io)) {
146+
PLOG(ERROR) << "DM_DEV_REMOVE with DM_DEFERRED_REMOVE failed for [" << name << "]";
147+
return false;
148+
}
149+
return true;
150+
}
151+
152+
bool DeviceMapper::DeleteDeviceIfExistsDeferred(const std::string& name) {
153+
if (GetState(name) == DmDeviceState::INVALID) {
154+
return true;
155+
}
156+
return DeleteDeviceDeferred(name);
157+
}
158+
136159
static std::string GenerateUuid() {
137160
uuid_t uuid_bytes;
138161
uuid_generate(uuid_bytes);

fs_mgr/libdm/dm_test.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <libdm/dm.h>
3636
#include <libdm/loop_control.h>
3737
#include "test_util.h"
38+
#include "utility.h"
3839

3940
using namespace std;
4041
using namespace std::chrono_literals;
@@ -617,3 +618,64 @@ TEST(libdm, GetParentBlockDeviceByPath) {
617618
auto sub_block_device = dm.GetParentBlockDeviceByPath(dev.path());
618619
ASSERT_EQ(loop.device(), *sub_block_device);
619620
}
621+
622+
TEST(libdm, DeleteDeviceDeferredNoReferences) {
623+
unique_fd tmp(CreateTempFile("file_1", 4096));
624+
ASSERT_GE(tmp, 0);
625+
LoopDevice loop(tmp, 10s);
626+
ASSERT_TRUE(loop.valid());
627+
628+
DmTable table;
629+
ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
630+
ASSERT_TRUE(table.valid());
631+
TempDevice dev("libdm-test-dm-linear", table);
632+
ASSERT_TRUE(dev.valid());
633+
634+
DeviceMapper& dm = DeviceMapper::Instance();
635+
636+
std::string path;
637+
ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
638+
ASSERT_EQ(0, access(path.c_str(), F_OK));
639+
640+
ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear"));
641+
642+
ASSERT_TRUE(WaitForFileDeleted(path, 5s));
643+
ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
644+
ASSERT_NE(0, access(path.c_str(), F_OK));
645+
ASSERT_EQ(ENOENT, errno);
646+
}
647+
648+
TEST(libdm, DeleteDeviceDeferredWaitsForLastReference) {
649+
unique_fd tmp(CreateTempFile("file_1", 4096));
650+
ASSERT_GE(tmp, 0);
651+
LoopDevice loop(tmp, 10s);
652+
ASSERT_TRUE(loop.valid());
653+
654+
DmTable table;
655+
ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
656+
ASSERT_TRUE(table.valid());
657+
TempDevice dev("libdm-test-dm-linear", table);
658+
ASSERT_TRUE(dev.valid());
659+
660+
DeviceMapper& dm = DeviceMapper::Instance();
661+
662+
std::string path;
663+
ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
664+
ASSERT_EQ(0, access(path.c_str(), F_OK));
665+
666+
{
667+
// Open a reference to block device.
668+
unique_fd fd(TEMP_FAILURE_RETRY(open(dev.path().c_str(), O_RDONLY | O_CLOEXEC)));
669+
ASSERT_GE(fd.get(), 0);
670+
671+
ASSERT_TRUE(dm.DeleteDeviceDeferred("libdm-test-dm-linear"));
672+
673+
ASSERT_EQ(0, access(path.c_str(), F_OK));
674+
}
675+
676+
// After release device will be removed.
677+
ASSERT_TRUE(WaitForFileDeleted(path, 5s));
678+
ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
679+
ASSERT_NE(0, access(path.c_str(), F_OK));
680+
ASSERT_EQ(ENOENT, errno);
681+
}

fs_mgr/libdm/include/libdm/dm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ class DeviceMapper final {
9595
bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
9696
bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms);
9797

98+
// Enqueues a deletion of device mapper device with the given name once last reference is
99+
// closed.
100+
// Returns 'true' on success, false otherwise.
101+
bool DeleteDeviceDeferred(const std::string& name);
102+
bool DeleteDeviceIfExistsDeferred(const std::string& name);
103+
98104
// Fetches and returns the complete state of the underlying device mapper
99105
// device with given name.
100106
std::optional<Info> GetDetailedInfo(const std::string& name) const;

0 commit comments

Comments
 (0)