diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index d4964669a..2f516fa9b 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp @@ -40,6 +40,20 @@ bool LinearExtent::AddTo(LpMetadata* out) const { return true; } +bool LinearExtent::OverlapsWith(const LinearExtent& other) const { + if (device_index_ != other.device_index()) { + return false; + } + return physical_sector() < other.end_sector() && other.physical_sector() < end_sector(); +} + +bool LinearExtent::OverlapsWith(const Interval& interval) const { + if (device_index_ != interval.device_index) { + return false; + } + return physical_sector() < interval.end && interval.start < end_sector(); +} + Interval LinearExtent::AsInterval() const { return Interval(device_index(), physical_sector(), end_sector()); } @@ -774,8 +788,7 @@ std::unique_ptr MetadataBuilder::ExtendFinalExtent( bool MetadataBuilder::IsAnyRegionCovered(const std::vector& regions, const LinearExtent& candidate) const { for (const auto& region : regions) { - if (region.device_index == candidate.device_index() && - (candidate.OwnsSector(region.start) || candidate.OwnsSector(region.end))) { + if (candidate.OverlapsWith(region)) { return true; } } @@ -786,11 +799,10 @@ bool MetadataBuilder::IsAnyRegionAllocated(const LinearExtent& candidate) const for (const auto& partition : partitions_) { for (const auto& extent : partition->extents()) { LinearExtent* linear = extent->AsLinearExtent(); - if (!linear || linear->device_index() != candidate.device_index()) { + if (!linear) { continue; } - if (linear->OwnsSector(candidate.physical_sector()) || - linear->OwnsSector(candidate.end_sector() - 1)) { + if (linear->OverlapsWith(candidate)) { return true; } } diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp index ca8df61fd..977ebe3c0 100644 --- a/fs_mgr/liblp/builder_test.cpp +++ b/fs_mgr/liblp/builder_test.cpp @@ -937,3 +937,85 @@ TEST_F(BuilderTest, ExpandedHeader) { EXPECT_EQ(exported->header.header_size, sizeof(LpMetadataHeaderV1_2)); EXPECT_EQ(exported->header.flags, 0x5e5e5e5e); } + +static Interval ToInterval(const std::unique_ptr& extent) { + if (LinearExtent* le = extent->AsLinearExtent()) { + return le->AsInterval(); + } + return {0, 0, 0}; +} + +static void AddPartition(const std::unique_ptr& builder, + const std::string& partition_name, uint64_t num_sectors, + uint64_t start_sector, std::vector* intervals) { + Partition* p = builder->AddPartition(partition_name, "group", 0); + ASSERT_NE(p, nullptr); + ASSERT_TRUE(builder->AddLinearExtent(p, "super", num_sectors, start_sector)); + ASSERT_EQ(p->extents().size(), 1); + + if (!intervals) { + return; + } + + auto new_interval = ToInterval(p->extents().back()); + std::vector new_intervals = {new_interval}; + + auto overlap = Interval::Intersect(*intervals, new_intervals); + ASSERT_TRUE(overlap.empty()); + + intervals->push_back(new_interval); +} + +TEST_F(BuilderTest, CollidedExtents) { + BlockDeviceInfo super("super", 8_GiB, 786432, 229376, 4096); + std::vector block_devices = {super}; + + unique_ptr builder = MetadataBuilder::New(block_devices, "super", 65536, 2); + ASSERT_NE(builder, nullptr); + + ASSERT_TRUE(builder->AddGroup("group", 0)); + + std::vector 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); + + // Don't track the first vendor interval, since it will get extended. + AddPartition(builder, "vendor", 2477920, 10231808, nullptr); + + std::vector new_intervals; + + Partition* p = builder->FindPartition("vendor"); + ASSERT_NE(p, nullptr); + ASSERT_TRUE(builder->ResizePartition(p, 1282031616)); + ASSERT_GE(p->extents().size(), 1); + for (const auto& extent : p->extents()) { + new_intervals.push_back(ToInterval(extent)); + } + + std::vector overlap = Interval::Intersect(old_intervals, new_intervals); + ASSERT_TRUE(overlap.empty()); +} + +TEST_F(BuilderTest, LinearExtentOverlap) { + LinearExtent extent(20, 0, 10); + + EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 10})); + EXPECT_TRUE(extent.OverlapsWith(LinearExtent{50, 0, 10})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 0, 30})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{10, 0, 0})); + EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 0})); + EXPECT_TRUE(extent.OverlapsWith(LinearExtent{40, 0, 0})); + EXPECT_TRUE(extent.OverlapsWith(LinearExtent{20, 0, 15})); + + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 0})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{50, 1, 10})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{40, 1, 0})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 15})); + EXPECT_FALSE(extent.OverlapsWith(LinearExtent{20, 1, 10})); +} diff --git a/fs_mgr/liblp/device_test.cpp b/fs_mgr/liblp/device_test.cpp index 382d53d52..99bff6e03 100644 --- a/fs_mgr/liblp/device_test.cpp +++ b/fs_mgr/liblp/device_test.cpp @@ -56,6 +56,10 @@ TEST_F(DeviceTest, BlockDeviceInfo) { // Having an alignment offset > alignment doesn't really make sense. EXPECT_LT(device_info.alignment_offset, device_info.alignment); + + if (IPropertyFetcher::GetInstance()->GetBoolProperty("ro.virtual_ab.enabled", false)) { + EXPECT_EQ(device_info.alignment_offset, 0); + } } TEST_F(DeviceTest, ReadSuperPartitionCurrentSlot) { diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h index f7738fb88..bd3915061 100644 --- a/fs_mgr/liblp/include/liblp/builder.h +++ b/fs_mgr/liblp/include/liblp/builder.h @@ -71,9 +71,8 @@ class LinearExtent final : public Extent { uint64_t end_sector() const { return physical_sector_ + num_sectors_; } uint32_t device_index() const { return device_index_; } - bool OwnsSector(uint64_t sector) const { - return sector >= physical_sector_ && sector < end_sector(); - } + bool OverlapsWith(const LinearExtent& other) const; + bool OverlapsWith(const Interval& interval) const; Interval AsInterval() const;