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

Commit 14bc7fb7 authored by Tianjie Xu's avatar Tianjie Xu Committed by Automerger Merge Worker
Browse files

Merge "Add function to compare the partitions' extents in metadata" am: d7b4fe95

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

Change-Id: I7faf667612073b69a6afc1ab0b7fa8a1304b1e0a
parents e7ab54ab d7b4fe95
Loading
Loading
Loading
Loading
+78 −2
Original line number Diff line number Diff line
@@ -31,6 +31,22 @@
namespace android {
namespace fs_mgr {

std::ostream& operator<<(std::ostream& os, const Extent& extent) {
    switch (extent.GetExtentType()) {
        case ExtentType::kZero: {
            os << "type: Zero";
            break;
        }
        case ExtentType::kLinear: {
            auto linear_extent = static_cast<const LinearExtent*>(&extent);
            os << "type: Linear, physical sectors: " << linear_extent->physical_sector()
               << ", end sectors: " << linear_extent->end_sector();
            break;
        }
    }
    return os;
}

bool LinearExtent::AddTo(LpMetadata* out) const {
    if (device_index_ >= out->block_devices.size()) {
        LERROR << "Extent references unknown block device.";
@@ -41,6 +57,17 @@ bool LinearExtent::AddTo(LpMetadata* out) const {
    return true;
}

bool LinearExtent::operator==(const android::fs_mgr::Extent& other) const {
    if (other.GetExtentType() != ExtentType::kLinear) {
        return false;
    }

    auto other_ptr = static_cast<const LinearExtent*>(&other);
    return num_sectors_ == other_ptr->num_sectors_ &&
           physical_sector_ == other_ptr->physical_sector_ &&
           device_index_ == other_ptr->device_index_;
}

bool LinearExtent::OverlapsWith(const LinearExtent& other) const {
    if (device_index_ != other.device_index()) {
        return false;
@@ -64,6 +91,10 @@ bool ZeroExtent::AddTo(LpMetadata* out) const {
    return true;
}

bool ZeroExtent::operator==(const android::fs_mgr::Extent& other) const {
    return other.GetExtentType() == ExtentType::kZero && num_sectors_ == other.num_sectors();
}

Partition::Partition(std::string_view name, std::string_view group_name, uint32_t attributes)
    : name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}

@@ -518,7 +549,7 @@ Partition* MetadataBuilder::AddPartition(std::string_view name, std::string_view
    return partitions_.back().get();
}

Partition* MetadataBuilder::FindPartition(std::string_view name) {
Partition* MetadataBuilder::FindPartition(std::string_view name) const {
    for (const auto& partition : partitions_) {
        if (partition->name() == name) {
            return partition.get();
@@ -527,7 +558,7 @@ Partition* MetadataBuilder::FindPartition(std::string_view name) {
    return nullptr;
}

PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) {
PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) const {
    for (const auto& group : groups_) {
        if (group->name() == group_name) {
            return group.get();
@@ -1270,5 +1301,50 @@ uint64_t MetadataBuilder::logical_block_size() const {
    return geometry_.logical_block_size;
}

bool MetadataBuilder::VerifyExtentsAgainstSourceMetadata(
        const MetadataBuilder& source_metadata, uint32_t source_slot_number,
        const MetadataBuilder& target_metadata, uint32_t target_slot_number,
        const std::vector<std::string>& partitions) {
    for (const auto& base_name : partitions) {
        // Find the partition in metadata with the slot suffix.
        auto target_partition_name = base_name + SlotSuffixForSlotNumber(target_slot_number);
        const auto target_partition = target_metadata.FindPartition(target_partition_name);
        if (!target_partition) {
            LERROR << "Failed to find partition " << target_partition_name << " in metadata slot "
                   << target_slot_number;
            return false;
        }

        auto source_partition_name = base_name + SlotSuffixForSlotNumber(source_slot_number);
        const auto source_partition = source_metadata.FindPartition(source_partition_name);
        if (!source_partition) {
            LERROR << "Failed to find partition " << source_partition << " in metadata slot "
                   << source_slot_number;
            return false;
        }

        // We expect the partitions in the target metadata to have the identical extents as the
        // one in the source metadata. Because they are copied in NewForUpdate.
        if (target_partition->extents().size() != source_partition->extents().size()) {
            LERROR << "Extents count mismatch for partition " << base_name << " target slot has "
                   << target_partition->extents().size() << ", source slot has "
                   << source_partition->extents().size();
            return false;
        }

        for (size_t i = 0; i < target_partition->extents().size(); i++) {
            const auto& src_extent = *source_partition->extents()[i];
            const auto& tgt_extent = *target_partition->extents()[i];
            if (tgt_extent != src_extent) {
                LERROR << "Extents " << i << " is different for partition " << base_name;
                LERROR << "tgt extent " << tgt_extent << "; src extent " << src_extent;
                return false;
            }
        }
    }

    return true;
}

}  // namespace fs_mgr
}  // namespace android
+40 −12
Original line number Diff line number Diff line
@@ -947,9 +947,10 @@ static Interval ToInterval(const std::unique_ptr<Extent>& extent) {
}

static void AddPartition(const std::unique_ptr<MetadataBuilder>& builder,
                         const std::string& partition_name, uint64_t num_sectors,
                         uint64_t start_sector, std::vector<Interval>* intervals) {
    Partition* p = builder->AddPartition(partition_name, "group", 0);
                         const std::string& partition_name, const std::string& group_name,
                         uint64_t num_sectors, uint64_t start_sector,
                         std::vector<Interval>* intervals = nullptr) {
    Partition* p = builder->AddPartition(partition_name, group_name, 0);
    ASSERT_NE(p, nullptr);
    ASSERT_TRUE(builder->AddLinearExtent(p, "super", num_sectors, start_sector));
    ASSERT_EQ(p->extents().size(), 1);
@@ -977,17 +978,17 @@ TEST_F(BuilderTest, CollidedExtents) {
    ASSERT_TRUE(builder->AddGroup("group", 0));

    std::vector<Interval> old_intervals;
    AddPartition(builder, "system", 10229008, 2048, &old_intervals);
    AddPartition(builder, "test_a", 648, 12709888, &old_intervals);
    AddPartition(builder, "test_b", 625184, 12711936, &old_intervals);
    AddPartition(builder, "test_c", 130912, 13338624, &old_intervals);
    AddPartition(builder, "test_d", 888, 13469696, &old_intervals);
    AddPartition(builder, "test_e", 888, 13471744, &old_intervals);
    AddPartition(builder, "test_f", 888, 13475840, &old_intervals);
    AddPartition(builder, "test_g", 888, 13477888, &old_intervals);
    AddPartition(builder, "system", "group", 10229008, 2048, &old_intervals);
    AddPartition(builder, "test_a", "group", 648, 12709888, &old_intervals);
    AddPartition(builder, "test_b", "group", 625184, 12711936, &old_intervals);
    AddPartition(builder, "test_c", "group", 130912, 13338624, &old_intervals);
    AddPartition(builder, "test_d", "group", 888, 13469696, &old_intervals);
    AddPartition(builder, "test_e", "group", 888, 13471744, &old_intervals);
    AddPartition(builder, "test_f", "group", 888, 13475840, &old_intervals);
    AddPartition(builder, "test_g", "group", 888, 13477888, &old_intervals);

    // Don't track the first vendor interval, since it will get extended.
    AddPartition(builder, "vendor", 2477920, 10231808, nullptr);
    AddPartition(builder, "vendor", "group", 2477920, 10231808, nullptr);

    std::vector<Interval> new_intervals;

@@ -1066,3 +1067,30 @@ TEST_F(BuilderTest, ResizeOverflow) {
    ASSERT_NE(p, nullptr);
    ASSERT_FALSE(builder->ResizePartition(p, 18446744073709551615ULL));
}

TEST_F(BuilderTest, VerifyExtent) {
    auto source_builder = MetadataBuilder::New(4096 * 50, 40960, 2);
    ASSERT_NE(source_builder, nullptr);
    ASSERT_TRUE(source_builder->AddGroup("test_group_a", 40960));
    ASSERT_TRUE(source_builder->AddGroup("test_group_b", 40960));
    AddPartition(source_builder, "system_a", "test_group_a", 8192, 2048);
    AddPartition(source_builder, "vendor_a", "test_group_a", 10240, 10240);
    AddPartition(source_builder, "system_b", "test_group_b", 8192, 20480);

    auto target_builder = MetadataBuilder::New(4096 * 50, 40960, 2);
    ASSERT_NE(target_builder, nullptr);
    ASSERT_TRUE(target_builder->AddGroup("test_group_b", 40960));
    AddPartition(target_builder, "system_b", "test_group_b", 8192, 2048);
    AddPartition(target_builder, "vendor_b", "test_group_b", 10240, 10240);

    ASSERT_TRUE(MetadataBuilder::VerifyExtentsAgainstSourceMetadata(
            *source_builder, 0, *target_builder, 1, std::vector<std::string>{"system", "vendor"}));

    target_builder->RemovePartition("vendor_b");
    ASSERT_FALSE(target_builder->VerifyExtentsAgainstSourceMetadata(
            *source_builder, 0, *target_builder, 1, std::vector<std::string>{"vendor"}));

    AddPartition(target_builder, "vendor_b", "test_group_b", 1000, 10240);
    ASSERT_FALSE(target_builder->VerifyExtentsAgainstSourceMetadata(
            *source_builder, 0, *target_builder, 1, std::vector<std::string>{"vendor"}));
}
+27 −2
Original line number Diff line number Diff line
@@ -42,6 +42,11 @@ static constexpr uint32_t kDefaultBlockSize = 4096;
// Name of the default group in a metadata.
static constexpr std::string_view kDefaultGroup = "default";

enum class ExtentType {
    kZero,
    kLinear,
};

// Abstraction around dm-targets that can be encoded into logical partition tables.
class Extent {
  public:
@@ -50,6 +55,10 @@ class Extent {

    virtual bool AddTo(LpMetadata* out) const = 0;
    virtual LinearExtent* AsLinearExtent() { return nullptr; }
    virtual ExtentType GetExtentType() const = 0;

    virtual bool operator==(const Extent& other) const = 0;
    virtual bool operator!=(const Extent& other) const { return !(*this == other); }

    uint64_t num_sectors() const { return num_sectors_; }
    void set_num_sectors(uint64_t num_sectors) { num_sectors_ = num_sectors; }
@@ -58,6 +67,8 @@ class Extent {
    uint64_t num_sectors_;
};

std::ostream& operator<<(std::ostream& os, const Extent& extent);

// This corresponds to a dm-linear target.
class LinearExtent final : public Extent {
  public:
@@ -66,6 +77,9 @@ class LinearExtent final : public Extent {

    bool AddTo(LpMetadata* metadata) const override;
    LinearExtent* AsLinearExtent() override { return this; }
    ExtentType GetExtentType() const override { return ExtentType::kLinear; }

    bool operator==(const Extent& other) const override;

    uint64_t physical_sector() const { return physical_sector_; }
    uint64_t end_sector() const { return physical_sector_ + num_sectors_; }
@@ -87,6 +101,9 @@ class ZeroExtent final : public Extent {
    explicit ZeroExtent(uint64_t num_sectors) : Extent(num_sectors) {}

    bool AddTo(LpMetadata* out) const override;
    ExtentType GetExtentType() const override { return ExtentType::kZero; }

    bool operator==(const Extent& other) const override;
};

class PartitionGroup final {
@@ -243,6 +260,14 @@ class MetadataBuilder {
        return New(device_info, metadata_max_size, metadata_slot_count);
    }

    // Verifies that the given partitions in the metadata have the same extents as the source
    // metadata.
    static bool VerifyExtentsAgainstSourceMetadata(const MetadataBuilder& source_metadata,
                                                   uint32_t source_slot_number,
                                                   const MetadataBuilder& target_metadata,
                                                   uint32_t target_slot_number,
                                                   const std::vector<std::string>& partitions);

    // Define a new partition group. By default there is one group called
    // "default", with an unrestricted size. A non-zero size will restrict the
    // total space used by all partitions in the group.
@@ -267,10 +292,10 @@ class MetadataBuilder {
    void RemovePartition(std::string_view name);

    // Find a partition by name. If no partition is found, nullptr is returned.
    Partition* FindPartition(std::string_view name);
    Partition* FindPartition(std::string_view name) const;

    // Find a group by name. If no group is found, nullptr is returned.
    PartitionGroup* FindGroup(std::string_view name);
    PartitionGroup* FindGroup(std::string_view name) const;

    // Add a predetermined extent to a partition.
    bool AddLinearExtent(Partition* partition, const std::string& block_device,