From efec0abf4a74357565db8560813858b830f850a8 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 13 Sep 2021 18:37:16 -0700 Subject: [PATCH] libdm, libsnapshot: Add a virtual interface for DeviceMapper. It is difficult to test libsnapshot failures because there is no way to inject failure scenarios into the kernel's device-mapper. Exposing a virtual interface will allow this kind of testing via dependency injection. Bug: 199785546 Test: builds, tests pass Change-Id: I5add0c7e24f7fa2853114eaeda7c479eaa4e0552 --- fs_mgr/libdm/include/libdm/dm.h | 51 ++++++---- fs_mgr/libfs_avb/Android.bp | 1 + fs_mgr/libsnapshot/device_info.cpp | 4 + fs_mgr/libsnapshot/device_info.h | 1 + .../include/libsnapshot/snapshot.h | 13 ++- .../include_test/libsnapshot/test_helpers.h | 3 + fs_mgr/libsnapshot/snapshot.cpp | 97 +++++++------------ fs_mgr/libsnapshot/snapshot_fuzz_utils.h | 5 +- fs_mgr/libsnapshot/utility.h | 4 +- 9 files changed, 93 insertions(+), 86 deletions(-) diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h index 7e01b859e..332fcf5bf 100644 --- a/fs_mgr/libdm/include/libdm/dm.h +++ b/fs_mgr/libdm/include/libdm/dm.h @@ -55,7 +55,33 @@ static constexpr uint64_t kSectorSize = 512; // that prefix. std::optional ExtractBlockDeviceName(const std::string& path); -class DeviceMapper final { +// This interface is for testing purposes. See DeviceMapper proper for what these methods do. +class IDeviceMapper { + public: + virtual ~IDeviceMapper() {} + + struct TargetInfo { + struct dm_target_spec spec; + std::string data; + TargetInfo() {} + TargetInfo(const struct dm_target_spec& spec, const std::string& data) + : spec(spec), data(data) {} + + bool IsOverflowSnapshot() const; + }; + + virtual bool CreateDevice(const std::string& name, const DmTable& table, std::string* path, + const std::chrono::milliseconds& timeout_ms) = 0; + virtual DmDeviceState GetState(const std::string& name) const = 0; + virtual bool LoadTableAndActivate(const std::string& name, const DmTable& table) = 0; + virtual bool GetTableInfo(const std::string& name, std::vector* table) = 0; + virtual bool GetTableStatus(const std::string& name, std::vector* table) = 0; + virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) = 0; + virtual bool GetDeviceString(const std::string& name, std::string* dev) = 0; + virtual bool DeleteDeviceIfExists(const std::string& name) = 0; +}; + +class DeviceMapper final : public IDeviceMapper { public: class DmBlockDevice final { public: @@ -95,7 +121,7 @@ class DeviceMapper final { // Removes a device mapper device with the given name. // Returns 'true' on success, false otherwise. bool DeleteDevice(const std::string& name); - bool DeleteDeviceIfExists(const std::string& name); + bool DeleteDeviceIfExists(const std::string& name) override; // Removes a device mapper device with the given name and waits for |timeout_ms| milliseconds // for the corresponding block device to be deleted. bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms); @@ -114,7 +140,7 @@ class DeviceMapper final { // Returns the current state of the underlying device mapper device // with given name. // One of INVALID, SUSPENDED or ACTIVE. - DmDeviceState GetState(const std::string& name) const; + DmDeviceState GetState(const std::string& name) const override; // Puts the given device to the specified status, which must be either: // - SUSPENDED: suspend the device, or @@ -158,7 +184,7 @@ class DeviceMapper final { // not |path| is available. It is the caller's responsibility to ensure // there are no races. bool CreateDevice(const std::string& name, const DmTable& table, std::string* path, - const std::chrono::milliseconds& timeout_ms); + const std::chrono::milliseconds& timeout_ms) override; // Create a device and activate the given table, without waiting to acquire // a valid path. If the caller will use GetDmDevicePathByName(), it should @@ -170,7 +196,7 @@ class DeviceMapper final { // process. A device with the given name must already exist. // // Returns 'true' on success, false otherwise. - bool LoadTableAndActivate(const std::string& name, const DmTable& table); + bool LoadTableAndActivate(const std::string& name, const DmTable& table) override; // Returns true if a list of available device mapper targets registered in the kernel was // successfully read and stored in 'targets'. Returns 'false' otherwise. @@ -216,7 +242,7 @@ class DeviceMapper final { // Returns a major:minor string for the named device-mapper node, that can // be used as inputs to DmTargets that take a block device. - bool GetDeviceString(const std::string& name, std::string* dev); + bool GetDeviceString(const std::string& name, std::string* dev) override; // The only way to create a DeviceMapper object. static DeviceMapper& Instance(); @@ -231,20 +257,11 @@ class DeviceMapper final { // contain one TargetInfo for each target in the table. If the device does // not exist, or there were too many targets, the call will fail and return // false. - struct TargetInfo { - struct dm_target_spec spec; - std::string data; - TargetInfo() {} - TargetInfo(const struct dm_target_spec& spec, const std::string& data) - : spec(spec), data(data) {} - - bool IsOverflowSnapshot() const; - }; - bool GetTableStatus(const std::string& name, std::vector* table); + bool GetTableStatus(const std::string& name, std::vector* table) override; // Identical to GetTableStatus, except also retrives the active table for the device // mapper device from the kernel. - bool GetTableInfo(const std::string& name, std::vector* table); + bool GetTableInfo(const std::string& name, std::vector* table) override; static std::string GetTargetType(const struct dm_target_spec& spec); diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp index 0cbd9db9a..a0ad20812 100644 --- a/fs_mgr/libfs_avb/Android.bp +++ b/fs_mgr/libfs_avb/Android.bp @@ -152,6 +152,7 @@ cc_test { static_libs: [ "libavb", "libdm", + "libext2_uuid", "libfs_avb", "libfstab", ], diff --git a/fs_mgr/libsnapshot/device_info.cpp b/fs_mgr/libsnapshot/device_info.cpp index 14ce0ee0e..a6d96ed82 100644 --- a/fs_mgr/libsnapshot/device_info.cpp +++ b/fs_mgr/libsnapshot/device_info.cpp @@ -139,5 +139,9 @@ std::unique_ptr ISnapshotManager::IDeviceInfo::O } } +android::dm::IDeviceMapper& DeviceInfo::GetDeviceMapper() { + return android::dm::DeviceMapper::Instance(); +} + } // namespace snapshot } // namespace android diff --git a/fs_mgr/libsnapshot/device_info.h b/fs_mgr/libsnapshot/device_info.h index 7999c99c2..8aefb8507 100644 --- a/fs_mgr/libsnapshot/device_info.h +++ b/fs_mgr/libsnapshot/device_info.h @@ -40,6 +40,7 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo { bool IsRecovery() const override; std::unique_ptr OpenImageManager() const override; bool IsFirstStageInit() const override; + android::dm::IDeviceMapper& GetDeviceMapper() override; void set_first_stage_init(bool value) { first_stage_init_ = value; } diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h index d9a0cd913..55f4ed7ca 100644 --- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h +++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h @@ -110,6 +110,7 @@ class ISnapshotManager { virtual bool IsTestDevice() const { return false; } virtual bool IsFirstStageInit() const = 0; virtual std::unique_ptr OpenImageManager() const = 0; + virtual android::dm::IDeviceMapper& GetDeviceMapper() = 0; // Helper method for implementing OpenImageManager. std::unique_ptr OpenImageManager(const std::string& gsid_dir) const; @@ -611,6 +612,14 @@ class SnapshotManager final : public ISnapshotManager { MergeFailureCode CheckMergeConsistency(LockedFile* lock, const std::string& name, const SnapshotStatus& update_status); + // Get status or table information about a device-mapper node with a single target. + enum class TableQuery { + Table, + Status, + }; + bool GetSingleTarget(const std::string& dm_name, TableQuery query, + android::dm::DeviceMapper::TargetInfo* target); + // Interact with status files under /metadata/ota/snapshots. bool WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus& status); bool ReadSnapshotStatus(LockedFile* lock, const std::string& name, SnapshotStatus* status); @@ -773,9 +782,9 @@ class SnapshotManager final : public ISnapshotManager { bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms = {}); - std::string gsid_dir_; - std::string metadata_dir_; + android::dm::IDeviceMapper& dm_; std::unique_ptr device_; + std::string metadata_dir_; std::unique_ptr images_; bool use_first_stage_snapuserd_ = false; bool in_factory_data_reset_ = false; diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h index 4e7ccf145..1f57bbc97 100644 --- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h +++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h @@ -99,6 +99,9 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo { std::unique_ptr OpenImageManager() const override { return IDeviceInfo::OpenImageManager("ota/test"); } + android::dm::IDeviceMapper& GetDeviceMapper() override { + return android::dm::DeviceMapper::Instance(); + } bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; } diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp index 3e8d9c1d3..68f659e42 100644 --- a/fs_mgr/libsnapshot/snapshot.cpp +++ b/fs_mgr/libsnapshot/snapshot.cpp @@ -114,9 +114,8 @@ std::unique_ptr SnapshotManager::NewForFirstStageMount(IDeviceI return sm; } -SnapshotManager::SnapshotManager(IDeviceInfo* device) : device_(device) { - metadata_dir_ = device_->GetMetadataDir(); -} +SnapshotManager::SnapshotManager(IDeviceInfo* device) + : dm_(device->GetDeviceMapper()), device_(device), metadata_dir_(device_->GetMetadataDir()) {} static std::string GetCowName(const std::string& snapshot_name) { return snapshot_name + "-cow"; @@ -402,8 +401,6 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, const std::chrono::milliseconds& timeout_ms, std::string* path) { CHECK(lock); - auto& dm = DeviceMapper::Instance(); - // Use an extra decoration for first-stage init, so we can transition // to a new table entry in second-stage. std::string misc_name = name; @@ -423,7 +420,7 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name, DmTable table; table.Emplace(0, base_sectors, misc_name); - if (!dm.CreateDevice(name, table, path, timeout_ms)) { + if (!dm_.CreateDevice(name, table, path, timeout_ms)) { return false; } if (!WaitForDevice(*path, timeout_ms)) { @@ -490,8 +487,6 @@ bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name, uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize; - auto& dm = DeviceMapper::Instance(); - // Note that merging is a global state. We do track whether individual devices // have completed merging, but the start of the merge process is considered // atomic. @@ -521,7 +516,7 @@ bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name, DmTable table; table.Emplace(0, snapshot_sectors, base_device, cow_device, mode, kSnapshotChunkSize); - if (!dm.CreateDevice(name, table, dev_path, timeout_ms)) { + if (!dm_.CreateDevice(name, table, dev_path, timeout_ms)) { LOG(ERROR) << "Could not create snapshot device: " << name; return false; } @@ -652,7 +647,6 @@ bool SnapshotManager::InitiateMerge() { auto other_suffix = device_->GetOtherSlotSuffix(); - auto& dm = DeviceMapper::Instance(); for (const auto& snapshot : snapshots) { if (android::base::EndsWith(snapshot, other_suffix)) { // Allow the merge to continue, but log this unexpected case. @@ -664,7 +658,7 @@ bool SnapshotManager::InitiateMerge() { // the same time. This is a fairly serious error. We could forcefully // map everything here, but it should have been mapped during first- // stage init. - if (dm.GetState(snapshot) == DmDeviceState::INVALID) { + if (dm_.GetState(snapshot) == DmDeviceState::INVALID) { LOG(ERROR) << "Cannot begin merge; device " << snapshot << " is not mapped."; return false; } @@ -797,10 +791,8 @@ MergeFailureCode SnapshotManager::SwitchSnapshotToMerge(LockedFile* lock, const } MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& name) { - auto& dm = DeviceMapper::Instance(); - std::vector old_targets; - if (!dm.GetTableInfo(name, &old_targets)) { + if (!dm_.GetTableInfo(name, &old_targets)) { LOG(ERROR) << "Could not read snapshot device table: " << name; return MergeFailureCode::GetTableInfo; } @@ -818,7 +810,7 @@ MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& DmTable table; table.Emplace(0, old_targets[0].spec.length, base_device, cow_device, SnapshotStorageMode::Merge, kSnapshotChunkSize); - if (!dm.LoadTableAndActivate(name, table)) { + if (!dm_.LoadTableAndActivate(name, table)) { LOG(ERROR) << "Could not swap device-mapper tables on snapshot device " << name; return MergeFailureCode::ActivateNewTable; } @@ -826,24 +818,18 @@ MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& return MergeFailureCode::Ok; } -enum class TableQuery { - Table, - Status, -}; - -static bool GetSingleTarget(const std::string& dm_name, TableQuery query, - DeviceMapper::TargetInfo* target) { - auto& dm = DeviceMapper::Instance(); - if (dm.GetState(dm_name) == DmDeviceState::INVALID) { +bool SnapshotManager::GetSingleTarget(const std::string& dm_name, TableQuery query, + DeviceMapper::TargetInfo* target) { + if (dm_.GetState(dm_name) == DmDeviceState::INVALID) { return false; } std::vector targets; bool result; if (query == TableQuery::Status) { - result = dm.GetTableStatus(dm_name, &targets); + result = dm_.GetTableStatus(dm_name, &targets); } else { - result = dm.GetTableInfo(dm_name, &targets); + result = dm_.GetTableInfo(dm_name, &targets); } if (!result) { LOG(ERROR) << "Could not query device: " << dm_name; @@ -1169,11 +1155,9 @@ MergeFailureCode SnapshotManager::CheckMergeConsistency(LockedFile* lock, const return MergeFailureCode::Ok; } - auto& dm = DeviceMapper::Instance(); - std::string cow_image_name = GetMappedCowDeviceName(name, status); std::string cow_image_path; - if (!dm.GetDmDevicePathByName(cow_image_name, &cow_image_path)) { + if (!dm_.GetDmDevicePathByName(cow_image_name, &cow_image_path)) { LOG(ERROR) << "Failed to get path for cow device: " << cow_image_name; return MergeFailureCode::GetCowPathConsistencyCheck; } @@ -1349,8 +1333,6 @@ bool SnapshotManager::OnSnapshotMergeComplete(LockedFile* lock, const std::strin bool SnapshotManager::CollapseSnapshotDevice(const std::string& name, const SnapshotStatus& status) { - auto& dm = DeviceMapper::Instance(); - // Verify we have a snapshot-merge device. DeviceMapper::TargetInfo target; if (!GetSingleTarget(name, TableQuery::Table, &target)) { @@ -1389,7 +1371,7 @@ bool SnapshotManager::CollapseSnapshotDevice(const std::string& name, return false; } - if (!dm.LoadTableAndActivate(name, table)) { + if (!dm_.LoadTableAndActivate(name, table)) { return false; } @@ -1462,8 +1444,6 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition, } } - auto& dm = DeviceMapper::Instance(); - auto lock = LockExclusive(); if (!lock) return false; @@ -1477,7 +1457,7 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition, size_t ok_cows = 0; for (const auto& snapshot : snapshots) { std::string user_cow_name = GetDmUserCowName(snapshot); - if (dm.GetState(user_cow_name) == DmDeviceState::INVALID) { + if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) { continue; } @@ -1504,7 +1484,7 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition, DmTable table; table.Emplace(0, target.spec.length, misc_name); - if (!dm.LoadTableAndActivate(user_cow_name, table)) { + if (!dm_.LoadTableAndActivate(user_cow_name, table)) { LOG(ERROR) << "Unable to swap tables for " << misc_name; continue; } @@ -1517,7 +1497,7 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition, } std::string source_device; - if (!dm.GetDmDevicePathByName(source_device_name, &source_device)) { + if (!dm_.GetDmDevicePathByName(source_device_name, &source_device)) { LOG(ERROR) << "Could not get device path for " << GetSourceDeviceName(snapshot); continue; } @@ -1525,7 +1505,7 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition, std::string cow_image_name = GetMappedCowDeviceName(snapshot, snapshot_status); std::string cow_image_device; - if (!dm.GetDmDevicePathByName(cow_image_name, &cow_image_device)) { + if (!dm_.GetDmDevicePathByName(cow_image_name, &cow_image_device)) { LOG(ERROR) << "Could not get device path for " << cow_image_name; continue; } @@ -1700,8 +1680,7 @@ bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) { // snapshot, but it's on the wrong slot. We can't unmap an active // partition. If this is not really a snapshot, skip the unmap // step. - auto& dm = DeviceMapper::Instance(); - if (dm.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) { + if (dm_.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) { LOG(ERROR) << "Detected snapshot " << name << " on " << current_slot << " slot" << " for source partition; removing without unmap."; should_unmap = false; @@ -2038,14 +2017,13 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, // Create the base device for the snapshot, or if there is no snapshot, the // device itself. This device consists of the real blocks in the super // partition that this logical partition occupies. - auto& dm = DeviceMapper::Instance(); std::string base_path; if (!CreateLogicalPartition(params, &base_path)) { LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName() << " as device " << params.GetDeviceName(); return false; } - created_devices.EmplaceBack(&dm, params.GetDeviceName()); + created_devices.EmplaceBack(&dm_, params.GetDeviceName()); if (paths) { paths->target_device = base_path; @@ -2059,7 +2037,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, // We don't have ueventd in first-stage init, so use device major:minor // strings instead. std::string base_device; - if (!dm.GetDeviceString(params.GetDeviceName(), &base_device)) { + if (!dm_.GetDeviceString(params.GetDeviceName(), &base_device)) { LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName(); return false; } @@ -2102,7 +2080,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, } auto source_device = GetSourceDeviceName(params.GetPartitionName()); - created_devices.EmplaceBack(&dm, source_device); + created_devices.EmplaceBack(&dm_, source_device); } else { source_device_path = base_path; } @@ -2129,7 +2107,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock, << params.GetPartitionName(); return false; } - created_devices.EmplaceBack(&dm, name); + created_devices.EmplaceBack(&dm_, name); remaining_time = GetRemainingTime(params.timeout_ms, begin); if (remaining_time.count() < 0) return false; @@ -2195,8 +2173,6 @@ bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartiti std::string cow_image_name = GetCowImageDeviceName(partition_name); *cow_name = GetCowName(partition_name); - auto& dm = DeviceMapper::Instance(); - // Map COW image if necessary. if (snapshot_status.cow_file_size() > 0) { if (!EnsureImageManager()) return false; @@ -2247,11 +2223,11 @@ bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartiti // We have created the DmTable now. Map it. std::string cow_path; - if (!dm.CreateDevice(*cow_name, table, &cow_path, remaining_time)) { + if (!dm_.CreateDevice(*cow_name, table, &cow_path, remaining_time)) { LOG(ERROR) << "Could not create COW device: " << *cow_name; return false; } - created_devices->EmplaceBack(&dm, *cow_name); + created_devices->EmplaceBack(&dm_, *cow_name); LOG(INFO) << "Mapped COW device for " << params.GetPartitionName() << " at " << cow_path; return true; } @@ -2278,10 +2254,8 @@ bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name) } bool SnapshotManager::UnmapDmUserDevice(const std::string& snapshot_name) { - auto& dm = DeviceMapper::Instance(); - auto dm_user_name = GetDmUserCowName(snapshot_name); - if (dm.GetState(dm_user_name) == DmDeviceState::INVALID) { + if (dm_.GetState(dm_user_name) == DmDeviceState::INVALID) { return true; } @@ -3501,7 +3475,6 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) { return false; } - auto& dm = DeviceMapper::Instance(); for (const auto& snapshot : snapshots) { SnapshotStatus status; if (!ReadSnapshotStatus(lock, snapshot, &status)) { @@ -3512,7 +3485,7 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) { } std::vector targets; - if (!dm.GetTableStatus(snapshot, &targets)) { + if (!dm_.GetTableStatus(snapshot, &targets)) { LOG(ERROR) << "Could not read snapshot device table: " << snapshot; return false; } @@ -3605,11 +3578,9 @@ ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() { // isn't running yet. bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name, std::string* device_path) { - auto& dm = DeviceMapper::Instance(); - // Try getting the device string if it is a device mapper device. - if (dm.GetState(device_name) != DmDeviceState::INVALID) { - return dm.GetDmDevicePathByName(device_name, device_path); + if (dm_.GetState(device_name) != DmDeviceState::INVALID) { + return dm_.GetDmDevicePathByName(device_name, device_path); } // Otherwise, get path from IImageManager. @@ -3618,10 +3589,9 @@ bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name, bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name, std::string* device_string_or_mapped_path) { - auto& dm = DeviceMapper::Instance(); // Try getting the device string if it is a device mapper device. - if (dm.GetState(device_name) != DmDeviceState::INVALID) { - return dm.GetDeviceString(device_name, device_string_or_mapped_path); + if (dm_.GetState(device_name) != DmDeviceState::INVALID) { + return dm_.GetDeviceString(device_name, device_string_or_mapped_path); } // Otherwise, get path from IImageManager. @@ -3737,10 +3707,9 @@ void SnapshotManager::UpdateCowStats(ISnapshotMergeStats* stats) { bool SnapshotManager::DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms) { - auto& dm = DeviceMapper::Instance(); auto start = std::chrono::steady_clock::now(); while (true) { - if (dm.DeleteDeviceIfExists(name)) { + if (dm_.DeleteDeviceIfExists(name)) { return true; } auto now = std::chrono::steady_clock::now(); @@ -3753,7 +3722,7 @@ bool SnapshotManager::DeleteDeviceIfExists(const std::string& name, // Try to diagnose why this failed. First get the actual device path. std::string full_path; - if (!dm.GetDmDevicePathByName(name, &full_path)) { + if (!dm_.GetDmDevicePathByName(name, &full_path)) { LOG(ERROR) << "Unable to diagnose DM_DEV_REMOVE failure."; return false; } diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h index 3ed27c836..c1a5af77d 100644 --- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h +++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h @@ -101,7 +101,8 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo { : env_(env), data_(&data), partition_opener_(std::move(partition_opener)), - metadata_dir_(metadata_dir) {} + metadata_dir_(metadata_dir), + dm_(android::dm::DeviceMapper::Instance()) {} // Following APIs are mocked. std::string GetMetadataDir() const override { return metadata_dir_; } @@ -125,6 +126,7 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo { } bool IsRecovery() const override { return data_->is_recovery(); } bool IsFirstStageInit() const override { return false; } + android::dm::IDeviceMapper& GetDeviceMapper() override { return dm_; } std::unique_ptr OpenImageManager() const { return env_->CheckCreateFakeImageManager(); } @@ -137,6 +139,7 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo { std::unique_ptr partition_opener_; std::string metadata_dir_; bool switched_slot_ = false; + android::dm::DeviceMapper& dm_; bool CurrentSlotIsA() const { return data_->slot_suffix_is_a() != switched_slot_; } }; diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h index 671de9dbc..e97afed22 100644 --- a/fs_mgr/libsnapshot/utility.h +++ b/fs_mgr/libsnapshot/utility.h @@ -57,14 +57,14 @@ struct AutoDeviceList { // Automatically unmap a device upon deletion. struct AutoUnmapDevice : AutoDevice { // On destruct, delete |name| from device mapper. - AutoUnmapDevice(android::dm::DeviceMapper* dm, const std::string& name) + AutoUnmapDevice(android::dm::IDeviceMapper* dm, const std::string& name) : AutoDevice(name), dm_(dm) {} AutoUnmapDevice(AutoUnmapDevice&& other) = default; ~AutoUnmapDevice(); private: DISALLOW_COPY_AND_ASSIGN(AutoUnmapDevice); - android::dm::DeviceMapper* dm_ = nullptr; + android::dm::IDeviceMapper* dm_ = nullptr; }; // Automatically unmap an image upon deletion.