init: Regenerate uevents for dependent super partition devices.

This patch adds another uevent-regeneration pass to the first stage
mount. When the super partition spans multiple block devices, we need
/dev/block/by-name symlinks to have been created before we begin mapping
dynamic partitions.

Bug: 116802789
Test: retrofit device boots
Change-Id: I00bb277e1d81385a457c5b4205a95d8fbe365bb2
This commit is contained in:
David Anderson 2018-11-05 17:30:16 -08:00
parent e0c3a8d97b
commit f89b1df1a5
5 changed files with 70 additions and 9 deletions

View file

@ -137,13 +137,22 @@ bool CreateLogicalPartitions(const std::string& block_device) {
LOG(ERROR) << "Could not read partition table.";
return true;
}
for (const auto& partition : metadata->partitions) {
return CreateLogicalPartitions(*metadata.get());
}
std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device) {
uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
return ReadMetadata(block_device.c_str(), slot);
}
bool CreateLogicalPartitions(const LpMetadata& metadata) {
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.get(), partition, false, {}, &path)) {
if (!CreateLogicalPartition(metadata, partition, false, {}, &path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}

View file

@ -33,11 +33,20 @@
#include <vector>
#include <libdm/dm.h>
#include <liblp/metadata_format.h>
#include <liblp/liblp.h>
namespace android {
namespace fs_mgr {
// Read metadata from the current slot.
std::unique_ptr<LpMetadata> ReadCurrentMetadata(const std::string& block_device);
// 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);
// Create block devices for all logical partitions. This is a convenience
// method for ReadMetadata and CreateLogicalPartitions.
bool CreateLogicalPartitions(const std::string& block_device);
// Create a block device for a single logical partition, given metadata and

View file

@ -90,6 +90,9 @@ const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metad
// Return the total size of all partitions comprising the super partition.
uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata);
// Get the list of block device names required by the given metadata.
std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata);
// Helper to return a slot number for a slot suffix.
uint32_t SlotNumberForSlotSuffix(const std::string& suffix);

View file

@ -116,5 +116,13 @@ uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata) {
return size;
}
std::vector<std::string> GetBlockDevicePartitionNames(const LpMetadata& metadata) {
std::vector<std::string> list;
for (const auto& block_device : metadata.block_devices) {
list.emplace_back(GetBlockDevicePartitionName(block_device));
}
return list;
}
} // namespace fs_mgr
} // namespace android

View file

@ -33,7 +33,7 @@
#include <fs_mgr_avb.h>
#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
#include <liblp/metadata_format.h>
#include <liblp/liblp.h>
#include "devices.h"
#include "switch_root.h"
@ -69,7 +69,8 @@ class FirstStageMount {
bool MountPartition(fstab_rec* fstab_rec);
bool MountPartitions();
bool IsDmLinearEnabled();
bool GetBackingDmLinearDevices();
bool GetDmLinearMetadataDevice();
bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
virtual ListenerAction UeventCallback(const Uevent& uevent);
@ -183,7 +184,7 @@ bool FirstStageMount::DoFirstStageMount() {
}
bool FirstStageMount::InitDevices() {
return GetBackingDmLinearDevices() && GetDmVerityDevices() && InitRequiredDevices();
return GetDmLinearMetadataDevice() && GetDmVerityDevices() && InitRequiredDevices();
}
bool FirstStageMount::IsDmLinearEnabled() {
@ -193,7 +194,7 @@ bool FirstStageMount::IsDmLinearEnabled() {
return false;
}
bool FirstStageMount::GetBackingDmLinearDevices() {
bool FirstStageMount::GetDmLinearMetadataDevice() {
// Add any additional devices required for dm-linear mappings.
if (!IsDmLinearEnabled()) {
return true;
@ -258,17 +259,48 @@ bool FirstStageMount::InitRequiredDevices() {
return true;
}
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
auto partition_names = GetBlockDevicePartitionNames(metadata);
for (const auto& partition_name : partition_names) {
if (partition_name == lp_metadata_partition_) {
continue;
}
required_devices_partition_names_.emplace(partition_name);
}
if (required_devices_partition_names_.empty()) {
return true;
}
auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
uevent_listener_.RegenerateUevents(uevent_callback);
if (!required_devices_partition_names_.empty()) {
LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: "
<< android::base::Join(required_devices_partition_names_, ", ");
return false;
}
return true;
}
bool FirstStageMount::CreateLogicalPartitions() {
if (!IsDmLinearEnabled()) {
return true;
}
if (lp_metadata_partition_.empty()) {
LOG(ERROR) << "Could not locate logical partition tables in partition "
<< super_partition_name_;
return false;
}
return android::fs_mgr::CreateLogicalPartitions(lp_metadata_partition_);
auto metadata = android::fs_mgr::ReadCurrentMetadata(lp_metadata_partition_);
if (!metadata) {
LOG(ERROR) << "Could not read logical partition metadata from " << lp_metadata_partition_;
return false;
}
if (!InitDmLinearBackingDevices(*metadata.get())) {
return false;
}
return android::fs_mgr::CreateLogicalPartitions(*metadata.get());
}
ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent) {