Loading fs_mgr/libsnapshot/android/snapshot/snapshot.proto +3 −3 Original line number Diff line number Diff line Loading @@ -97,8 +97,8 @@ message SnapshotStatus { // This is non-zero when |state| == MERGING or MERGE_COMPLETED. uint64 metadata_sectors = 8; // True if compression is enabled, false otherwise. bool compression_enabled = 9; // True if using snapuserd, false otherwise. bool using_snapuserd = 9; // The old partition size (if none existed, this will be zero). uint64 old_partition_size = 10; Loading Loading @@ -184,7 +184,7 @@ message SnapshotUpdateStatus { uint64 metadata_sectors = 4; // Whether compression/dm-user was used for any snapshots. bool compression_enabled = 5; bool using_snapuserd = 5; // Merge phase (if state == MERGING). MergePhase merge_phase = 6; Loading fs_mgr/libsnapshot/partition_cow_creator.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Exte } std::optional<uint64_t> PartitionCowCreator::GetCowSize() { if (compression_enabled) { if (using_snapuserd) { if (update == nullptr || !update->has_estimate_cow_size()) { LOG(ERROR) << "Update manifest does not include a COW size"; return std::nullopt; Loading fs_mgr/libsnapshot/partition_cow_creator.h +2 −2 Original line number Diff line number Diff line Loading @@ -56,8 +56,8 @@ struct PartitionCowCreator { // Extra extents that are going to be invalidated during the update // process. std::vector<ChromeOSExtent> extra_extents = {}; // True if compression is enabled. bool compression_enabled = false; // True if snapuserd COWs are enabled. bool using_snapuserd = false; std::string compression_algorithm; struct Return { Loading fs_mgr/libsnapshot/partition_cow_creator_test.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -249,7 +249,7 @@ TEST_F(PartitionCowCreatorTest, CompressionEnabled) { .target_partition = system_b, .current_metadata = builder_a.get(), .current_suffix = "_a", .compression_enabled = true, .using_snapuserd = true, .update = &update}; auto ret = creator.Run(); Loading @@ -275,7 +275,7 @@ TEST_F(PartitionCowCreatorTest, CompressionWithNoManifest) { .target_partition = system_b, .current_metadata = builder_a.get(), .current_suffix = "_a", .compression_enabled = true, .using_snapuserd = true, .update = nullptr}; auto ret = creator.Run(); Loading fs_mgr/libsnapshot/snapshot.cpp +80 −86 Original line number Diff line number Diff line Loading @@ -398,7 +398,7 @@ bool SnapshotManager::CreateSnapshot(LockedFile* lock, PartitionCowCreator* cow_ status->set_state(SnapshotState::CREATED); status->set_sectors_allocated(0); status->set_metadata_sectors(0); status->set_compression_enabled(cow_creator->compression_enabled); status->set_using_snapuserd(cow_creator->using_snapuserd); status->set_compression_algorithm(cow_creator->compression_algorithm); if (!WriteSnapshotStatus(lock, *status)) { Loading Loading @@ -788,7 +788,7 @@ bool SnapshotManager::InitiateMerge() { } } bool compression_enabled = false; bool using_snapuserd = false; std::vector<std::string> first_merge_group; Loading @@ -809,7 +809,7 @@ bool SnapshotManager::InitiateMerge() { return false; } compression_enabled |= snapshot_status.compression_enabled(); using_snapuserd |= snapshot_status.using_snapuserd(); if (DecideMergePhase(snapshot_status) == MergePhase::FIRST_PHASE) { first_merge_group.emplace_back(snapshot); } Loading @@ -817,7 +817,7 @@ bool SnapshotManager::InitiateMerge() { SnapshotUpdateStatus initial_status = ReadSnapshotUpdateStatus(lock.get()); initial_status.set_state(UpdateState::Merging); initial_status.set_compression_enabled(compression_enabled); initial_status.set_using_snapuserd(using_snapuserd); if (!UpdateUsesUserSnapshots(lock.get())) { initial_status.set_sectors_allocated(initial_target_values.sectors_allocated); Loading Loading @@ -1364,7 +1364,7 @@ MergeFailureCode SnapshotManager::CheckMergeConsistency(LockedFile* lock, const } MergeFailureCode CheckMergeConsistency(const std::string& name, const SnapshotStatus& status) { if (!status.compression_enabled()) { if (!status.using_snapuserd()) { // Do not try to verify old-style COWs yet. return MergeFailureCode::Ok; } Loading Loading @@ -1625,7 +1625,7 @@ bool SnapshotManager::CollapseSnapshotDevice(LockedFile* lock, const std::string // as unmap will fail since dm-user itself was a snapshot device prior // to switching of tables. Unmap will fail as the device will be mounted // by system partitions if (status.compression_enabled()) { if (status.using_snapuserd()) { auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock)); UnmapDmUserDevice(dm_user_name); } Loading Loading @@ -2115,8 +2115,10 @@ bool SnapshotManager::UpdateUsesCompression() { } bool SnapshotManager::UpdateUsesCompression(LockedFile* lock) { // This returns true even if compression is "none", since update_engine is // really just trying to see if snapuserd is in use. SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock); return update_status.compression_enabled(); return update_status.using_snapuserd(); } bool SnapshotManager::UpdateUsesIouring(LockedFile* lock) { Loading Loading @@ -2436,13 +2438,13 @@ 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()) { if (context == SnapshotContext::Update && live_snapshot_status->using_snapuserd()) { // 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 (live_snapshot_status->using_snapuserd()) { // 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) { Loading Loading @@ -2944,7 +2946,7 @@ bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state, // build fingerprint. if (!(state == UpdateState::Initiated || state == UpdateState::None)) { SnapshotUpdateStatus old_status = ReadSnapshotUpdateStatus(lock); status.set_compression_enabled(old_status.compression_enabled()); status.set_using_snapuserd(old_status.using_snapuserd()); status.set_source_build_fingerprint(old_status.source_build_fingerprint()); status.set_merge_phase(old_status.merge_phase()); status.set_userspace_snapshots(old_status.userspace_snapshots()); Loading Loading @@ -3198,18 +3200,42 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife LOG(INFO) << " dap_metadata.cow_version(): " << dap_metadata.cow_version() << " writer.GetCowVersion(): " << writer.GetCowVersion(); bool use_compression = IsCompressionEnabled() && dap_metadata.vabc_enabled() && !device_->IsRecovery() && cow_format_support; // Deduce supported features. bool userspace_snapshots = CanUseUserspaceSnapshots(); bool legacy_compression = GetLegacyCompressionEnabledProperty(); std::string vabc_disable_reason; if (!dap_metadata.vabc_enabled()) { vabc_disable_reason = "not enabled metadata"; } else if (device_->IsRecovery()) { vabc_disable_reason = "recovery"; } else if (!cow_format_support) { vabc_disable_reason = "cow format not supported"; } if (!vabc_disable_reason.empty()) { if (userspace_snapshots) { LOG(INFO) << "Userspace snapshots disabled: " << vabc_disable_reason; } if (legacy_compression) { LOG(INFO) << "Compression disabled: " << vabc_disable_reason; } userspace_snapshots = false; legacy_compression = false; } const bool using_snapuserd = userspace_snapshots || legacy_compression; if (!using_snapuserd) { LOG(INFO) << "Using legacy Virtual A/B (dm-snapshot)"; } std::string compression_algorithm; if (use_compression) { if (using_snapuserd) { compression_algorithm = dap_metadata.vabc_compression_param(); if (compression_algorithm.empty()) { // Older OTAs don't set an explicit compression type, so default to gz. compression_algorithm = "gz"; } } else { compression_algorithm = "none"; } PartitionCowCreator cow_creator{ Loading @@ -3220,7 +3246,7 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife .current_suffix = current_suffix, .update = nullptr, .extra_extents = {}, .compression_enabled = use_compression, .using_snapuserd = using_snapuserd, .compression_algorithm = compression_algorithm, }; Loading @@ -3245,11 +3271,11 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife return Return::Error(); } // If compression is enabled, we need to retain a copy of the old metadata // If snapuserd 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) { if (using_snapuserd) { auto metadata = current_metadata->Export(); if (!metadata) { LOG(ERROR) << "Could not export current metadata"; Loading @@ -3265,70 +3291,36 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife 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()) { bool userSnapshotsEnabled = IsUserspaceSnapshotsEnabled(); const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } // Userspace snapshots is enabled only if compression is enabled status.set_userspace_snapshots(userSnapshotsEnabled); if (userSnapshotsEnabled) { is_snapshot_userspace_ = true; status.set_io_uring_enabled(IsIouringEnabled()); LOG(INFO) << "Userspace snapshots enabled"; status.set_using_snapuserd(using_snapuserd); if (userspace_snapshots) { status.set_userspace_snapshots(true); LOG(INFO) << "Virtual A/B using userspace snapshots"; if (GetIouringEnabledProperty()) { status.set_io_uring_enabled(true); LOG(INFO) << "io_uring for snapshots enabled"; } } else if (legacy_compression) { LOG(INFO) << "Virtual A/B using legacy snapuserd"; } else { is_snapshot_userspace_ = false; LOG(INFO) << "Userspace snapshots disabled"; LOG(INFO) << "Virtual A/B using dm-snapshot"; } is_snapshot_userspace_.emplace(userspace_snapshots); if (!device()->IsTestDevice() && using_snapuserd) { // Terminate stale daemon if any std::unique_ptr<SnapuserdClient> snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s); std::unique_ptr<SnapuserdClient> snapuserd_client = std::move(snapuserd_client_); if (!snapuserd_client) { snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s); } 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 { bool userSnapshotsEnabled = true; const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } userSnapshotsEnabled = (userSnapshotsEnabled && !IsDmSnapshotTestingEnabled()); status.set_userspace_snapshots(userSnapshotsEnabled); if (!userSnapshotsEnabled) { 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(); Loading Loading @@ -3521,7 +3513,7 @@ Return SnapshotManager::InitializeUpdateSnapshots( return Return::Error(); } if (it->second.compression_enabled()) { if (it->second.using_snapuserd()) { unique_fd fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC)); if (fd < 0) { PLOG(ERROR) << "open " << cow_path << " failed for snapshot " Loading Loading @@ -3567,8 +3559,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.using_snapuserd()) { LOG(ERROR) << "Cannot use MapUpdateSnapshot with snapuserd"; return false; } Loading Loading @@ -3625,7 +3617,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( return nullptr; } if (status.compression_enabled()) { if (status.using_snapuserd()) { return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); } Loading Loading @@ -3755,7 +3747,10 @@ bool SnapshotManager::Dump(std::ostream& os) { auto update_status = ReadSnapshotUpdateStatus(file.get()); ss << "Update state: " << ReadUpdateState(file.get()) << std::endl; ss << "Compression: " << update_status.compression_enabled() << std::endl; ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl; ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl; ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl; ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl; ss << "Current slot: " << device_->GetSlotSuffix() << std::endl; ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl; ss << "Rollback indicator: " Loading Loading @@ -3976,7 +3971,7 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) { if (!ReadSnapshotStatus(lock, snapshot, &status)) { return false; } if (status.compression_enabled()) { if (status.using_snapuserd()) { continue; } Loading Loading @@ -4140,7 +4135,7 @@ bool SnapshotManager::IsSnapuserdRequired() { if (!lock) return false; auto status = ReadSnapshotUpdateStatus(lock.get()); return status.state() != UpdateState::None && status.compression_enabled(); return status.state() != UpdateState::None && status.using_snapuserd(); } bool SnapshotManager::DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv) { Loading @@ -4166,7 +4161,7 @@ const LpMetadata* SnapshotManager::ReadOldPartitionMetadata(LockedFile* lock) { } MergePhase SnapshotManager::DecideMergePhase(const SnapshotStatus& status) { if (status.compression_enabled() && status.device_size() < status.old_partition_size()) { if (status.using_snapuserd() && status.device_size() < status.old_partition_size()) { return MergePhase::FIRST_PHASE; } return MergePhase::SECOND_PHASE; Loading Loading @@ -4208,8 +4203,7 @@ void SnapshotManager::SetMergeStatsFeatures(ISnapshotMergeStats* stats) { SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get()); stats->report()->set_iouring_used(update_status.io_uring_enabled()); stats->report()->set_userspace_snapshots_used(update_status.userspace_snapshots()); stats->report()->set_xor_compression_used( android::base::GetBoolProperty("ro.virtual_ab.compression.xor.enabled", false)); stats->report()->set_xor_compression_used(GetXorCompressionEnabledProperty()); } bool SnapshotManager::DeleteDeviceIfExists(const std::string& name, Loading Loading
fs_mgr/libsnapshot/android/snapshot/snapshot.proto +3 −3 Original line number Diff line number Diff line Loading @@ -97,8 +97,8 @@ message SnapshotStatus { // This is non-zero when |state| == MERGING or MERGE_COMPLETED. uint64 metadata_sectors = 8; // True if compression is enabled, false otherwise. bool compression_enabled = 9; // True if using snapuserd, false otherwise. bool using_snapuserd = 9; // The old partition size (if none existed, this will be zero). uint64 old_partition_size = 10; Loading Loading @@ -184,7 +184,7 @@ message SnapshotUpdateStatus { uint64 metadata_sectors = 4; // Whether compression/dm-user was used for any snapshots. bool compression_enabled = 5; bool using_snapuserd = 5; // Merge phase (if state == MERGING). MergePhase merge_phase = 6; Loading
fs_mgr/libsnapshot/partition_cow_creator.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -143,7 +143,7 @@ void WriteExtent(DmSnapCowSizeCalculator* sc, const chromeos_update_engine::Exte } std::optional<uint64_t> PartitionCowCreator::GetCowSize() { if (compression_enabled) { if (using_snapuserd) { if (update == nullptr || !update->has_estimate_cow_size()) { LOG(ERROR) << "Update manifest does not include a COW size"; return std::nullopt; Loading
fs_mgr/libsnapshot/partition_cow_creator.h +2 −2 Original line number Diff line number Diff line Loading @@ -56,8 +56,8 @@ struct PartitionCowCreator { // Extra extents that are going to be invalidated during the update // process. std::vector<ChromeOSExtent> extra_extents = {}; // True if compression is enabled. bool compression_enabled = false; // True if snapuserd COWs are enabled. bool using_snapuserd = false; std::string compression_algorithm; struct Return { Loading
fs_mgr/libsnapshot/partition_cow_creator_test.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -249,7 +249,7 @@ TEST_F(PartitionCowCreatorTest, CompressionEnabled) { .target_partition = system_b, .current_metadata = builder_a.get(), .current_suffix = "_a", .compression_enabled = true, .using_snapuserd = true, .update = &update}; auto ret = creator.Run(); Loading @@ -275,7 +275,7 @@ TEST_F(PartitionCowCreatorTest, CompressionWithNoManifest) { .target_partition = system_b, .current_metadata = builder_a.get(), .current_suffix = "_a", .compression_enabled = true, .using_snapuserd = true, .update = nullptr}; auto ret = creator.Run(); Loading
fs_mgr/libsnapshot/snapshot.cpp +80 −86 Original line number Diff line number Diff line Loading @@ -398,7 +398,7 @@ bool SnapshotManager::CreateSnapshot(LockedFile* lock, PartitionCowCreator* cow_ status->set_state(SnapshotState::CREATED); status->set_sectors_allocated(0); status->set_metadata_sectors(0); status->set_compression_enabled(cow_creator->compression_enabled); status->set_using_snapuserd(cow_creator->using_snapuserd); status->set_compression_algorithm(cow_creator->compression_algorithm); if (!WriteSnapshotStatus(lock, *status)) { Loading Loading @@ -788,7 +788,7 @@ bool SnapshotManager::InitiateMerge() { } } bool compression_enabled = false; bool using_snapuserd = false; std::vector<std::string> first_merge_group; Loading @@ -809,7 +809,7 @@ bool SnapshotManager::InitiateMerge() { return false; } compression_enabled |= snapshot_status.compression_enabled(); using_snapuserd |= snapshot_status.using_snapuserd(); if (DecideMergePhase(snapshot_status) == MergePhase::FIRST_PHASE) { first_merge_group.emplace_back(snapshot); } Loading @@ -817,7 +817,7 @@ bool SnapshotManager::InitiateMerge() { SnapshotUpdateStatus initial_status = ReadSnapshotUpdateStatus(lock.get()); initial_status.set_state(UpdateState::Merging); initial_status.set_compression_enabled(compression_enabled); initial_status.set_using_snapuserd(using_snapuserd); if (!UpdateUsesUserSnapshots(lock.get())) { initial_status.set_sectors_allocated(initial_target_values.sectors_allocated); Loading Loading @@ -1364,7 +1364,7 @@ MergeFailureCode SnapshotManager::CheckMergeConsistency(LockedFile* lock, const } MergeFailureCode CheckMergeConsistency(const std::string& name, const SnapshotStatus& status) { if (!status.compression_enabled()) { if (!status.using_snapuserd()) { // Do not try to verify old-style COWs yet. return MergeFailureCode::Ok; } Loading Loading @@ -1625,7 +1625,7 @@ bool SnapshotManager::CollapseSnapshotDevice(LockedFile* lock, const std::string // as unmap will fail since dm-user itself was a snapshot device prior // to switching of tables. Unmap will fail as the device will be mounted // by system partitions if (status.compression_enabled()) { if (status.using_snapuserd()) { auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock)); UnmapDmUserDevice(dm_user_name); } Loading Loading @@ -2115,8 +2115,10 @@ bool SnapshotManager::UpdateUsesCompression() { } bool SnapshotManager::UpdateUsesCompression(LockedFile* lock) { // This returns true even if compression is "none", since update_engine is // really just trying to see if snapuserd is in use. SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock); return update_status.compression_enabled(); return update_status.using_snapuserd(); } bool SnapshotManager::UpdateUsesIouring(LockedFile* lock) { Loading Loading @@ -2436,13 +2438,13 @@ 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()) { if (context == SnapshotContext::Update && live_snapshot_status->using_snapuserd()) { // 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 (live_snapshot_status->using_snapuserd()) { // 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) { Loading Loading @@ -2944,7 +2946,7 @@ bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state, // build fingerprint. if (!(state == UpdateState::Initiated || state == UpdateState::None)) { SnapshotUpdateStatus old_status = ReadSnapshotUpdateStatus(lock); status.set_compression_enabled(old_status.compression_enabled()); status.set_using_snapuserd(old_status.using_snapuserd()); status.set_source_build_fingerprint(old_status.source_build_fingerprint()); status.set_merge_phase(old_status.merge_phase()); status.set_userspace_snapshots(old_status.userspace_snapshots()); Loading Loading @@ -3198,18 +3200,42 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife LOG(INFO) << " dap_metadata.cow_version(): " << dap_metadata.cow_version() << " writer.GetCowVersion(): " << writer.GetCowVersion(); bool use_compression = IsCompressionEnabled() && dap_metadata.vabc_enabled() && !device_->IsRecovery() && cow_format_support; // Deduce supported features. bool userspace_snapshots = CanUseUserspaceSnapshots(); bool legacy_compression = GetLegacyCompressionEnabledProperty(); std::string vabc_disable_reason; if (!dap_metadata.vabc_enabled()) { vabc_disable_reason = "not enabled metadata"; } else if (device_->IsRecovery()) { vabc_disable_reason = "recovery"; } else if (!cow_format_support) { vabc_disable_reason = "cow format not supported"; } if (!vabc_disable_reason.empty()) { if (userspace_snapshots) { LOG(INFO) << "Userspace snapshots disabled: " << vabc_disable_reason; } if (legacy_compression) { LOG(INFO) << "Compression disabled: " << vabc_disable_reason; } userspace_snapshots = false; legacy_compression = false; } const bool using_snapuserd = userspace_snapshots || legacy_compression; if (!using_snapuserd) { LOG(INFO) << "Using legacy Virtual A/B (dm-snapshot)"; } std::string compression_algorithm; if (use_compression) { if (using_snapuserd) { compression_algorithm = dap_metadata.vabc_compression_param(); if (compression_algorithm.empty()) { // Older OTAs don't set an explicit compression type, so default to gz. compression_algorithm = "gz"; } } else { compression_algorithm = "none"; } PartitionCowCreator cow_creator{ Loading @@ -3220,7 +3246,7 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife .current_suffix = current_suffix, .update = nullptr, .extra_extents = {}, .compression_enabled = use_compression, .using_snapuserd = using_snapuserd, .compression_algorithm = compression_algorithm, }; Loading @@ -3245,11 +3271,11 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife return Return::Error(); } // If compression is enabled, we need to retain a copy of the old metadata // If snapuserd 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) { if (using_snapuserd) { auto metadata = current_metadata->Export(); if (!metadata) { LOG(ERROR) << "Could not export current metadata"; Loading @@ -3265,70 +3291,36 @@ Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manife 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()) { bool userSnapshotsEnabled = IsUserspaceSnapshotsEnabled(); const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } // Userspace snapshots is enabled only if compression is enabled status.set_userspace_snapshots(userSnapshotsEnabled); if (userSnapshotsEnabled) { is_snapshot_userspace_ = true; status.set_io_uring_enabled(IsIouringEnabled()); LOG(INFO) << "Userspace snapshots enabled"; status.set_using_snapuserd(using_snapuserd); if (userspace_snapshots) { status.set_userspace_snapshots(true); LOG(INFO) << "Virtual A/B using userspace snapshots"; if (GetIouringEnabledProperty()) { status.set_io_uring_enabled(true); LOG(INFO) << "io_uring for snapshots enabled"; } } else if (legacy_compression) { LOG(INFO) << "Virtual A/B using legacy snapuserd"; } else { is_snapshot_userspace_ = false; LOG(INFO) << "Userspace snapshots disabled"; LOG(INFO) << "Virtual A/B using dm-snapshot"; } is_snapshot_userspace_.emplace(userspace_snapshots); if (!device()->IsTestDevice() && using_snapuserd) { // Terminate stale daemon if any std::unique_ptr<SnapuserdClient> snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s); std::unique_ptr<SnapuserdClient> snapuserd_client = std::move(snapuserd_client_); if (!snapuserd_client) { snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s); } 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 { bool userSnapshotsEnabled = true; const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } userSnapshotsEnabled = (userSnapshotsEnabled && !IsDmSnapshotTestingEnabled()); status.set_userspace_snapshots(userSnapshotsEnabled); if (!userSnapshotsEnabled) { 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(); Loading Loading @@ -3521,7 +3513,7 @@ Return SnapshotManager::InitializeUpdateSnapshots( return Return::Error(); } if (it->second.compression_enabled()) { if (it->second.using_snapuserd()) { unique_fd fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC)); if (fd < 0) { PLOG(ERROR) << "open " << cow_path << " failed for snapshot " Loading Loading @@ -3567,8 +3559,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.using_snapuserd()) { LOG(ERROR) << "Cannot use MapUpdateSnapshot with snapuserd"; return false; } Loading Loading @@ -3625,7 +3617,7 @@ std::unique_ptr<ISnapshotWriter> SnapshotManager::OpenSnapshotWriter( return nullptr; } if (status.compression_enabled()) { if (status.using_snapuserd()) { return OpenCompressedSnapshotWriter(lock.get(), source_device, params.GetPartitionName(), status, paths); } Loading Loading @@ -3755,7 +3747,10 @@ bool SnapshotManager::Dump(std::ostream& os) { auto update_status = ReadSnapshotUpdateStatus(file.get()); ss << "Update state: " << ReadUpdateState(file.get()) << std::endl; ss << "Compression: " << update_status.compression_enabled() << std::endl; ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl; ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl; ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl; ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl; ss << "Current slot: " << device_->GetSlotSuffix() << std::endl; ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl; ss << "Rollback indicator: " Loading Loading @@ -3976,7 +3971,7 @@ bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) { if (!ReadSnapshotStatus(lock, snapshot, &status)) { return false; } if (status.compression_enabled()) { if (status.using_snapuserd()) { continue; } Loading Loading @@ -4140,7 +4135,7 @@ bool SnapshotManager::IsSnapuserdRequired() { if (!lock) return false; auto status = ReadSnapshotUpdateStatus(lock.get()); return status.state() != UpdateState::None && status.compression_enabled(); return status.state() != UpdateState::None && status.using_snapuserd(); } bool SnapshotManager::DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv) { Loading @@ -4166,7 +4161,7 @@ const LpMetadata* SnapshotManager::ReadOldPartitionMetadata(LockedFile* lock) { } MergePhase SnapshotManager::DecideMergePhase(const SnapshotStatus& status) { if (status.compression_enabled() && status.device_size() < status.old_partition_size()) { if (status.using_snapuserd() && status.device_size() < status.old_partition_size()) { return MergePhase::FIRST_PHASE; } return MergePhase::SECOND_PHASE; Loading Loading @@ -4208,8 +4203,7 @@ void SnapshotManager::SetMergeStatsFeatures(ISnapshotMergeStats* stats) { SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get()); stats->report()->set_iouring_used(update_status.io_uring_enabled()); stats->report()->set_userspace_snapshots_used(update_status.userspace_snapshots()); stats->report()->set_xor_compression_used( android::base::GetBoolProperty("ro.virtual_ab.compression.xor.enabled", false)); stats->report()->set_xor_compression_used(GetXorCompressionEnabledProperty()); } bool SnapshotManager::DeleteDeviceIfExists(const std::string& name, Loading