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

Commit 88a094ab 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:...

Merge "Add function to compare the partitions' extents in metadata" am: d7b4fe95 am: 14bc7fb7 am: 7e1411ac am: 2b00e7aa am: de4ea080

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

Change-Id: I5a8bf67371bad8ad73694218f3a3609ee5047439
parents 7460620a de4ea080
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,