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) {