Handle renamed "super" device correctly
In the non-retrofit case, the metadata source partition will be
hardcoded as "super", but such a partition may not exist or may have
been overridden by super_partition=<something>. Make this work reliably
by plumbing the resolved metadata block device through, and using it any
time a partition called "super" is requested.
This also fixes a case in the first_stage_mount code that assumed that
detected a non-A/B, non-retrofit case by assuming the metadata source
partition would be called "super".
Bug: 113175337
Test: boot test on cuttlefish
Change-Id: I8ce1defb902e257eeb7170d697b378eba31faee3
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index fe0e039..3f075ef 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -51,12 +51,20 @@
using DmTargetZero = android::dm::DmTargetZero;
using DmTargetLinear = android::dm::DmTargetLinear;
-bool GetPhysicalPartitionDevicePath(const LpMetadataBlockDevice& block_device,
- std::string* result) {
+static bool GetPhysicalPartitionDevicePath(const LpMetadata& metadata,
+ const LpMetadataBlockDevice& block_device,
+ const std::string& super_device,
+ std::string* result) {
// Note: device-mapper will not accept symlinks, so we must use realpath
// here.
std::string name = GetBlockDevicePartitionName(block_device);
std::string path = "/dev/block/by-name/" + name;
+ // If the super device is the source of this block device's metadata,
+ // make sure we use the correct super device (and not just "super",
+ // which might not exist.)
+ if (GetMetadataSuperBlockDevice(metadata) == &block_device) {
+ path = super_device;
+ }
if (!android::base::Realpath(path, result)) {
PERROR << "realpath: " << path;
return false;
@@ -65,7 +73,7 @@
}
static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition,
- DmTable* table) {
+ const std::string& super_device, DmTable* table) {
uint64_t sector = 0;
for (size_t i = 0; i < partition.num_extents; i++) {
const auto& extent = metadata.extents[partition.first_extent_index + i];
@@ -77,7 +85,7 @@
case LP_TARGET_TYPE_LINEAR: {
const auto& block_device = metadata.block_devices[extent.target_source];
std::string path;
- if (!GetPhysicalPartitionDevicePath(block_device, &path)) {
+ if (!GetPhysicalPartitionDevicePath(metadata, block_device, super_device, &path)) {
LOG(ERROR) << "Unable to complete device-mapper table, unknown block device";
return false;
}
@@ -102,11 +110,11 @@
static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition,
bool force_writable, const std::chrono::milliseconds& timeout_ms,
- std::string* path) {
+ const std::string& super_device, std::string* path) {
DeviceMapper& dm = DeviceMapper::Instance();
DmTable table;
- if (!CreateDmTable(metadata, partition, &table)) {
+ if (!CreateDmTable(metadata, partition, super_device, &table)) {
return false;
}
if (force_writable) {
@@ -137,7 +145,7 @@
LOG(ERROR) << "Could not read partition table.";
return true;
}
- return CreateLogicalPartitions(*metadata.get());
+ return CreateLogicalPartitions(*metadata.get(), block_device);
}
std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device) {
@@ -145,14 +153,14 @@
return ReadMetadata(block_device.c_str(), slot);
}
-bool CreateLogicalPartitions(const LpMetadata& metadata) {
+bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& super_device) {
for (const auto& partition : metadata.partitions) {
if (!partition.num_extents) {
LINFO << "Skipping zero-length logical partition: " << GetPartitionName(partition);
continue;
}
std::string path;
- if (!CreateLogicalPartition(metadata, partition, false, {}, &path)) {
+ if (!CreateLogicalPartition(metadata, partition, false, {}, super_device, &path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}
@@ -171,7 +179,7 @@
for (const auto& partition : metadata->partitions) {
if (GetPartitionName(partition) == partition_name) {
return CreateLogicalPartition(*metadata.get(), partition, force_writable, timeout_ms,
- path);
+ block_device, path);
}
}
LERROR << "Could not find any partition with name: " << partition_name;
diff --git a/fs_mgr/include/fs_mgr_dm_linear.h b/fs_mgr/include/fs_mgr_dm_linear.h
index 66abfca..f065071 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -43,7 +43,7 @@
// Create block devices for all logical partitions in the given metadata. The
// metadata must have been read from the current slot.
-bool CreateLogicalPartitions(const LpMetadata& metadata);
+bool CreateLogicalPartitions(const LpMetadata& metadata, const std::string& block_device);
// Create block devices for all logical partitions. This is a convenience
// method for ReadMetadata and CreateLogicalPartitions.
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 8644dae..0db26bc 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -252,9 +252,10 @@
}
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
- auto partition_names = GetBlockDevicePartitionNames(metadata);
+ auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
for (const auto& partition_name : partition_names) {
- if (partition_name == lp_metadata_partition_) {
+ const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata);
+ if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) {
continue;
}
required_devices_partition_names_.emplace(partition_name);
@@ -292,7 +293,7 @@
if (!InitDmLinearBackingDevices(*metadata.get())) {
return false;
}
- return android::fs_mgr::CreateLogicalPartitions(*metadata.get());
+ return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), lp_metadata_partition_);
}
ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent) {