summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2022-01-05 00:39:24 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-01-05 00:39:24 +0000
commitec68504cf96695c0f09c35cbb988f15d28b42af6 (patch)
tree4b9d4e3cfacf568ef1d01e676f51631d504bc528
parentbd925574f27a8d32f24c74f2ca55360a00ca3cbd (diff)
parent508aecb13e9cea8fd1dacf47f14fb5dc95dfad8f (diff)
Merge changes I219f956b,I281937e2 am: a216080a63 am: fc8ed5d9d5
Original change: https://android-review.googlesource.com/c/platform/system/core/+/1935201 Change-Id: I16ebd75b0f0c9878d01ecc217e182c99cc064d2d
-rw-r--r--fs_mgr/libsnapshot/device_info.cpp6
-rw-r--r--fs_mgr/libsnapshot/device_info.h1
-rw-r--r--fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h1
-rw-r--r--fs_mgr/libsnapshot/include/libsnapshot/snapshot.h1
-rw-r--r--fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h1
-rw-r--r--fs_mgr/libsnapshot/partition_cow_creator.cpp2
-rw-r--r--fs_mgr/libsnapshot/partition_cow_creator.h1
-rw-r--r--fs_mgr/libsnapshot/snapshot.cpp138
-rw-r--r--fs_mgr/libsnapshot/snapshot_fuzz_utils.h1
-rw-r--r--fs_mgr/libsnapshot/snapshot_test.cpp10
-rw-r--r--fs_mgr/libsnapshot/test_helpers.cpp6
11 files changed, 98 insertions, 70 deletions
diff --git a/fs_mgr/libsnapshot/device_info.cpp b/fs_mgr/libsnapshot/device_info.cpp
index a6d96ed829..5c1b291c5f 100644
--- a/fs_mgr/libsnapshot/device_info.cpp
+++ b/fs_mgr/libsnapshot/device_info.cpp
@@ -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
diff --git a/fs_mgr/libsnapshot/device_info.h b/fs_mgr/libsnapshot/device_info.h
index 8aefb85078..a07f554a86 100644
--- a/fs_mgr/libsnapshot/device_info.h
+++ b/fs_mgr/libsnapshot/device_info.h
@@ -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; }
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
index 573a85b240..8c4161c22f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_device_info.h
@@ -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
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 41c6ef5763..f7e37bbcc4 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -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;
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index c3b40dca40..07c3ec5b56 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -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) {
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.cpp b/fs_mgr/libsnapshot/partition_cow_creator.cpp
index 5569da0383..5fcbdfe117 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator.cpp
@@ -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;
diff --git a/fs_mgr/libsnapshot/partition_cow_creator.h b/fs_mgr/libsnapshot/partition_cow_creator.h
index 34b39ca725..1f34177786 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator.h
+++ b/fs_mgr/libsnapshot/partition_cow_creator.h
@@ -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 {
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index e6e17bdf32..c7c5da1f3e 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -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,32 +3134,40 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
.compression_algorithm = compression_algorithm,
};
- auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
- &all_snapshot_status);
- if (!ret.is_ok()) return ret;
-
- auto exported_target_metadata = target_metadata->Export();
- if (exported_target_metadata == nullptr) {
- LOG(ERROR) << "Cannot export target metadata";
- return Return::Error();
+ 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;
- ret = InitializeUpdateSnapshots(lock.get(), target_metadata.get(),
- exported_target_metadata.get(), target_suffix,
- all_snapshot_status);
- if (!ret.is_ok()) return ret;
+ 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;
+ }
- if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot),
- *exported_target_metadata, target_slot)) {
- LOG(ERROR) << "Cannot write target metadata";
- return Return::Error();
+ // 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.
- if (cow_creator.compression_enabled) {
+ //
+ // 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";
@@ -3171,46 +3181,32 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife
}
}
+ auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
+ &all_snapshot_status);
+ if (!ret.is_ok()) return ret;
+
+ auto exported_target_metadata = target_metadata->Export();
+ if (exported_target_metadata == nullptr) {
+ LOG(ERROR) << "Cannot export target metadata";
+ return Return::Error();
+ }
+
+ ret = InitializeUpdateSnapshots(lock.get(), target_metadata.get(),
+ exported_target_metadata.get(), target_suffix,
+ all_snapshot_status);
+ if (!ret.is_ok()) return ret;
+
+ if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot),
+ *exported_target_metadata, target_slot)) {
+ LOG(ERROR) << "Cannot write target metadata";
+ 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;
}
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
index c1a5af77d7..63159dc9d4 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
@@ -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_; }
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 14f2d45be1..c70b353ede 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -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";
}
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index e3e3af853d..2cd13e0447 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -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