Merge "ueventd: require opt-in for modalias handling"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c830321..321e6ba 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -127,6 +127,7 @@
"product-services",
true, false },
{ "recovery", "recovery.img", "recovery.sig", "recovery", true, false },
+ { "super", "super.img", "super.sig", "super", true, false },
{ "system", "system.img", "system.sig", "system", false, false },
{ nullptr, "system_other.img", "system.sig", "system", true, true },
{ "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, false },
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index b3df811..5f57182 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1052,6 +1052,9 @@
return FS_MGR_DOMNT_FAILED;
}
+ // Run fsck if needed
+ prepare_fs_for_mount(rec->blk_device, rec);
+
int ret = __mount(rec->blk_device, rec->mount_point, rec);
if (ret) {
ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED;
@@ -1177,8 +1180,8 @@
{
int ret;
- ret = mount("tmpfs", n_name, "tmpfs",
- MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS);
+ ret = mount("tmpfs", n_name, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV | MS_NOEXEC,
+ CRYPTO_TMPFS_OPTIONS);
if (ret < 0) {
LERROR << "Cannot mount tmpfs filesystem at " << n_name;
return -1;
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 9d710f9..eb429b9 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -48,10 +48,20 @@
PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
return false;
}
- if (ioctl(fd, BLKALIGNOFF, &device_info->alignment_offset) < 0) {
+
+ int alignment_offset;
+ if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
return false;
}
+ int logical_block_size;
+ if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
+ return false;
+ }
+
+ device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
+ device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
return true;
#else
(void)block_device;
@@ -82,11 +92,7 @@
extents_.clear();
}
-void Partition::ShrinkTo(uint64_t requested_size) {
- uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE);
- if (size_ <= aligned_size) {
- return;
- }
+void Partition::ShrinkTo(uint64_t aligned_size) {
if (aligned_size == 0) {
RemoveExtents();
return;
@@ -106,7 +112,7 @@
sectors_to_remove -= extent->num_sectors();
extents_.pop_back();
}
- DCHECK(size_ == requested_size);
+ DCHECK(size_ == aligned_size);
}
std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_device,
@@ -182,6 +188,7 @@
device_info_.alignment = geometry_.alignment;
device_info_.alignment_offset = geometry_.alignment_offset;
+ device_info_.logical_block_size = geometry_.logical_block_size;
return true;
}
@@ -205,6 +212,10 @@
LERROR << "Block device size must be a multiple of 512.";
return false;
}
+ if (device_info_.logical_block_size % LP_SECTOR_SIZE != 0) {
+ LERROR << "Logical block size must be a multiple of 512.";
+ return false;
+ }
if (device_info_.alignment_offset % LP_SECTOR_SIZE != 0) {
LERROR << "Alignment offset is not sector-aligned.";
return false;
@@ -248,6 +259,18 @@
return false;
}
+ // Finally, the size of the allocatable space must be a multiple of the
+ // logical block size. If we have no more free space after this
+ // computation, then we abort. Note that the last sector is inclusive,
+ // so we have to account for that.
+ uint64_t num_free_sectors = last_sector - first_sector + 1;
+ uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
+ if (num_free_sectors < sectors_per_block) {
+ LERROR << "Not enough space to allocate any partition tables.";
+ return false;
+ }
+ last_sector = first_sector + (num_free_sectors / sectors_per_block) * sectors_per_block - 1;
+
geometry_.first_logical_sector = first_sector;
geometry_.last_logical_sector = last_sector;
geometry_.metadata_max_size = metadata_max_size;
@@ -255,6 +278,7 @@
geometry_.alignment = device_info_.alignment;
geometry_.alignment_offset = device_info_.alignment_offset;
geometry_.block_device_size = device_info_.size;
+ geometry_.logical_block_size = device_info.logical_block_size;
return true;
}
@@ -290,13 +314,7 @@
}
}
-bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t requested_size) {
- // Align the space needed up to the nearest sector.
- uint64_t aligned_size = AlignTo(requested_size, LP_SECTOR_SIZE);
- if (partition->size() >= aligned_size) {
- return true;
- }
-
+bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
// Figure out how much we need to allocate.
uint64_t space_needed = aligned_size - partition->size();
uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE;
@@ -307,95 +325,101 @@
uint64_t end;
Interval(uint64_t start, uint64_t end) : start(start), end(end) {}
+ uint64_t length() const { return end - start; }
bool operator<(const Interval& other) const { return start < other.start; }
};
- std::vector<Interval> intervals;
- // Collect all extents in the partition table.
+ // Collect all extents in the partition table, then sort them by starting
+ // sector.
+ std::vector<Interval> extents;
for (const auto& partition : partitions_) {
for (const auto& extent : partition->extents()) {
LinearExtent* linear = extent->AsLinearExtent();
if (!linear) {
continue;
}
- intervals.emplace_back(linear->physical_sector(),
- linear->physical_sector() + extent->num_sectors());
+ extents.emplace_back(linear->physical_sector(),
+ linear->physical_sector() + extent->num_sectors());
}
}
+ std::sort(extents.begin(), extents.end());
- // Sort extents by starting sector.
- std::sort(intervals.begin(), intervals.end());
+ // Convert the extent list into a list of gaps between the extents; i.e.,
+ // the list of ranges that are free on the disk.
+ std::vector<Interval> free_regions;
+ for (size_t i = 1; i < extents.size(); i++) {
+ const Interval& previous = extents[i - 1];
+ const Interval& current = extents[i];
+
+ uint64_t aligned = AlignSector(previous.end);
+ if (aligned >= current.start) {
+ // There is no gap between these two extents, try the next one.
+ // Note that we check with >= instead of >, since alignment may
+ // bump the ending sector past the beginning of the next extent.
+ continue;
+ }
+
+ // The new interval represents the free space starting at the end of
+ // the previous interval, and ending at the start of the next interval.
+ free_regions.emplace_back(aligned, current.start);
+ }
+
+ // Add a final interval representing the remainder of the free space.
+ uint64_t last_free_extent_start =
+ extents.empty() ? geometry_.first_logical_sector : extents.back().end;
+ last_free_extent_start = AlignSector(last_free_extent_start);
+ if (last_free_extent_start <= geometry_.last_logical_sector) {
+ free_regions.emplace_back(last_free_extent_start, geometry_.last_logical_sector + 1);
+ }
+
+ const uint64_t sectors_per_block = device_info_.logical_block_size / LP_SECTOR_SIZE;
+ CHECK(sectors_needed % sectors_per_block == 0);
// Find gaps that we can use for new extents. Note we store new extents in a
// temporary vector, and only commit them if we are guaranteed enough free
// space.
std::vector<std::unique_ptr<LinearExtent>> new_extents;
- for (size_t i = 1; i < intervals.size(); i++) {
- const Interval& previous = intervals[i - 1];
- const Interval& current = intervals[i];
+ for (auto& region : free_regions) {
+ if (region.length() % sectors_per_block != 0) {
+ // This should never happen, because it would imply that we
+ // once allocated an extent that was not a multiple of the
+ // block size. That extent would be rejected by DM_TABLE_LOAD.
+ LERROR << "Region " << region.start << ".." << region.end
+ << " is not a multiple of the block size, " << sectors_per_block;
- if (previous.end >= current.start) {
- // There is no gap between these two extents, try the next one. Note that
- // extents may never overlap, but just for safety, we ignore them if they
- // do.
- DCHECK(previous.end == current.start);
- continue;
+ // If for some reason the final region is mis-sized we still want
+ // to be able to grow partitions. So just to be safe, round the
+ // region down to the nearest block.
+ region.end = region.start + (region.length() / sectors_per_block) * sectors_per_block;
+ if (!region.length()) {
+ continue;
+ }
}
- uint64_t aligned = AlignSector(previous.end);
- if (aligned >= current.start) {
- // After alignment, this extent is not usable.
- continue;
- }
+ uint64_t sectors = std::min(sectors_needed, region.length());
+ CHECK(sectors % sectors_per_block == 0);
- // This gap is enough to hold the remainder of the space requested, so we
- // can allocate what we need and return.
- if (current.start - aligned >= sectors_needed) {
- auto extent = std::make_unique<LinearExtent>(sectors_needed, aligned);
- sectors_needed -= extent->num_sectors();
- new_extents.push_back(std::move(extent));
+ auto extent = std::make_unique<LinearExtent>(sectors, region.start);
+ new_extents.push_back(std::move(extent));
+ sectors_needed -= sectors;
+ if (!sectors_needed) {
break;
}
-
- // This gap is not big enough to fit the remainder of the space requested,
- // so consume the whole thing and keep looking for more.
- auto extent = std::make_unique<LinearExtent>(current.start - aligned, aligned);
- sectors_needed -= extent->num_sectors();
- new_extents.push_back(std::move(extent));
}
-
- // If we still have more to allocate, take it from the remaining free space
- // in the allocatable region.
if (sectors_needed) {
- uint64_t first_sector;
- if (intervals.empty()) {
- first_sector = geometry_.first_logical_sector;
- } else {
- first_sector = intervals.back().end;
- }
- DCHECK(first_sector <= geometry_.last_logical_sector);
-
- // Note: After alignment, |first_sector| may be > the last usable sector.
- first_sector = AlignSector(first_sector);
-
- // Note: the last usable sector is inclusive.
- if (first_sector > geometry_.last_logical_sector ||
- geometry_.last_logical_sector + 1 - first_sector < sectors_needed) {
- LERROR << "Not enough free space to expand partition: " << partition->name();
- return false;
- }
- auto extent = std::make_unique<LinearExtent>(sectors_needed, first_sector);
- new_extents.push_back(std::move(extent));
+ LERROR << "Not enough free space to expand partition: " << partition->name();
+ return false;
}
+ // Everything succeeded, so commit the new extents.
for (auto& extent : new_extents) {
partition->AddExtent(std::move(extent));
}
return true;
}
-void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t requested_size) {
- partition->ShrinkTo(requested_size);
+void MetadataBuilder::ShrinkPartition(Partition* partition, uint64_t aligned_size) {
+ partition->ShrinkTo(aligned_size);
}
std::unique_ptr<LpMetadata> MetadataBuilder::Export() {
@@ -455,6 +479,12 @@
void MetadataBuilder::set_block_device_info(const BlockDeviceInfo& device_info) {
device_info_.size = device_info.size;
+ // Note that if the logical block size changes, we're probably in trouble:
+ // we could have already built extents that will only work on the previous
+ // size.
+ DCHECK(partitions_.empty() ||
+ device_info_.logical_block_size == device_info.logical_block_size);
+
// The kernel does not guarantee these values are present, so we only
// replace existing values if the new values are non-zero.
if (device_info.alignment) {
@@ -465,5 +495,18 @@
}
}
+bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
+ // Align the space needed up to the nearest sector.
+ uint64_t aligned_size = AlignTo(requested_size, device_info_.logical_block_size);
+
+ if (aligned_size > partition->size()) {
+ return GrowPartition(partition, aligned_size);
+ }
+ if (aligned_size < partition->size()) {
+ ShrinkPartition(partition, aligned_size);
+ }
+ return true;
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index b610fd4..f1a91c4 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -45,7 +45,7 @@
Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
EXPECT_EQ(system->size(), 65536);
ASSERT_EQ(system->extents().size(), 1);
@@ -55,24 +55,23 @@
// The first logical sector will be (4096+1024*2)/512 = 12.
EXPECT_EQ(extent->physical_sector(), 12);
- // Test growing to the same size.
- EXPECT_EQ(builder->GrowPartition(system, 65536), true);
+ // Test resizing to the same size.
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
EXPECT_EQ(system->size(), 65536);
EXPECT_EQ(system->extents().size(), 1);
EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE);
- // Test growing to a smaller size.
- EXPECT_EQ(builder->GrowPartition(system, 0), true);
- EXPECT_EQ(system->size(), 65536);
+ // Test resizing to a smaller size.
+ EXPECT_EQ(builder->ResizePartition(system, 0), true);
+ EXPECT_EQ(system->size(), 0);
+ EXPECT_EQ(system->extents().size(), 0);
+ // Test resizing to a greater size.
+ builder->ResizePartition(system, 131072);
+ EXPECT_EQ(system->size(), 131072);
EXPECT_EQ(system->extents().size(), 1);
- EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE);
- // Test shrinking to a greater size.
- builder->ShrinkPartition(system, 131072);
- EXPECT_EQ(system->size(), 65536);
- EXPECT_EQ(system->extents().size(), 1);
- EXPECT_EQ(system->extents()[0]->num_sectors(), 65536 / LP_SECTOR_SIZE);
+ EXPECT_EQ(system->extents()[0]->num_sectors(), 131072 / LP_SECTOR_SIZE);
// Test shrinking within the same extent.
- builder->ShrinkPartition(system, 32768);
+ builder->ResizePartition(system, 32768);
EXPECT_EQ(system->size(), 32768);
EXPECT_EQ(system->extents().size(), 1);
extent = system->extents()[0]->AsLinearExtent();
@@ -81,7 +80,7 @@
EXPECT_EQ(extent->physical_sector(), 12);
// Test shrinking to 0.
- builder->ShrinkPartition(system, 0);
+ builder->ResizePartition(system, 0);
EXPECT_EQ(system->size(), 0);
EXPECT_EQ(system->extents().size(), 0);
}
@@ -92,12 +91,12 @@
// Test that we align up to one sector.
Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 10000), true);
- EXPECT_EQ(system->size(), 10240);
+ EXPECT_EQ(builder->ResizePartition(system, 10000), true);
+ EXPECT_EQ(system->size(), 12288);
EXPECT_EQ(system->extents().size(), 1);
- builder->ShrinkPartition(system, 9000);
- EXPECT_EQ(system->size(), 9216);
+ builder->ResizePartition(system, 7000);
+ EXPECT_EQ(system->size(), 8192);
EXPECT_EQ(system->extents().size(), 1);
}
@@ -121,13 +120,13 @@
TEST(liblp, InternalAlignment) {
// Test the metadata fitting within alignment.
- BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0);
+ BlockDeviceInfo device_info(1024 * 1024, 768 * 1024, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 2);
ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 1536);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2035);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
// Test a large alignment offset thrown in.
device_info.alignment_offset = 753664;
@@ -136,7 +135,7 @@
exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 1472);
- EXPECT_EQ(exported->geometry.last_logical_sector, 2035);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 2031);
// Alignment offset without alignment doesn't mean anything.
device_info.alignment = 0;
@@ -151,7 +150,7 @@
exported = builder->Export();
ASSERT_NE(exported, nullptr);
EXPECT_EQ(exported->geometry.first_logical_sector, 78);
- EXPECT_EQ(exported->geometry.last_logical_sector, 1975);
+ EXPECT_EQ(exported->geometry.last_logical_sector, 1973);
// Test a small alignment with no alignment offset.
device_info.alignment = 11 * 1024;
@@ -164,7 +163,7 @@
}
TEST(liblp, InternalPartitionAlignment) {
- BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664);
+ BlockDeviceInfo device_info(512 * 1024 * 1024, 768 * 1024, 753664, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 32 * 1024, 2);
Partition* a = builder->AddPartition("a", TEST_GUID, 0);
@@ -174,8 +173,8 @@
// Add a bunch of small extents to each, interleaving.
for (size_t i = 0; i < 10; i++) {
- ASSERT_TRUE(builder->GrowPartition(a, a->size() + 4096));
- ASSERT_TRUE(builder->GrowPartition(b, b->size() + 4096));
+ ASSERT_TRUE(builder->ResizePartition(a, a->size() + 4096));
+ ASSERT_TRUE(builder->ResizePartition(b, b->size() + 4096));
}
EXPECT_EQ(a->size(), 40960);
EXPECT_EQ(b->size(), 40960);
@@ -203,9 +202,9 @@
Partition* system = builder->AddPartition("system", TEST_GUID, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 1036288), true);
+ EXPECT_EQ(builder->ResizePartition(system, 1036288), true);
EXPECT_EQ(system->size(), 1036288);
- EXPECT_EQ(builder->GrowPartition(system, 1036289), false);
+ EXPECT_EQ(builder->ResizePartition(system, 1036289), false);
}
TEST(liblp, BuildComplex) {
@@ -215,9 +214,9 @@
Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 65536), true);
- EXPECT_EQ(builder->GrowPartition(vendor, 32768), true);
- EXPECT_EQ(builder->GrowPartition(system, 98304), true);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
+ EXPECT_EQ(builder->ResizePartition(system, 98304), true);
EXPECT_EQ(system->size(), 98304);
EXPECT_EQ(vendor->size(), 32768);
@@ -268,9 +267,9 @@
Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 65536), true);
- EXPECT_EQ(builder->GrowPartition(vendor, 32768), true);
- EXPECT_EQ(builder->GrowPartition(system, 98304), true);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
+ EXPECT_EQ(builder->ResizePartition(system, 98304), true);
unique_ptr<LpMetadata> exported = builder->Export();
EXPECT_NE(exported, nullptr);
@@ -323,9 +322,9 @@
Partition* vendor = builder->AddPartition("vendor", TEST_GUID2, LP_PARTITION_ATTR_READONLY);
ASSERT_NE(system, nullptr);
ASSERT_NE(vendor, nullptr);
- EXPECT_EQ(builder->GrowPartition(system, 65536), true);
- EXPECT_EQ(builder->GrowPartition(vendor, 32768), true);
- EXPECT_EQ(builder->GrowPartition(system, 98304), true);
+ EXPECT_EQ(builder->ResizePartition(system, 65536), true);
+ EXPECT_EQ(builder->ResizePartition(vendor, 32768), true);
+ EXPECT_EQ(builder->ResizePartition(system, 98304), true);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
@@ -382,7 +381,7 @@
static const size_t kMetadataSize = 64 * 1024;
// No space to store metadata + geometry.
- BlockDeviceInfo device_info(kDiskSize, 0, 0);
+ BlockDeviceInfo device_info(kDiskSize, 0, 0, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
@@ -391,8 +390,8 @@
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_EQ(builder, nullptr);
- // Space for metadata + geometry + one free sector.
- device_info.size += LP_SECTOR_SIZE;
+ // Space for metadata + geometry + one free block.
+ device_info.size += device_info.logical_block_size;
builder = MetadataBuilder::New(device_info, kMetadataSize, 1);
EXPECT_NE(builder, nullptr);
@@ -425,19 +424,21 @@
ASSERT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
ASSERT_EQ(device_info.alignment_offset % LP_SECTOR_SIZE, 0);
ASSERT_LE(device_info.alignment_offset, INT_MAX);
+ ASSERT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
// Having an alignment offset > alignment doesn't really make sense.
ASSERT_LT(device_info.alignment_offset, device_info.alignment);
}
TEST(liblp, UpdateBlockDeviceInfo) {
- BlockDeviceInfo device_info(1024 * 1024, 4096, 1024);
+ BlockDeviceInfo device_info(1024 * 1024, 4096, 1024, 4096);
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
ASSERT_NE(builder, nullptr);
EXPECT_EQ(builder->block_device_info().size, device_info.size);
EXPECT_EQ(builder->block_device_info().alignment, device_info.alignment);
EXPECT_EQ(builder->block_device_info().alignment_offset, device_info.alignment_offset);
+ EXPECT_EQ(builder->block_device_info().logical_block_size, device_info.logical_block_size);
device_info.alignment = 0;
device_info.alignment_offset = 2048;
@@ -451,3 +452,27 @@
EXPECT_EQ(builder->block_device_info().alignment, 8192);
EXPECT_EQ(builder->block_device_info().alignment_offset, 2048);
}
+
+TEST(liblp, InvalidBlockSize) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 513);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ EXPECT_EQ(builder, nullptr);
+}
+
+TEST(liblp, AlignedExtentSize) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+
+ Partition* partition = builder->AddPartition("system", TEST_GUID, 0);
+ ASSERT_NE(partition, nullptr);
+ ASSERT_TRUE(builder->ResizePartition(partition, 512));
+ EXPECT_EQ(partition->size(), 4096);
+}
+
+TEST(liblp, AlignedFreeSpace) {
+ // Only one sector free - at least one block is required.
+ BlockDeviceInfo device_info(10240, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 512, 1);
+ ASSERT_EQ(builder, nullptr);
+}
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 8bde313..e83b922 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -32,11 +32,16 @@
// By default, partitions are aligned on a 1MiB boundary.
static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
+static const uint32_t kDefaultBlockSize = 4096;
struct BlockDeviceInfo {
- BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0) {}
- BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset)
- : size(size), alignment(alignment), alignment_offset(alignment_offset) {}
+ BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
+ BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
+ uint32_t logical_block_size)
+ : size(size),
+ alignment(alignment),
+ alignment_offset(alignment_offset),
+ logical_block_size(logical_block_size) {}
// Size of the block device, in bytes.
uint64_t size;
// Optimal target alignment, in bytes. Partition extents will be aligned to
@@ -46,6 +51,8 @@
// |alignment_offset| on the target device is correctly aligned on its
// parent device. This value must be 0 or a multiple of 512.
uint32_t alignment_offset;
+ // Block size, for aligning extent sizes and partition sizes.
+ uint32_t logical_block_size;
};
// Abstraction around dm-targets that can be encoded into logical partition tables.
@@ -88,6 +95,8 @@
};
class Partition final {
+ friend class MetadataBuilder;
+
public:
Partition(const std::string& name, const std::string& guid, uint32_t attributes);
@@ -97,10 +106,6 @@
// Remove all extents from this partition.
void RemoveExtents();
- // Remove and/or shrink extents until the partition is the requested size.
- // See MetadataBuilder::ShrinkPartition for more information.
- void ShrinkTo(uint64_t requested_size);
-
const std::string& name() const { return name_; }
uint32_t attributes() const { return attributes_; }
const std::string& guid() const { return guid_; }
@@ -108,6 +113,8 @@
uint64_t size() const { return size_; }
private:
+ void ShrinkTo(uint64_t aligned_size);
+
std::string name_;
std::string guid_;
std::vector<std::unique_ptr<Extent>> extents_;
@@ -144,7 +151,7 @@
// size. This is a convenience method for tests.
static std::unique_ptr<MetadataBuilder> New(uint64_t blockdev_size, uint32_t metadata_max_size,
uint32_t metadata_slot_count) {
- BlockDeviceInfo device_info(blockdev_size, 0, 0);
+ BlockDeviceInfo device_info(blockdev_size, 0, 0, kDefaultBlockSize);
return New(device_info, metadata_max_size, metadata_slot_count);
}
@@ -162,29 +169,17 @@
// Find a partition by name. If no partition is found, nullptr is returned.
Partition* FindPartition(const std::string& name);
- // Grow a partition to the requested size. If the partition's size is already
- // greater or equal to the requested size, this will return true and the
- // partition table will not be changed. Otherwise, a greedy algorithm is
- // used to find free gaps in the partition table and allocate them for this
- // partition. If not enough space can be allocated, false is returned, and
- // the parition table will not be modified.
+ // Grow or shrink a partition to the requested size. This size will be
+ // rounded UP to the nearest block (512 bytes).
//
- // The size will be rounded UP to the nearest sector.
+ // When growing a partition, a greedy algorithm is used to find free gaps
+ // in the partition table and allocate them. If not enough space can be
+ // allocated, false is returned, and the parition table will not be
+ // modified.
//
// Note, this is an in-memory operation, and it does not alter the
// underlying filesystem or contents of the partition on disk.
- bool GrowPartition(Partition* partition, uint64_t requested_size);
-
- // Shrink a partition to the requested size. If the partition is already
- // smaller than the given size, this will return and the partition table
- // will not be changed. Otherwise, extents will be removed and/or shrunk
- // from the end of the partition until it is the requested size.
- //
- // The size will be rounded UP to the nearest sector.
- //
- // Note, this is an in-memory operation, and it does not alter the
- // underlying filesystem or contents of the partition on disk.
- void ShrinkPartition(Partition* partition, uint64_t requested_size);
+ bool ResizePartition(Partition* partition, uint64_t requested_size);
// Amount of space that can be allocated to logical partitions.
uint64_t AllocatableSpace() const;
@@ -198,7 +193,8 @@
MetadataBuilder();
bool Init(const BlockDeviceInfo& info, uint32_t metadata_max_size, uint32_t metadata_slot_count);
bool Init(const LpMetadata& metadata);
-
+ bool GrowPartition(Partition* partition, uint64_t aligned_size);
+ void ShrinkPartition(Partition* partition, uint64_t aligned_size);
uint64_t AlignSector(uint64_t sector);
LpMetadataGeometry geometry_;
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index e1323e1..52c80f7 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -136,6 +136,12 @@
* can be used to verify the geometry against a target device.
*/
uint64_t block_device_size;
+
+ /* 76: Logical block size of the super partition block device. This is the
+ * minimal alignment for partition and extent sizes, and it must be a
+ * multiple of LP_SECTOR_SIZE.
+ */
+ uint32_t logical_block_size;
} __attribute__((packed)) LpMetadataGeometry;
/* The logical partition metadata has a number of tables; they are described
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index bbbedc7..638f4b3 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -85,7 +85,7 @@
if (!system) {
return false;
}
- return builder->GrowPartition(system, 24 * 1024);
+ return builder->ResizePartition(system, 24 * 1024);
}
// Create a temporary disk and flash it with the default partition setup.
@@ -345,7 +345,7 @@
ASSERT_NE(partition, nullptr);
// Add one extent to any partition to fill up more space - we're at 508
// bytes after this, out of 512.
- ASSERT_TRUE(builder->GrowPartition(partition, 1024));
+ ASSERT_TRUE(builder->ResizePartition(partition, 1024));
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 092dbf1..7bf42ae 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -40,7 +40,8 @@
80000,
0,
0,
- 1024 * 1024};
+ 1024 * 1024,
+ 4096};
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), 4096);
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 1), 4096 + 16384);
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 2), 4096 + 16384 * 2);
diff --git a/init/init.cpp b/init/init.cpp
index 73194bd..7ad9ec3 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -670,6 +670,10 @@
CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
+ // This is needed for log wrapper, which gets called before ueventd runs.
+ CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
+ CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
+
// Mount staging areas for devices managed by vold
// See storage config details at http://source.android.com/devices/storage/
CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 94f206e..b788be9 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -414,6 +414,8 @@
if constexpr (WORLD_WRITABLE_KMSG) {
selinux_android_restorecon("/dev/kmsg_debug", 0);
}
+ selinux_android_restorecon("/dev/null", 0);
+ selinux_android_restorecon("/dev/ptmx", 0);
selinux_android_restorecon("/dev/socket", 0);
selinux_android_restorecon("/dev/random", 0);
selinux_android_restorecon("/dev/urandom", 0);
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index bb1ce34..1b7c377 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -108,6 +108,13 @@
android_log_list_element android_log_read_next(android_log_context ctx);
android_log_list_element android_log_peek_next(android_log_context ctx);
+/* Reset writer context */
+int android_log_reset(android_log_context ctx);
+
+/* Reset reader context */
+int android_log_parser_reset(android_log_context ctx,
+ const char* msg, size_t len);
+
/* Finished with reader or writer context */
int android_log_destroy(android_log_context* ctx);
diff --git a/liblog/include_vndk/log/log_event_list.h b/liblog/include_vndk/log/log_event_list.h
index cbd3091..9f74534 100644
--- a/liblog/include_vndk/log/log_event_list.h
+++ b/liblog/include_vndk/log/log_event_list.h
@@ -63,6 +63,13 @@
/* NB: LOG_ID_EVENTS and LOG_ID_SECURITY only valid binary buffers */
int android_log_write_list(android_log_context ctx, log_id_t id);
+/* Reset writer context */
+int android_log_reset(android_log_context ctx);
+
+/* Reset reader context */
+int android_log_parser_reset(android_log_context ctx,
+ const char* msg, size_t len);
+
/* Finished with reader or writer context */
int android_log_destroy(android_log_context* ctx);
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 66670fe..015c9cb 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -53,3 +53,9 @@
__android_log_is_loggable_len;
__android_log_is_debuggable; # vndk
};
+
+LIBLOG_Q {
+ global:
+ android_log_reset; #vndk
+ android_log_parser_reset; #vndk
+};
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index a59cb87..14002ce 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -45,14 +45,9 @@
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
} android_log_context_internal;
-LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
- size_t needed, i;
- android_log_context_internal* context;
+static void init_context(android_log_context_internal* context, uint32_t tag) {
+ size_t needed;
- context = calloc(1, sizeof(android_log_context_internal));
- if (!context) {
- return NULL;
- }
context->tag = tag;
context->read_write_flag = kAndroidLoggerWrite;
needed = sizeof(uint8_t) + sizeof(uint8_t);
@@ -63,6 +58,24 @@
context->storage[context->pos + 0] = EVENT_TYPE_LIST;
context->list[0] = context->pos + 1;
context->pos += needed;
+}
+
+static void init_parser_context(android_log_context_internal* context,
+ const char* msg, size_t len) {
+ len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
+ context->len = len;
+ memcpy(context->storage, msg, len);
+ context->read_write_flag = kAndroidLoggerRead;
+}
+
+LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
+ android_log_context_internal* context;
+
+ context = calloc(1, sizeof(android_log_context_internal));
+ if (!context) {
+ return NULL;
+ }
+ init_context(context, tag);
return (android_log_context)context;
}
@@ -76,10 +89,7 @@
if (!context) {
return NULL;
}
- len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
- context->len = len;
- memcpy(context->storage, msg, len);
- context->read_write_flag = kAndroidLoggerRead;
+ init_parser_context(context, msg, len);
return (android_log_context)context;
}
@@ -97,6 +107,38 @@
return 0;
}
+LIBLOG_ABI_PUBLIC int android_log_reset(android_log_context ctx) {
+ android_log_context_internal* context;
+ uint32_t tag;
+
+ context = (android_log_context_internal*)ctx;
+ if (!context || (kAndroidLoggerWrite != context->read_write_flag)) {
+ return -EBADF;
+ }
+
+ tag = context->tag;
+ memset(context, 0, sizeof(*context));
+ init_context(context, tag);
+
+ return 0;
+}
+
+LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx,
+ const char* msg, size_t len) {
+ android_log_context_internal* context;
+
+ context = (android_log_context_internal*)ctx;
+ if (!context || (kAndroidLoggerRead != context->read_write_flag)) {
+ return -EBADF;
+ }
+
+ memset(context, 0, sizeof(*context));
+ init_parser_context(context, msg, len);
+
+ return 0;
+}
+
+
LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
size_t needed;
android_log_context_internal* context;
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 0586381..3d7521c 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -27,6 +27,7 @@
phony {
name: "shell_and_utilities_recovery",
required: [
+ "grep.recovery",
"sh.recovery",
"toolbox.recovery",
"toybox.recovery",
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index e75e4af..f08cf93 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -62,8 +62,8 @@
}
// We build BSD grep separately (but see http://b/111849261).
-cc_binary {
- name: "grep",
+cc_defaults {
+ name: "grep_common",
defaults: ["toolbox_defaults"],
srcs: [
"upstream-netbsd/usr.bin/grep/fastgrep.c",
@@ -72,8 +72,27 @@
"upstream-netbsd/usr.bin/grep/queue.c",
"upstream-netbsd/usr.bin/grep/util.c",
],
-
+ symlinks: [
+ "egrep",
+ "fgrep",
+ ],
sanitize: {
integer_overflow: false,
},
}
+
+cc_binary {
+ name: "grep",
+ defaults: ["grep_common"],
+ recovery_available: true,
+}
+
+// Build vendor grep.
+// TODO: Add vendor_available to "grep" module and remove "grep_vendor" module
+// when vendor_available is fully supported.
+cc_binary {
+ name: "grep_vendor",
+ stem: "grep",
+ vendor: true,
+ defaults: ["grep_common"],
+}