Merge "libsnapshot: Move ImageManager creation to DeviceInfo." am: 9ac43f5421

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

Change-Id: I29ed378aa7c22664156572452184172f6044a368
This commit is contained in:
David Anderson 2021-05-14 00:29:31 +00:00 committed by Automerger Merge Worker
commit 260c7f6e3d
11 changed files with 117 additions and 55 deletions

View file

@ -266,7 +266,7 @@ cc_defaults {
"android.hardware.boot@1.1",
"libbrotli",
"libc++fs",
"libfs_mgr",
"libfs_mgr_binder",
"libgsi",
"libgmock",
"liblp",
@ -421,8 +421,8 @@ cc_defaults {
"snapuserd_server.cpp",
"snapuserd.cpp",
"snapuserd_daemon.cpp",
"snapuserd_worker.cpp",
"snapuserd_readahead.cpp",
"snapuserd_worker.cpp",
"snapuserd_readahead.cpp",
],
cflags: [
@ -564,7 +564,7 @@ cc_test {
srcs: [
"cow_snapuserd_test.cpp",
"snapuserd.cpp",
"snapuserd_worker.cpp",
"snapuserd_worker.cpp",
],
cflags: [
"-Wall",
@ -581,7 +581,7 @@ cc_test {
"libsnapshot_snapuserd",
"libcutils_sockets",
"libz",
"libfs_mgr",
"libfs_mgr",
"libdm",
],
header_libs: [

View file

@ -0,0 +1,41 @@
device_info_data {
allow_set_slot_as_unbootable: true
is_recovery: true
}
is_super_metadata_valid: true
super_data {
partitions {
partition_name: "sys_a"
new_partition_info {
size: 3145728
}
}
partitions {
partition_name: "vnnd_"
new_partition_info {
size: 3145728
}
}
partitions {
partition_name: "prd_a"
new_partition_info {
}
}
dynamic_partition_metadata {
groups {
name: "group_google_dp_a"
size: 34375467008
partition_names: "sys_a"
partition_names: "vnd_a"
partition_names: "prd_a"
}
}
}
has_metadata_snapshots_dir: true
actions {
handle_imminent_data_wipe: true
}
actions {
begin_update {
}
}

View file

@ -17,6 +17,7 @@
#include <android-base/logging.h>
#include <fs_mgr.h>
#include <fs_mgr_overlayfs.h>
#include <libfiemap/image_manager.h>
namespace android {
namespace snapshot {
@ -26,6 +27,7 @@ using android::hardware::boot::V1_0::BoolResult;
using android::hardware::boot::V1_0::CommandResult;
#endif
using namespace std::chrono_literals;
using namespace std::string_literals;
#ifdef __ANDROID_RECOVERY__
@ -34,10 +36,6 @@ constexpr bool kIsRecovery = true;
constexpr bool kIsRecovery = false;
#endif
std::string DeviceInfo::GetGsidDir() const {
return "ota"s;
}
std::string DeviceInfo::GetMetadataDir() const {
return "/metadata/ota"s;
}
@ -100,6 +98,10 @@ bool DeviceInfo::IsRecovery() const {
return kIsRecovery;
}
bool DeviceInfo::IsFirstStageInit() const {
return first_stage_init_;
}
bool DeviceInfo::SetSlotAsUnbootable([[maybe_unused]] unsigned int slot) {
#ifdef LIBSNAPSHOT_USE_HAL
if (!EnsureBootHal()) {
@ -120,5 +122,22 @@ bool DeviceInfo::SetSlotAsUnbootable([[maybe_unused]] unsigned int slot) {
#endif
}
std::unique_ptr<android::fiemap::IImageManager> DeviceInfo::OpenImageManager() const {
return IDeviceInfo::OpenImageManager("ota");
}
std::unique_ptr<android::fiemap::IImageManager> ISnapshotManager::IDeviceInfo::OpenImageManager(
const std::string& gsid_dir) const {
if (IsRecovery() || IsFirstStageInit()) {
android::fiemap::ImageManager::DeviceInfo device_info = {
.is_recovery = {IsRecovery()},
};
return android::fiemap::ImageManager::Open(gsid_dir, device_info);
} else {
// For now, use a preset timeout.
return android::fiemap::IImageManager::Open(gsid_dir, 15000ms);
}
}
} // namespace snapshot
} // namespace android

View file

@ -29,7 +29,6 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo {
using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
public:
std::string GetGsidDir() const override;
std::string GetMetadataDir() const override;
std::string GetSlotSuffix() const override;
std::string GetOtherSlotSuffix() const override;
@ -39,11 +38,16 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo {
bool SetBootControlMergeStatus(MergeStatus status) override;
bool SetSlotAsUnbootable(unsigned int slot) override;
bool IsRecovery() const override;
std::unique_ptr<IImageManager> OpenImageManager() const override;
bool IsFirstStageInit() const override;
void set_first_stage_init(bool value) { first_stage_init_ = value; }
private:
bool EnsureBootHal();
android::fs_mgr::PartitionOpener opener_;
bool first_stage_init_ = false;
#ifdef LIBSNAPSHOT_USE_HAL
android::sp<android::hardware::boot::V1_1::IBootControl> boot_control_;
#endif

View file

@ -22,7 +22,6 @@ namespace android::snapshot {
class MockDeviceInfo : public SnapshotManager::IDeviceInfo {
public:
MOCK_METHOD(std::string, GetGsidDir, (), (const, override));
MOCK_METHOD(std::string, GetMetadataDir, (), (const, override));
MOCK_METHOD(std::string, GetSlotSuffix, (), (const, override));
MOCK_METHOD(std::string, GetOtherSlotSuffix, (), (const, override));
@ -32,6 +31,9 @@ class MockDeviceInfo : public SnapshotManager::IDeviceInfo {
MOCK_METHOD(bool, SetBootControlMergeStatus, (MergeStatus status), (override));
MOCK_METHOD(bool, SetSlotAsUnbootable, (unsigned int slot), (override));
MOCK_METHOD(bool, IsRecovery, (), (const, override));
MOCK_METHOD(bool, IsFirstStageInit, (), (const, override));
MOCK_METHOD(std::unique_ptr<android::fiemap::IImageManager>, OpenImageManager, (),
(const, override));
};
} // namespace android::snapshot

View file

@ -94,8 +94,9 @@ class ISnapshotManager {
// Dependency injection for testing.
class IDeviceInfo {
public:
using IImageManager = android::fiemap::IImageManager;
virtual ~IDeviceInfo() {}
virtual std::string GetGsidDir() const = 0;
virtual std::string GetMetadataDir() const = 0;
virtual std::string GetSlotSuffix() const = 0;
virtual std::string GetOtherSlotSuffix() const = 0;
@ -107,6 +108,11 @@ class ISnapshotManager {
virtual bool SetSlotAsUnbootable(unsigned int slot) = 0;
virtual bool IsRecovery() const = 0;
virtual bool IsTestDevice() const { return false; }
virtual bool IsFirstStageInit() const = 0;
virtual std::unique_ptr<IImageManager> OpenImageManager() const = 0;
// Helper method for implementing OpenImageManager.
std::unique_ptr<IImageManager> OpenImageManager(const std::string& gsid_dir) const;
};
virtual ~ISnapshotManager() = default;
@ -420,7 +426,6 @@ class SnapshotManager final : public ISnapshotManager {
bool EnsureSnapuserdConnected();
// Helpers for first-stage init.
bool ForceLocalImageManager();
const std::unique_ptr<IDeviceInfo>& device() const { return device_; }
// Helper functions for tests.
@ -765,7 +770,6 @@ class SnapshotManager final : public ISnapshotManager {
std::string metadata_dir_;
std::unique_ptr<IDeviceInfo> device_;
std::unique_ptr<IImageManager> images_;
bool has_local_image_manager_ = false;
bool use_first_stage_snapuserd_ = false;
bool in_factory_data_reset_ = false;
std::function<bool(const std::string&)> uevent_regen_callback_;

View file

@ -77,7 +77,6 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
: TestDeviceInfo(fake_super) {
set_slot_suffix(slot_suffix);
}
std::string GetGsidDir() const override { return "ota/test"s; }
std::string GetMetadataDir() const override { return "/metadata/ota/test"s; }
std::string GetSlotSuffix() const override { return slot_suffix_; }
std::string GetOtherSlotSuffix() const override { return slot_suffix_ == "_a" ? "_b" : "_a"; }
@ -96,6 +95,10 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
return true;
}
bool IsTestDevice() const override { return true; }
bool IsFirstStageInit() const override { return first_stage_init_; }
std::unique_ptr<IImageManager> OpenImageManager() const override {
return IDeviceInfo::OpenImageManager("ota/test");
}
bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; }
@ -104,6 +107,7 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
opener_ = std::make_unique<TestPartitionOpener>(path);
}
void set_recovery(bool value) { recovery_ = value; }
void set_first_stage_init(bool value) { first_stage_init_ = value; }
MergeStatus merge_status() const { return merge_status_; }
private:
@ -111,6 +115,7 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
std::unique_ptr<TestPartitionOpener> opener_;
MergeStatus merge_status_;
bool recovery_ = false;
bool first_stage_init_ = false;
std::unordered_set<uint32_t> unbootable_slots_;
};

View file

@ -95,18 +95,16 @@ std::unique_ptr<SnapshotManager> SnapshotManager::New(IDeviceInfo* info) {
if (!info) {
info = new DeviceInfo();
}
auto sm = std::unique_ptr<SnapshotManager>(new SnapshotManager(info));
if (info->IsRecovery()) {
sm->ForceLocalImageManager();
}
return sm;
return std::unique_ptr<SnapshotManager>(new SnapshotManager(info));
}
std::unique_ptr<SnapshotManager> SnapshotManager::NewForFirstStageMount(IDeviceInfo* info) {
auto sm = New(info);
if (!sm || !sm->ForceLocalImageManager()) {
return nullptr;
if (!info) {
DeviceInfo* impl = new DeviceInfo();
impl->set_first_stage_init(true);
info = impl;
}
auto sm = New(info);
// The first-stage version of snapuserd is explicitly started by init. Do
// not attempt to using it during tests (which run in normal AOSP).
@ -117,7 +115,6 @@ std::unique_ptr<SnapshotManager> SnapshotManager::NewForFirstStageMount(IDeviceI
}
SnapshotManager::SnapshotManager(IDeviceInfo* device) : device_(device) {
gsid_dir_ = device_->GetGsidDir();
metadata_dir_ = device_->GetMetadataDir();
}
@ -538,9 +535,7 @@ std::optional<std::string> SnapshotManager::MapCowImage(
bool ok;
std::string cow_dev;
if (has_local_image_manager_) {
// If we forced a local image manager, it means we don't have binder,
// which means first-stage init. We must use device-mapper.
if (device_->IsRecovery() || device_->IsFirstStageInit()) {
const auto& opener = device_->GetPartitionOpener();
ok = images_->MapImageWithDeviceMapper(opener, cow_image_name, &cow_dev);
} else {
@ -1836,6 +1831,10 @@ bool SnapshotManager::MapAllPartitions(LockedFile* lock, const std::string& supe
return false;
}
if (!EnsureImageManager()) {
return false;
}
for (const auto& partition : metadata->partitions) {
if (GetPartitionGroupName(metadata->groups[partition.group_index]) == kCowGroupName) {
LOG(INFO) << "Skip mapping partition " << GetPartitionName(partition) << " in group "
@ -2556,8 +2555,7 @@ bool SnapshotManager::WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus
bool SnapshotManager::EnsureImageManager() {
if (images_) return true;
// For now, use a preset timeout.
images_ = android::fiemap::IImageManager::Open(gsid_dir_, 15000ms);
images_ = device_->OpenImageManager();
if (!images_) {
LOG(ERROR) << "Could not open ImageManager";
return false;
@ -2582,20 +2580,6 @@ bool SnapshotManager::EnsureSnapuserdConnected() {
return true;
}
bool SnapshotManager::ForceLocalImageManager() {
android::fiemap::ImageManager::DeviceInfo device_info = {
.is_recovery = {device_->IsRecovery()},
};
images_ = android::fiemap::ImageManager::Open(gsid_dir_, device_info);
if (!images_) {
LOG(ERROR) << "Could not open ImageManager";
return false;
}
has_local_image_manager_ = true;
return true;
}
void SnapshotManager::UnmapAndDeleteCowPartition(MetadataBuilder* current_metadata) {
std::vector<std::string> to_delete;
for (auto* existing_cow_partition : current_metadata->ListPartitionsInGroup(kCowGroupName)) {

View file

@ -381,8 +381,9 @@ void SnapshotFuzzEnv::CheckSoftReset() {
CheckDetachLoopDevices({Basename(fake_super_), Basename(fake_data_block_device_)});
}
std::unique_ptr<IImageManager> SnapshotFuzzEnv::CheckCreateFakeImageManager(
const std::string& metadata_dir, const std::string& data_dir) {
std::unique_ptr<IImageManager> SnapshotFuzzEnv::CheckCreateFakeImageManager() {
auto metadata_dir = fake_root_->tmp_path() + "/images_manager_metadata";
auto data_dir = fake_data_mount_point_ + "/image_manager_data";
PCHECK(Mkdir(metadata_dir));
PCHECK(Mkdir(data_dir));
return SnapshotFuzzImageManager::Open(metadata_dir, data_dir);
@ -428,13 +429,9 @@ SnapshotTestModule SnapshotFuzzEnv::CheckCreateSnapshotManager(const SnapshotFuz
PCHECK(Mkdir(metadata_dir + "/snapshots"));
}
ret.device_info = new SnapshotFuzzDeviceInfo(data.device_info_data(),
ret.device_info = new SnapshotFuzzDeviceInfo(this, data.device_info_data(),
std::move(partition_opener), metadata_dir);
auto snapshot = SnapshotManager::New(ret.device_info /* takes ownership */);
snapshot->images_ =
CheckCreateFakeImageManager(fake_root_->tmp_path() + "/images_manager_metadata",
fake_data_mount_point_ + "/image_manager_data");
snapshot->has_local_image_manager_ = data.manager_data().is_local_image_manager();
ret.snapshot = std::move(snapshot);
return ret;

View file

@ -65,6 +65,8 @@ class SnapshotFuzzEnv {
// ISnapshotManager.
SnapshotTestModule CheckCreateSnapshotManager(const SnapshotFuzzData& data);
std::unique_ptr<android::fiemap::IImageManager> CheckCreateFakeImageManager();
// Return path to super partition.
const std::string& super() const;
@ -79,8 +81,6 @@ class SnapshotFuzzEnv {
std::string fake_data_block_device_;
std::unique_ptr<AutoDevice> mounted_data_;
static std::unique_ptr<android::fiemap::IImageManager> CheckCreateFakeImageManager(
const std::string& metadata_dir, const std::string& data_dir);
static std::unique_ptr<AutoDevice> CheckMapImage(const std::string& fake_persist_path,
uint64_t size,
android::dm::LoopControl* control,
@ -95,15 +95,15 @@ class SnapshotFuzzEnv {
class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
public:
// Client is responsible for maintaining the lifetime of |data|.
SnapshotFuzzDeviceInfo(const FuzzDeviceInfoData& data,
SnapshotFuzzDeviceInfo(SnapshotFuzzEnv* env, const FuzzDeviceInfoData& data,
std::unique_ptr<TestPartitionOpener>&& partition_opener,
const std::string& metadata_dir)
: data_(&data),
: env_(env),
data_(&data),
partition_opener_(std::move(partition_opener)),
metadata_dir_(metadata_dir) {}
// Following APIs are mocked.
std::string GetGsidDir() const override { return "fuzz_ota"; }
std::string GetMetadataDir() const override { return metadata_dir_; }
std::string GetSuperDevice(uint32_t) const override {
// TestPartitionOpener can recognize this.
@ -124,10 +124,15 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
return data_->allow_set_slot_as_unbootable();
}
bool IsRecovery() const override { return data_->is_recovery(); }
bool IsFirstStageInit() const override { return false; }
std::unique_ptr<IImageManager> OpenImageManager() const {
return env_->CheckCreateFakeImageManager();
}
void SwitchSlot() { switched_slot_ = !switched_slot_; }
private:
SnapshotFuzzEnv* env_;
const FuzzDeviceInfoData* data_;
std::unique_ptr<TestPartitionOpener> partition_opener_;
std::string metadata_dir_;

View file

@ -403,6 +403,7 @@ class SnapshotTest : public ::testing::Test {
}
std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(TestDeviceInfo* info) {
info->set_first_stage_init(true);
auto init = SnapshotManager::NewForFirstStageMount(info);
if (!init) {
return nullptr;