Merge "Add function to compare the partitions' extents in metadata" am: d7b4fe95c7
Original change: https://android-review.googlesource.com/c/platform/system/core/+/1352612 Change-Id: I7faf667612073b69a6afc1ab0b7fa8a1304b1e0a
This commit is contained in:
commit
14bc7fb7e4
3 changed files with 145 additions and 16 deletions
|
|
@ -31,6 +31,22 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace fs_mgr {
|
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 {
|
bool LinearExtent::AddTo(LpMetadata* out) const {
|
||||||
if (device_index_ >= out->block_devices.size()) {
|
if (device_index_ >= out->block_devices.size()) {
|
||||||
LERROR << "Extent references unknown block device.";
|
LERROR << "Extent references unknown block device.";
|
||||||
|
|
@ -41,6 +57,17 @@ bool LinearExtent::AddTo(LpMetadata* out) const {
|
||||||
return true;
|
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 {
|
bool LinearExtent::OverlapsWith(const LinearExtent& other) const {
|
||||||
if (device_index_ != other.device_index()) {
|
if (device_index_ != other.device_index()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -64,6 +91,10 @@ bool ZeroExtent::AddTo(LpMetadata* out) const {
|
||||||
return true;
|
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)
|
Partition::Partition(std::string_view name, std::string_view group_name, uint32_t attributes)
|
||||||
: name_(name), group_name_(group_name), attributes_(attributes), size_(0) {}
|
: 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();
|
return partitions_.back().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Partition* MetadataBuilder::FindPartition(std::string_view name) {
|
Partition* MetadataBuilder::FindPartition(std::string_view name) const {
|
||||||
for (const auto& partition : partitions_) {
|
for (const auto& partition : partitions_) {
|
||||||
if (partition->name() == name) {
|
if (partition->name() == name) {
|
||||||
return partition.get();
|
return partition.get();
|
||||||
|
|
@ -527,7 +558,7 @@ Partition* MetadataBuilder::FindPartition(std::string_view name) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) {
|
PartitionGroup* MetadataBuilder::FindGroup(std::string_view group_name) const {
|
||||||
for (const auto& group : groups_) {
|
for (const auto& group : groups_) {
|
||||||
if (group->name() == group_name) {
|
if (group->name() == group_name) {
|
||||||
return group.get();
|
return group.get();
|
||||||
|
|
@ -1270,5 +1301,50 @@ uint64_t MetadataBuilder::logical_block_size() const {
|
||||||
return geometry_.logical_block_size;
|
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 fs_mgr
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
||||||
|
|
@ -947,9 +947,10 @@ static Interval ToInterval(const std::unique_ptr<Extent>& extent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddPartition(const std::unique_ptr<MetadataBuilder>& builder,
|
static void AddPartition(const std::unique_ptr<MetadataBuilder>& builder,
|
||||||
const std::string& partition_name, uint64_t num_sectors,
|
const std::string& partition_name, const std::string& group_name,
|
||||||
uint64_t start_sector, std::vector<Interval>* intervals) {
|
uint64_t num_sectors, uint64_t start_sector,
|
||||||
Partition* p = builder->AddPartition(partition_name, "group", 0);
|
std::vector<Interval>* intervals = nullptr) {
|
||||||
|
Partition* p = builder->AddPartition(partition_name, group_name, 0);
|
||||||
ASSERT_NE(p, nullptr);
|
ASSERT_NE(p, nullptr);
|
||||||
ASSERT_TRUE(builder->AddLinearExtent(p, "super", num_sectors, start_sector));
|
ASSERT_TRUE(builder->AddLinearExtent(p, "super", num_sectors, start_sector));
|
||||||
ASSERT_EQ(p->extents().size(), 1);
|
ASSERT_EQ(p->extents().size(), 1);
|
||||||
|
|
@ -977,17 +978,17 @@ TEST_F(BuilderTest, CollidedExtents) {
|
||||||
ASSERT_TRUE(builder->AddGroup("group", 0));
|
ASSERT_TRUE(builder->AddGroup("group", 0));
|
||||||
|
|
||||||
std::vector<Interval> old_intervals;
|
std::vector<Interval> old_intervals;
|
||||||
AddPartition(builder, "system", 10229008, 2048, &old_intervals);
|
AddPartition(builder, "system", "group", 10229008, 2048, &old_intervals);
|
||||||
AddPartition(builder, "test_a", 648, 12709888, &old_intervals);
|
AddPartition(builder, "test_a", "group", 648, 12709888, &old_intervals);
|
||||||
AddPartition(builder, "test_b", 625184, 12711936, &old_intervals);
|
AddPartition(builder, "test_b", "group", 625184, 12711936, &old_intervals);
|
||||||
AddPartition(builder, "test_c", 130912, 13338624, &old_intervals);
|
AddPartition(builder, "test_c", "group", 130912, 13338624, &old_intervals);
|
||||||
AddPartition(builder, "test_d", 888, 13469696, &old_intervals);
|
AddPartition(builder, "test_d", "group", 888, 13469696, &old_intervals);
|
||||||
AddPartition(builder, "test_e", 888, 13471744, &old_intervals);
|
AddPartition(builder, "test_e", "group", 888, 13471744, &old_intervals);
|
||||||
AddPartition(builder, "test_f", 888, 13475840, &old_intervals);
|
AddPartition(builder, "test_f", "group", 888, 13475840, &old_intervals);
|
||||||
AddPartition(builder, "test_g", 888, 13477888, &old_intervals);
|
AddPartition(builder, "test_g", "group", 888, 13477888, &old_intervals);
|
||||||
|
|
||||||
// Don't track the first vendor interval, since it will get extended.
|
// 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;
|
std::vector<Interval> new_intervals;
|
||||||
|
|
||||||
|
|
@ -1066,3 +1067,30 @@ TEST_F(BuilderTest, ResizeOverflow) {
|
||||||
ASSERT_NE(p, nullptr);
|
ASSERT_NE(p, nullptr);
|
||||||
ASSERT_FALSE(builder->ResizePartition(p, 18446744073709551615ULL));
|
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"}));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,11 @@ static constexpr uint32_t kDefaultBlockSize = 4096;
|
||||||
// Name of the default group in a metadata.
|
// Name of the default group in a metadata.
|
||||||
static constexpr std::string_view kDefaultGroup = "default";
|
static constexpr std::string_view kDefaultGroup = "default";
|
||||||
|
|
||||||
|
enum class ExtentType {
|
||||||
|
kZero,
|
||||||
|
kLinear,
|
||||||
|
};
|
||||||
|
|
||||||
// Abstraction around dm-targets that can be encoded into logical partition tables.
|
// Abstraction around dm-targets that can be encoded into logical partition tables.
|
||||||
class Extent {
|
class Extent {
|
||||||
public:
|
public:
|
||||||
|
|
@ -50,6 +55,10 @@ class Extent {
|
||||||
|
|
||||||
virtual bool AddTo(LpMetadata* out) const = 0;
|
virtual bool AddTo(LpMetadata* out) const = 0;
|
||||||
virtual LinearExtent* AsLinearExtent() { return nullptr; }
|
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_; }
|
uint64_t num_sectors() const { return num_sectors_; }
|
||||||
void set_num_sectors(uint64_t num_sectors) { num_sectors_ = num_sectors; }
|
void set_num_sectors(uint64_t num_sectors) { num_sectors_ = num_sectors; }
|
||||||
|
|
@ -58,6 +67,8 @@ class Extent {
|
||||||
uint64_t num_sectors_;
|
uint64_t num_sectors_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const Extent& extent);
|
||||||
|
|
||||||
// This corresponds to a dm-linear target.
|
// This corresponds to a dm-linear target.
|
||||||
class LinearExtent final : public Extent {
|
class LinearExtent final : public Extent {
|
||||||
public:
|
public:
|
||||||
|
|
@ -66,6 +77,9 @@ class LinearExtent final : public Extent {
|
||||||
|
|
||||||
bool AddTo(LpMetadata* metadata) const override;
|
bool AddTo(LpMetadata* metadata) const override;
|
||||||
LinearExtent* AsLinearExtent() override { return this; }
|
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 physical_sector() const { return physical_sector_; }
|
||||||
uint64_t end_sector() const { return physical_sector_ + num_sectors_; }
|
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) {}
|
explicit ZeroExtent(uint64_t num_sectors) : Extent(num_sectors) {}
|
||||||
|
|
||||||
bool AddTo(LpMetadata* out) const override;
|
bool AddTo(LpMetadata* out) const override;
|
||||||
|
ExtentType GetExtentType() const override { return ExtentType::kZero; }
|
||||||
|
|
||||||
|
bool operator==(const Extent& other) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PartitionGroup final {
|
class PartitionGroup final {
|
||||||
|
|
@ -243,6 +260,14 @@ class MetadataBuilder {
|
||||||
return New(device_info, metadata_max_size, metadata_slot_count);
|
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
|
// Define a new partition group. By default there is one group called
|
||||||
// "default", with an unrestricted size. A non-zero size will restrict the
|
// "default", with an unrestricted size. A non-zero size will restrict the
|
||||||
// total space used by all partitions in the group.
|
// total space used by all partitions in the group.
|
||||||
|
|
@ -267,10 +292,10 @@ class MetadataBuilder {
|
||||||
void RemovePartition(std::string_view name);
|
void RemovePartition(std::string_view name);
|
||||||
|
|
||||||
// Find a partition by name. If no partition is found, nullptr is returned.
|
// 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.
|
// 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.
|
// Add a predetermined extent to a partition.
|
||||||
bool AddLinearExtent(Partition* partition, const std::string& block_device,
|
bool AddLinearExtent(Partition* partition, const std::string& block_device,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue