Merge "libdm: Add DeleteDeviceDeferred API" into sc-dev
This commit is contained in:
commit
a35d50c234
|
@ -35,6 +35,10 @@
|
|||
|
||||
#include "utility.h"
|
||||
|
||||
#ifndef DM_DEFERRED_REMOVE
|
||||
#define DM_DEFERRED_REMOVE (1 << 17)
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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…
Reference in New Issue