libsnapshot: Ensure dm-user devices are destroyed after a merge.
Also, make sure snapuserd has closed its references. This is preventing
the merge from completing until a reboot.
Bug: N/A
Test: vts_libsnapshot_test
Change-Id: Iba18f887bdb262c630ec44461871e19fe64dbf3c
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 71cdbe0..397ff2e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -630,6 +630,9 @@
// The reverse of MapPartitionWithSnapshot.
bool UnmapPartitionWithSnapshot(LockedFile* lock, const std::string& target_partition_name);
+ // Unmap a dm-user device through snapuserd.
+ bool UnmapDmUserDevice(const std::string& snapshot_name);
+
// If there isn't a previous update, return true. |needs_merge| is set to false.
// If there is a previous update but the device has not boot into it, tries to cancel the
// update and delete any snapshots. Return true if successful. |needs_merge| is set to false.
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 67b5b8b..f0646fc 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1247,6 +1247,10 @@
return false;
}
+ if (status.compression_enabled()) {
+ UnmapDmUserDevice(name);
+ }
+
// Cleanup the base device as well, since it is no longer used. This does
// not block cleanup.
auto base_name = GetBaseDeviceName(name);
@@ -2063,27 +2067,8 @@
auto& dm = DeviceMapper::Instance();
- auto dm_user_name = GetDmUserCowName(name);
- if (IsCompressionEnabled() && dm.GetState(dm_user_name) != DmDeviceState::INVALID) {
- if (!EnsureSnapuserdConnected()) {
- return false;
- }
- if (!dm.DeleteDeviceIfExists(dm_user_name)) {
- LOG(ERROR) << "Cannot unmap " << dm_user_name;
- return false;
- }
-
- if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
- LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
- return false;
- }
-
- // Ensure the control device is gone so we don't run into ABA problems.
- auto control_device = "/dev/dm-user/" + dm_user_name;
- if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
- LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
- return false;
- }
+ if (IsCompressionEnabled() && !UnmapDmUserDevice(name)) {
+ return false;
}
auto cow_name = GetCowName(name);
@@ -2100,6 +2085,37 @@
return true;
}
+bool SnapshotManager::UnmapDmUserDevice(const std::string& snapshot_name) {
+ auto& dm = DeviceMapper::Instance();
+
+ if (!EnsureSnapuserdConnected()) {
+ return false;
+ }
+
+ auto dm_user_name = GetDmUserCowName(snapshot_name);
+ if (dm.GetState(dm_user_name) == DmDeviceState::INVALID) {
+ return true;
+ }
+
+ if (!dm.DeleteDeviceIfExists(dm_user_name)) {
+ LOG(ERROR) << "Cannot unmap " << dm_user_name;
+ return false;
+ }
+
+ if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
+ LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
+ return false;
+ }
+
+ // Ensure the control device is gone so we don't run into ABA problems.
+ auto control_device = "/dev/dm-user/" + dm_user_name;
+ if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
+ LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
+ return false;
+ }
+ return true;
+}
+
bool SnapshotManager::MapAllSnapshots(const std::chrono::milliseconds& timeout_ms) {
auto lock = LockExclusive();
if (!lock) return false;