Merge changes I219f956b,I281937e2
* changes: libsnapshot: Fix libsnapshot_fuzzer_test. libsnapshot: Fix checks for compression to work with new snapuserd.
This commit is contained in:
commit
a216080a63
11 changed files with 99 additions and 71 deletions
|
@ -19,6 +19,8 @@
|
|||
#include <fs_mgr_overlayfs.h>
|
||||
#include <libfiemap/image_manager.h>
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
|
@ -143,5 +145,9 @@ android::dm::IDeviceMapper& DeviceInfo::GetDeviceMapper() {
|
|||
return android::dm::DeviceMapper::Instance();
|
||||
}
|
||||
|
||||
bool DeviceInfo::UseUserspaceSnapshots() const {
|
||||
return IsUserspaceSnapshotsEnabled();
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
|
|
|
@ -41,6 +41,7 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo {
|
|||
std::unique_ptr<IImageManager> OpenImageManager() const override;
|
||||
bool IsFirstStageInit() const override;
|
||||
android::dm::IDeviceMapper& GetDeviceMapper() override;
|
||||
bool UseUserspaceSnapshots() const override;
|
||||
|
||||
void set_first_stage_init(bool value) { first_stage_init_ = value; }
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ class MockDeviceInfo : public SnapshotManager::IDeviceInfo {
|
|||
MOCK_METHOD(bool, IsFirstStageInit, (), (const, override));
|
||||
MOCK_METHOD(std::unique_ptr<android::fiemap::IImageManager>, OpenImageManager, (),
|
||||
(const, override));
|
||||
MOCK_METHOD(bool, UseUserspaceSnapshots, (), (const, override));
|
||||
};
|
||||
|
||||
} // namespace android::snapshot
|
||||
|
|
|
@ -111,6 +111,7 @@ class ISnapshotManager {
|
|||
virtual bool IsFirstStageInit() const = 0;
|
||||
virtual std::unique_ptr<IImageManager> OpenImageManager() const = 0;
|
||||
virtual android::dm::IDeviceMapper& GetDeviceMapper() = 0;
|
||||
virtual bool UseUserspaceSnapshots() const = 0;
|
||||
|
||||
// Helper method for implementing OpenImageManager.
|
||||
std::unique_ptr<IImageManager> OpenImageManager(const std::string& gsid_dir) const;
|
||||
|
|
|
@ -107,6 +107,7 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
|
|||
}
|
||||
|
||||
bool IsSlotUnbootable(uint32_t slot) { return unbootable_slots_.count(slot) != 0; }
|
||||
bool UseUserspaceSnapshots() const override;
|
||||
|
||||
void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
|
||||
void set_fake_super(const std::string& path) {
|
||||
|
|
|
@ -143,7 +143,7 @@ void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Exte
|
|||
}
|
||||
|
||||
std::optional<uint64_t> PartitionCowCreator::GetCowSize() {
|
||||
if (compression_enabled) {
|
||||
if (compression_enabled || userspace_snapshots_enabled) {
|
||||
if (update == nullptr || !update->has_estimate_cow_size()) {
|
||||
LOG(ERROR) << "Update manifest does not include a COW size";
|
||||
return std::nullopt;
|
||||
|
|
|
@ -58,6 +58,7 @@ struct PartitionCowCreator {
|
|||
std::vector<ChromeOSExtent> extra_extents = {};
|
||||
// True if compression is enabled.
|
||||
bool compression_enabled = false;
|
||||
bool userspace_snapshots_enabled = false;
|
||||
std::string compression_algorithm;
|
||||
|
||||
struct Return {
|
||||
|
|
|
@ -1329,7 +1329,7 @@ MergeFailureCode SnapshotManager::CheckMergeConsistency(LockedFile* lock, const
|
|||
const SnapshotStatus& status) {
|
||||
CHECK(lock);
|
||||
|
||||
if (!status.compression_enabled()) {
|
||||
if (!status.compression_enabled() && !UpdateUsesUserSnapshots(lock)) {
|
||||
// Do not try to verify old-style COWs yet.
|
||||
return MergeFailureCode::Ok;
|
||||
}
|
||||
|
@ -2345,13 +2345,15 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
|
|||
remaining_time = GetRemainingTime(params.timeout_ms, begin);
|
||||
if (remaining_time.count() < 0) return false;
|
||||
|
||||
if (context == SnapshotContext::Update && live_snapshot_status->compression_enabled()) {
|
||||
// Stop here, we can't run dm-user yet, the COW isn't built.
|
||||
created_devices.Release();
|
||||
return true;
|
||||
if (context == SnapshotContext::Update) {
|
||||
if (UpdateUsesUserSnapshots(lock) || live_snapshot_status->compression_enabled()) {
|
||||
// Stop here, we can't run dm-user yet, the COW isn't built.
|
||||
created_devices.Release();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (live_snapshot_status->compression_enabled()) {
|
||||
if (UpdateUsesUserSnapshots(lock) || live_snapshot_status->compression_enabled()) {
|
||||
// Get the source device (eg the view of the partition from before it was resized).
|
||||
std::string source_device_path;
|
||||
if (live_snapshot_status->old_partition_size() > 0) {
|
||||
|
@ -3132,6 +3134,53 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
|
|||
.compression_algorithm = compression_algorithm,
|
||||
};
|
||||
|
||||
cow_creator.userspace_snapshots_enabled = device_->UseUserspaceSnapshots();
|
||||
if (cow_creator.userspace_snapshots_enabled) {
|
||||
LOG(INFO) << "User-space snapshots enabled, compression = " << compression_algorithm;
|
||||
} else {
|
||||
LOG(INFO) << "User-space snapshots disabled, compression = " << compression_algorithm;
|
||||
}
|
||||
is_snapshot_userspace_ = cow_creator.userspace_snapshots_enabled;
|
||||
|
||||
if ((use_compression || is_snapshot_userspace_) && !device()->IsTestDevice()) {
|
||||
// Terminate stale daemon if any
|
||||
std::unique_ptr<SnapuserdClient> snapuserd_client =
|
||||
SnapuserdClient::Connect(kSnapuserdSocket, 10s);
|
||||
if (snapuserd_client) {
|
||||
snapuserd_client->DetachSnapuserd();
|
||||
snapuserd_client->CloseConnection();
|
||||
snapuserd_client = nullptr;
|
||||
}
|
||||
|
||||
// Clear the cached client if any
|
||||
if (snapuserd_client_) {
|
||||
snapuserd_client_->CloseConnection();
|
||||
snapuserd_client_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If compression is enabled, we need to retain a copy of the old metadata
|
||||
// so we can access original blocks in case they are moved around. We do
|
||||
// not want to rely on the old super metadata slot because we don't
|
||||
// guarantee its validity after the slot switch is successful.
|
||||
//
|
||||
// Note that we do this for userspace merges even if compression is
|
||||
// disabled, since the code path expects it even if the source device will
|
||||
// be unused.
|
||||
if (cow_creator.compression_enabled || cow_creator.userspace_snapshots_enabled) {
|
||||
auto metadata = current_metadata->Export();
|
||||
if (!metadata) {
|
||||
LOG(ERROR) << "Could not export current metadata";
|
||||
return Return::Error();
|
||||
}
|
||||
|
||||
auto path = GetOldPartitionMetadataPath();
|
||||
if (!android::fs_mgr::WriteToImageFile(path, *metadata.get())) {
|
||||
LOG(ERROR) << "Cannot write old metadata to " << path;
|
||||
return Return::Error();
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
|
||||
&all_snapshot_status);
|
||||
if (!ret.is_ok()) return ret;
|
||||
|
@ -3153,64 +3202,11 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
|
|||
return Return::Error();
|
||||
}
|
||||
|
||||
// If compression is enabled, we need to retain a copy of the old metadata
|
||||
// so we can access original blocks in case they are moved around. We do
|
||||
// not want to rely on the old super metadata slot because we don't
|
||||
// guarantee its validity after the slot switch is successful.
|
||||
if (cow_creator.compression_enabled) {
|
||||
auto metadata = current_metadata->Export();
|
||||
if (!metadata) {
|
||||
LOG(ERROR) << "Could not export current metadata";
|
||||
return Return::Error();
|
||||
}
|
||||
|
||||
auto path = GetOldPartitionMetadataPath();
|
||||
if (!android::fs_mgr::WriteToImageFile(path, *metadata.get())) {
|
||||
LOG(ERROR) << "Cannot write old metadata to " << path;
|
||||
return Return::Error();
|
||||
}
|
||||
}
|
||||
|
||||
SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
|
||||
status.set_state(update_state);
|
||||
status.set_compression_enabled(cow_creator.compression_enabled);
|
||||
if (cow_creator.compression_enabled) {
|
||||
if (!device()->IsTestDevice()) {
|
||||
// Userspace snapshots is enabled only if compression is enabled
|
||||
status.set_userspace_snapshots(IsUserspaceSnapshotsEnabled());
|
||||
if (IsUserspaceSnapshotsEnabled()) {
|
||||
is_snapshot_userspace_ = true;
|
||||
LOG(INFO) << "User-space snapshots enabled";
|
||||
} else {
|
||||
is_snapshot_userspace_ = false;
|
||||
LOG(INFO) << "User-space snapshots disabled";
|
||||
}
|
||||
status.set_userspace_snapshots(cow_creator.userspace_snapshots_enabled);
|
||||
|
||||
// Terminate stale daemon if any
|
||||
std::unique_ptr<SnapuserdClient> snapuserd_client =
|
||||
SnapuserdClient::Connect(kSnapuserdSocket, 10s);
|
||||
if (snapuserd_client) {
|
||||
snapuserd_client->DetachSnapuserd();
|
||||
snapuserd_client->CloseConnection();
|
||||
snapuserd_client = nullptr;
|
||||
}
|
||||
|
||||
// Clear the cached client if any
|
||||
if (snapuserd_client_) {
|
||||
snapuserd_client_->CloseConnection();
|
||||
snapuserd_client_ = nullptr;
|
||||
}
|
||||
} else {
|
||||
status.set_userspace_snapshots(!IsDmSnapshotTestingEnabled());
|
||||
if (IsDmSnapshotTestingEnabled()) {
|
||||
is_snapshot_userspace_ = false;
|
||||
LOG(INFO) << "User-space snapshots disabled for testing";
|
||||
} else {
|
||||
is_snapshot_userspace_ = true;
|
||||
LOG(INFO) << "User-space snapshots enabled for testing";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WriteSnapshotUpdateStatus(lock.get(), status)) {
|
||||
LOG(ERROR) << "Unable to write new update state";
|
||||
return Return::Error();
|
||||
|
@ -3374,6 +3370,8 @@ Return SnapshotManager::InitializeUpdateSnapshots(
|
|||
const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
|
||||
CHECK(lock);
|
||||
|
||||
bool userspace_merges = UpdateUsesUserSnapshots(lock);
|
||||
|
||||
CreateLogicalPartitionParams cow_params{
|
||||
.block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
|
||||
.metadata = exported_target_metadata,
|
||||
|
@ -3403,7 +3401,7 @@ Return SnapshotManager::InitializeUpdateSnapshots(
|
|||
return Return::Error();
|
||||
}
|
||||
|
||||
if (it->second.compression_enabled()) {
|
||||
if (userspace_merges || it->second.compression_enabled()) {
|
||||
unique_fd fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
|
||||
if (fd < 0) {
|
||||
PLOG(ERROR) << "open " << cow_path << " failed for snapshot "
|
||||
|
@ -3449,8 +3447,8 @@ bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& para
|
|||
if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
|
||||
return false;
|
||||
}
|
||||
if (status.compression_enabled()) {
|
||||
LOG(ERROR) << "Cannot use MapUpdateSnapshot with compressed snapshots";
|
||||
if (status.compression_enabled() || UpdateUsesUserSnapshots(lock.get())) {
|
||||
LOG(ERROR) << "Cannot use MapUpdateSnapshot with user snapshots";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3507,7 +3505,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (status.compression_enabled()) {
|
||||
if (status.compression_enabled() || UpdateUsesUserSnapshots(lock.get())) {
|
||||
return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(),
|
||||
status, paths);
|
||||
}
|
||||
|
@ -3647,6 +3645,7 @@ bool SnapshotManager::Dump(std::ostream& os) {
|
|||
<< (access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0 ? "exists" : strerror(errno))
|
||||
<< std::endl;
|
||||
ss << "Source build fingerprint: " << update_status.source_build_fingerprint() << std::endl;
|
||||
ss << "Using userspace snapshots: " << UpdateUsesUserSnapshots(file.get()) << std::endl;
|
||||
|
||||
bool ok = true;
|
||||
std::vector<std::string> snapshots;
|
||||
|
@ -3847,6 +3846,10 @@ UpdateState SnapshotManager::ProcessUpdateStateOnDataWipe(bool allow_forward_mer
|
|||
bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
|
||||
CHECK(lock);
|
||||
|
||||
if (UpdateUsesUserSnapshots(lock)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> snapshots;
|
||||
if (!ListSnapshots(lock, &snapshots)) {
|
||||
LOG(ERROR) << "Could not list snapshots.";
|
||||
|
@ -3859,6 +3862,7 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
|
|||
return false;
|
||||
}
|
||||
if (status.compression_enabled()) {
|
||||
// Compressed snapshots are never written through dm-snapshot.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4022,7 +4026,10 @@ bool SnapshotManager::IsSnapuserdRequired() {
|
|||
if (!lock) return false;
|
||||
|
||||
auto status = ReadSnapshotUpdateStatus(lock.get());
|
||||
return status.state() != UpdateState::None && status.compression_enabled();
|
||||
if (status.state() != UpdateState::None && status.compression_enabled()) {
|
||||
return true;
|
||||
}
|
||||
return UpdateUsesUserSnapshots(lock.get());
|
||||
}
|
||||
|
||||
bool SnapshotManager::DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv) {
|
||||
|
@ -4048,6 +4055,9 @@ const LpMetadata* SnapshotManager::ReadOldPartitionMetadata(LockedFile* lock) {
|
|||
}
|
||||
|
||||
MergePhase SnapshotManager::DecideMergePhase(const SnapshotStatus& status) {
|
||||
// Note: disabling compression disables move operations, so we don't need
|
||||
// separate phases when compression is disabled (irrespective of userspace
|
||||
// merges).
|
||||
if (status.compression_enabled() && status.device_size() < status.old_partition_size()) {
|
||||
return MergePhase::FIRST_PHASE;
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
|
|||
std::unique_ptr<IImageManager> OpenImageManager() const {
|
||||
return env_->CheckCreateFakeImageManager();
|
||||
}
|
||||
bool UseUserspaceSnapshots() const override { return false; }
|
||||
|
||||
void SwitchSlot() { switched_slot_ = !switched_slot_; }
|
||||
|
||||
|
|
|
@ -357,7 +357,7 @@ class SnapshotTest : public ::testing::Test {
|
|||
DeltaArchiveManifest manifest;
|
||||
|
||||
auto dynamic_partition_metadata = manifest.mutable_dynamic_partition_metadata();
|
||||
dynamic_partition_metadata->set_vabc_enabled(IsCompressionEnabled());
|
||||
dynamic_partition_metadata->set_vabc_enabled(ShouldUseCompression());
|
||||
dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
|
||||
|
||||
auto group = dynamic_partition_metadata->add_groups();
|
||||
|
@ -396,7 +396,7 @@ class SnapshotTest : public ::testing::Test {
|
|||
if (!res) {
|
||||
return res;
|
||||
}
|
||||
} else if (!IsCompressionEnabled()) {
|
||||
} else if (!ShouldUseUserspaceSnapshots()) {
|
||||
std::string ignore;
|
||||
if (!MapUpdateSnapshot("test_partition_b", &ignore)) {
|
||||
return AssertionFailure() << "Failed to map test_partition_b";
|
||||
|
@ -1030,7 +1030,7 @@ class SnapshotUpdateTest : public SnapshotTest {
|
|||
}
|
||||
|
||||
AssertionResult MapOneUpdateSnapshot(const std::string& name) {
|
||||
if (ShouldUseCompression()) {
|
||||
if (ShouldUseUserspaceSnapshots()) {
|
||||
std::unique_ptr<ISnapshotWriter> writer;
|
||||
return MapUpdateSnapshot(name, &writer);
|
||||
} else {
|
||||
|
@ -1040,7 +1040,7 @@ class SnapshotUpdateTest : public SnapshotTest {
|
|||
}
|
||||
|
||||
AssertionResult WriteSnapshotAndHash(const std::string& name) {
|
||||
if (ShouldUseCompression()) {
|
||||
if (ShouldUseUserspaceSnapshots()) {
|
||||
std::unique_ptr<ISnapshotWriter> writer;
|
||||
auto res = MapUpdateSnapshot(name, &writer);
|
||||
if (!res) {
|
||||
|
@ -2072,7 +2072,7 @@ TEST_F(SnapshotUpdateTest, Hashtree) {
|
|||
|
||||
// Test for overflow bit after update
|
||||
TEST_F(SnapshotUpdateTest, Overflow) {
|
||||
if (ShouldUseCompression()) {
|
||||
if (ShouldUseUserspaceSnapshots()) {
|
||||
GTEST_SKIP() << "No overflow bit set for userspace COWs";
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <openssl/sha.h>
|
||||
#include <payload_consumer/file_descriptor.h>
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
namespace android {
|
||||
namespace snapshot {
|
||||
|
||||
|
@ -320,5 +322,9 @@ bool IsVirtualAbEnabled() {
|
|||
return android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
|
||||
}
|
||||
|
||||
bool TestDeviceInfo::UseUserspaceSnapshots() const {
|
||||
return !IsDmSnapshotTestingEnabled();
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
|
|
Loading…
Reference in a new issue