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
This commit is contained in:
David Anderson 2021-01-11 18:55:00 -08:00
parent 2147cc5675
commit 4067c7e1a7
2 changed files with 40 additions and 21 deletions

View File

@ -630,6 +630,9 @@ class SnapshotManager final : public ISnapshotManager {
// The reverse of MapPartitionWithSnapshot. // The reverse of MapPartitionWithSnapshot.
bool UnmapPartitionWithSnapshot(LockedFile* lock, const std::string& target_partition_name); 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 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 // 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. // update and delete any snapshots. Return true if successful. |needs_merge| is set to false.

View File

@ -1247,6 +1247,10 @@ bool SnapshotManager::CollapseSnapshotDevice(const std::string& name,
return false; return false;
} }
if (status.compression_enabled()) {
UnmapDmUserDevice(name);
}
// Cleanup the base device as well, since it is no longer used. This does // Cleanup the base device as well, since it is no longer used. This does
// not block cleanup. // not block cleanup.
auto base_name = GetBaseDeviceName(name); auto base_name = GetBaseDeviceName(name);
@ -2063,27 +2067,8 @@ bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name)
auto& dm = DeviceMapper::Instance(); auto& dm = DeviceMapper::Instance();
auto dm_user_name = GetDmUserCowName(name); if (IsCompressionEnabled() && !UnmapDmUserDevice(name)) {
if (IsCompressionEnabled() && dm.GetState(dm_user_name) != DmDeviceState::INVALID) { return false;
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;
}
} }
auto cow_name = GetCowName(name); auto cow_name = GetCowName(name);
@ -2100,6 +2085,37 @@ bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name)
return true; 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) { bool SnapshotManager::MapAllSnapshots(const std::chrono::milliseconds& timeout_ms) {
auto lock = LockExclusive(); auto lock = LockExclusive();
if (!lock) return false; if (!lock) return false;