Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3cbe388e authored by David Anderson's avatar David Anderson Committed by Automerger Merge Worker
Browse files

Merge "libsnapshot: Clarify the meaning of "compression.enabled"." am:...

Merge "libsnapshot: Clarify the meaning of "compression.enabled"." am: ef46fe4e am: f0049583 am: b429efaa

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



Change-Id: I5bf4f86bb314d083000436cd548b819396bbc7a0
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents fefc425f b429efaa
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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 {
+2 −2
Original line number Diff line number Diff line
@@ -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();
@@ -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();
+80 −86
Original line number Diff line number Diff line
@@ -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)) {
@@ -788,7 +788,7 @@ bool SnapshotManager::InitiateMerge() {
        }
    }

    bool compression_enabled = false;
    bool using_snapuserd = false;

    std::vector<std::string> first_merge_group;

@@ -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);
        }
@@ -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);
@@ -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;
    }
@@ -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);
        }
@@ -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) {
@@ -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) {
@@ -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());
@@ -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{
@@ -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,
    };

@@ -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";
@@ -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();
@@ -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 "
@@ -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;
    }

@@ -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);
    }
@@ -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: "
@@ -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;
        }

@@ -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) {
@@ -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;
@@ -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