diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp index 0ad8d9db0..1d2683a54 100644 --- a/fs_mgr/libdm/dm.cpp +++ b/fs_mgr/libdm/dm.cpp @@ -162,6 +162,24 @@ DmDeviceState DeviceMapper::GetState(const std::string& name) const { return DmDeviceState::SUSPENDED; } +bool DeviceMapper::ChangeState(const std::string& name, DmDeviceState state) { + if (state != DmDeviceState::SUSPENDED && state != DmDeviceState::ACTIVE) { + return false; + } + + struct dm_ioctl io; + InitIo(&io, name); + + if (state == DmDeviceState::SUSPENDED) io.flags = DM_SUSPEND_FLAG; + + if (ioctl(fd_, DM_DEV_SUSPEND, &io) < 0) { + PLOG(ERROR) << "DM_DEV_SUSPEND " + << (state == DmDeviceState::SUSPENDED ? "suspend" : "resume") << " failed"; + return false; + } + return true; +} + bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table) { std::string ignore_path; if (!CreateDevice(name, table, &ignore_path, 0ms)) { diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp index b28a8f2e9..da1c4a9b0 100644 --- a/fs_mgr/libdm/dm_test.cpp +++ b/fs_mgr/libdm/dm_test.cpp @@ -166,6 +166,34 @@ TEST(libdm, DmLinear) { ASSERT_TRUE(dev.Destroy()); } +TEST(libdm, DmSuspendResume) { + unique_fd tmp1(CreateTempFile("file_suspend_resume", 512)); + ASSERT_GE(tmp1, 0); + + LoopDevice loop_a(tmp1, 10s); + ASSERT_TRUE(loop_a.valid()); + + DmTable table; + ASSERT_TRUE(table.Emplace(0, 1, loop_a.device(), 0)); + ASSERT_TRUE(table.valid()); + + TempDevice dev("libdm-test-dm-suspend-resume", table); + ASSERT_TRUE(dev.valid()); + ASSERT_FALSE(dev.path().empty()); + + auto& dm = DeviceMapper::Instance(); + + // Test Set and Get status of device. + vector targets; + ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE); + + ASSERT_TRUE(dm.ChangeState(dev.name(), DmDeviceState::SUSPENDED)); + ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::SUSPENDED); + + ASSERT_TRUE(dm.ChangeState(dev.name(), DmDeviceState::ACTIVE)); + ASSERT_EQ(dm.GetState(dev.name()), DmDeviceState::ACTIVE); +} + TEST(libdm, DmVerityArgsAvb2) { std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a"; std::string algorithm = "sha1"; diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index 9c0c2f30f..753b8c97d 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -79,6 +79,11 @@ class DeviceMapper final { // One of INVALID, SUSPENDED or ACTIVE. DmDeviceState GetState(const std::string& name) const; + // Puts the given device to the specified status, which must be either: + // - SUSPENDED: suspend the device, or + // - ACTIVE: resumes the device. + bool ChangeState(const std::string& name, DmDeviceState state); + // Creates a device, loads the given table, and activates it. If the device // is not able to be activated, it is destroyed, and false is returned. // After creation, |path| contains the result of calling