Merge "libdm, libsnapshot: Add a virtual interface for DeviceMapper." am: 5cd741583f

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1825107

Change-Id: I5b6aa6445809c808cf4d4cac8769f7d42cfe1bac
This commit is contained in:
David Anderson 2021-09-23 22:39:48 +00:00 committed by Automerger Merge Worker
commit 8005743be4
9 changed files with 93 additions and 86 deletions

View file

@ -55,7 +55,33 @@ static constexpr uint64_t kSectorSize = 512;
// that prefix.
std::optional<std::string> 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<TargetInfo>* table) = 0;
virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* 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<TargetInfo>* table);
bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* 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<TargetInfo>* table);
bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) override;
static std::string GetTargetType(const struct dm_target_spec& spec);

View file

@ -152,6 +152,7 @@ cc_test {
static_libs: [
"libavb",
"libdm",
"libext2_uuid",
"libfs_avb",
"libfstab",
],

View file

@ -139,5 +139,9 @@ std::unique_ptr<android::fiemap::IImageManager> ISnapshotManager::IDeviceInfo::O
}
}
android::dm::IDeviceMapper& DeviceInfo::GetDeviceMapper() {
return android::dm::DeviceMapper::Instance();
}
} // namespace snapshot
} // namespace android

View file

@ -40,6 +40,7 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo {
bool IsRecovery() const override;
std::unique_ptr<IImageManager> OpenImageManager() const override;
bool IsFirstStageInit() const override;
android::dm::IDeviceMapper& GetDeviceMapper() override;
void set_first_stage_init(bool value) { first_stage_init_ = value; }

View file

@ -110,6 +110,7 @@ class ISnapshotManager {
virtual bool IsTestDevice() const { return false; }
virtual bool IsFirstStageInit() const = 0;
virtual std::unique_ptr<IImageManager> OpenImageManager() const = 0;
virtual android::dm::IDeviceMapper& GetDeviceMapper() = 0;
// Helper method for implementing OpenImageManager.
std::unique_ptr<IImageManager> 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<IDeviceInfo> device_;
std::string metadata_dir_;
std::unique_ptr<IImageManager> images_;
bool use_first_stage_snapuserd_ = false;
bool in_factory_data_reset_ = false;

View file

@ -99,6 +99,9 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
std::unique_ptr<IImageManager> 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; }

View file

@ -114,9 +114,8 @@ std::unique_ptr<SnapshotManager> 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<DmTargetUser>(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.
@ -528,7 +523,7 @@ bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,
DmTable table;
table.Emplace<DmTargetSnapshot>(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;
}
@ -659,7 +654,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.
@ -671,7 +665,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;
}
@ -804,10 +798,8 @@ MergeFailureCode SnapshotManager::SwitchSnapshotToMerge(LockedFile* lock, const
}
MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& name) {
auto& dm = DeviceMapper::Instance();
std::vector<DeviceMapper::TargetInfo> 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;
}
@ -825,7 +817,7 @@ MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string&
DmTable table;
table.Emplace<DmTargetSnapshot>(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;
}
@ -833,24 +825,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<DeviceMapper::TargetInfo> 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;
@ -1180,11 +1166,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;
}
@ -1360,8 +1344,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)) {
@ -1400,7 +1382,7 @@ bool SnapshotManager::CollapseSnapshotDevice(const std::string& name,
return false;
}
if (!dm.LoadTableAndActivate(name, table)) {
if (!dm_.LoadTableAndActivate(name, table)) {
return false;
}
@ -1473,8 +1455,6 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition,
}
}
auto& dm = DeviceMapper::Instance();
auto lock = LockExclusive();
if (!lock) return false;
@ -1488,7 +1468,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;
}
@ -1515,7 +1495,7 @@ bool SnapshotManager::PerformInitTransition(InitTransition transition,
DmTable table;
table.Emplace<DmTargetUser>(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;
}
@ -1528,7 +1508,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;
}
@ -1536,7 +1516,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;
}
@ -1711,8 +1691,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;
@ -2049,14 +2028,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<AutoUnmapDevice>(&dm, params.GetDeviceName());
created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, params.GetDeviceName());
if (paths) {
paths->target_device = base_path;
@ -2070,7 +2048,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;
}
@ -2113,7 +2091,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
}
auto source_device = GetSourceDeviceName(params.GetPartitionName());
created_devices.EmplaceBack<AutoUnmapDevice>(&dm, source_device);
created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, source_device);
} else {
source_device_path = base_path;
}
@ -2140,7 +2118,7 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
<< params.GetPartitionName();
return false;
}
created_devices.EmplaceBack<AutoUnmapDevice>(&dm, name);
created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, name);
remaining_time = GetRemainingTime(params.timeout_ms, begin);
if (remaining_time.count() < 0) return false;
@ -2206,8 +2184,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;
@ -2258,11 +2234,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<AutoUnmapDevice>(&dm, *cow_name);
created_devices->EmplaceBack<AutoUnmapDevice>(&dm_, *cow_name);
LOG(INFO) << "Mapped COW device for " << params.GetPartitionName() << " at " << cow_path;
return true;
}
@ -2289,10 +2265,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;
}
@ -3512,7 +3486,6 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
return false;
}
auto& dm = DeviceMapper::Instance();
for (const auto& snapshot : snapshots) {
SnapshotStatus status;
if (!ReadSnapshotStatus(lock, snapshot, &status)) {
@ -3523,7 +3496,7 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
}
std::vector<DeviceMapper::TargetInfo> targets;
if (!dm.GetTableStatus(snapshot, &targets)) {
if (!dm_.GetTableStatus(snapshot, &targets)) {
LOG(ERROR) << "Could not read snapshot device table: " << snapshot;
return false;
}
@ -3616,11 +3589,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.
@ -3629,10 +3600,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.
@ -3748,10 +3718,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();
@ -3764,7 +3733,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;
}

View file

@ -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<IImageManager> OpenImageManager() const {
return env_->CheckCreateFakeImageManager();
}
@ -137,6 +139,7 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
std::unique_ptr<TestPartitionOpener> 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_; }
};

View file

@ -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.