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

Commit dccd6b33 authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge "libsnapshot: Refactor CreateLogicalAndSnapshotPartitions"

parents d6c426c0 31fda7e4
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -329,6 +329,10 @@ class SnapshotManager final {
    std::string GetSnapshotDeviceName(const std::string& snapshot_name,
    std::string GetSnapshotDeviceName(const std::string& snapshot_name,
                                      const SnapshotStatus& status);
                                      const SnapshotStatus& status);


    // Map the base device, COW devices, and snapshot device.
    bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params,
                                  std::string* path);

    std::string gsid_dir_;
    std::string gsid_dir_;
    std::string metadata_dir_;
    std::string metadata_dir_;
    std::unique_ptr<IDeviceInfo> device_;
    std::unique_ptr<IDeviceInfo> device_;
+82 −54
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/types.h>
#include <sys/unistd.h>
#include <sys/unistd.h>


#include <optional>
#include <thread>
#include <thread>
#include <unordered_set>
#include <unordered_set>


@@ -1127,22 +1128,6 @@ bool SnapshotManager::CreateLogicalAndSnapshotPartitions(const std::string& supe
    auto lock = LockExclusive();
    auto lock = LockExclusive();
    if (!lock) return false;
    if (!lock) return false;


    std::vector<std::string> snapshot_list;
    if (!ListSnapshots(lock.get(), &snapshot_list)) {
        return false;
    }

    std::unordered_set<std::string> live_snapshots;
    for (const auto& snapshot : snapshot_list) {
        SnapshotStatus status;
        if (!ReadSnapshotStatus(lock.get(), snapshot, &status)) {
            return false;
        }
        if (status.state != SnapshotState::MergeCompleted) {
            live_snapshots.emplace(snapshot);
        }
    }

    const auto& opener = device_->GetPartitionOpener();
    const auto& opener = device_->GetPartitionOpener();
    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
    uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
    auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
    auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
@@ -1151,45 +1136,86 @@ bool SnapshotManager::CreateLogicalAndSnapshotPartitions(const std::string& supe
        return false;
        return false;
    }
    }


    // Map logical partitions.
    auto& dm = DeviceMapper::Instance();
    for (const auto& partition : metadata->partitions) {
    for (const auto& partition : metadata->partitions) {
        auto partition_name = GetPartitionName(partition);
        if (!partition.num_extents) {
            LOG(INFO) << "Skipping zero-length logical partition: " << partition_name;
            continue;
        }

        if (!(partition.attributes & LP_PARTITION_ATTR_UPDATED)) {
            LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
                      << partition_name;
            live_snapshots.erase(partition_name);
        }

        CreateLogicalPartitionParams params = {
        CreateLogicalPartitionParams params = {
                .block_device = super_device,
                .block_device = super_device,
                .metadata = metadata.get(),
                .metadata = metadata.get(),
                .partition = &partition,
                .partition = &partition,
                .partition_opener = &opener,
                .partition_opener = &opener,
        };
        };
        std::string ignore_path;
        if (!MapPartitionWithSnapshot(lock.get(), std::move(params), &ignore_path)) {
            return false;
        }
    }


        if (auto iter = live_snapshots.find(partition_name); iter != live_snapshots.end()) {
    LOG(INFO) << "Created logical partitions with snapshot.";
            // If the device has a snapshot, it'll need to be writable, and
    return true;
            // we'll need to create the logical partition with a marked-up name
}
            // (since the snapshot will use the partition name).

bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
                                               CreateLogicalPartitionParams params,
                                               std::string* path) {
    CHECK(lock);
    path->clear();

    // Fill out fields in CreateLogicalPartitionParams so that we have more information (e.g. by
    // reading super partition metadata).
    CreateLogicalPartitionParams::OwnedData params_owned_data;
    if (!params.InitDefaults(&params_owned_data)) {
        return false;
    }

    if (!params.partition->num_extents) {
        LOG(INFO) << "Skipping zero-length logical partition: " << params.GetPartitionName();
        return true;  // leave path empty to indicate that nothing is mapped.
    }

    // Determine if there is a live snapshot for the SnapshotStatus of the partition; i.e. if the
    // partition still has a snapshot that needs to be mapped.  If no live snapshot or merge
    // completed, live_snapshot_status is set to nullopt.
    std::optional<SnapshotStatus> live_snapshot_status;
    do {
        if (!(params.partition->attributes & LP_PARTITION_ATTR_UPDATED)) {
            LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
                      << params.GetPartitionName();
            break;
        }
        auto file_path = GetSnapshotStatusFilePath(params.GetPartitionName());
        if (access(file_path.c_str(), F_OK) != 0) {
            if (errno != ENOENT) {
                PLOG(INFO) << "Can't map snapshot for " << params.GetPartitionName()
                           << ": Can't access " << file_path;
                return false;
            }
            break;
        }
        live_snapshot_status = std::make_optional<SnapshotStatus>();
        if (!ReadSnapshotStatus(lock, params.GetPartitionName(), &*live_snapshot_status)) {
            return false;
        }
        // No live snapshot if merge is completed.
        if (live_snapshot_status->state == SnapshotState::MergeCompleted) {
            live_snapshot_status.reset();
        }
    } while (0);

    if (live_snapshot_status.has_value()) {
        // dm-snapshot requires the base device to be writable.
        params.force_writable = true;
        params.force_writable = true;
            params.device_name = GetBaseDeviceName(partition_name);
        // Map the base device with a different name to avoid collision.
        params.device_name = GetBaseDeviceName(params.GetPartitionName());
    }
    }


    auto& dm = DeviceMapper::Instance();
    std::string ignore_path;
    std::string ignore_path;
    if (!CreateLogicalPartition(params, &ignore_path)) {
    if (!CreateLogicalPartition(params, &ignore_path)) {
            LOG(ERROR) << "Could not create logical partition " << partition_name << " as device "
        LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName()
                       << params.GetDeviceName();
                   << " as device " << params.GetDeviceName();
        return false;
        return false;
    }
    }
        if (!params.force_writable) {
    if (!live_snapshot_status.has_value()) {
            // No snapshot.
        return true;
            continue;
    }
    }


    // We don't have ueventd in first-stage init, so use device major:minor
    // We don't have ueventd in first-stage init, so use device major:minor
@@ -1199,11 +1225,13 @@ bool SnapshotManager::CreateLogicalAndSnapshotPartitions(const std::string& supe
        LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
        LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
        return false;
        return false;
    }
    }
        if (!MapSnapshot(lock.get(), partition_name, base_device, {}, &ignore_path)) {
    if (!MapSnapshot(lock, params.GetPartitionName(), base_device, {}, path)) {
            LOG(ERROR) << "Could not map snapshot for partition: " << partition_name;
        LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
        return false;
        return false;
    }
    }
    }

    LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << *path;

    return true;
    return true;
}
}