diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index 6b4216fe4..4a1bc5a1a 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -77,8 +77,9 @@ class FirstStageMount { bool InitDevices(); protected: - ListenerAction HandleBlockDevice(const std::string& name, const Uevent&); - bool InitRequiredDevices(); + ListenerAction HandleBlockDevice(const std::string& name, const Uevent&, + std::set* required_devices); + bool InitRequiredDevices(std::set devices); bool InitMappedDevice(const std::string& verity_device); bool InitDeviceMapper(); bool CreateLogicalPartitions(); @@ -89,14 +90,14 @@ class FirstStageMount { bool TrySwitchSystemAsRoot(); bool TrySkipMountingPartitions(); bool IsDmLinearEnabled(); - bool GetDmLinearMetadataDevice(); + void GetDmLinearMetadataDevice(std::set* devices); bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata); void UseGsiIfPresent(); - ListenerAction UeventCallback(const Uevent& uevent); + ListenerAction UeventCallback(const Uevent& uevent, std::set* required_devices); // Pure virtual functions. - virtual bool GetDmVerityDevices() = 0; + virtual bool GetDmVerityDevices(std::set* devices) = 0; virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0; bool need_dm_verity_; @@ -104,7 +105,6 @@ class FirstStageMount { Fstab fstab_; std::string lp_metadata_partition_; - std::set required_devices_partition_names_; std::string super_partition_name_; std::unique_ptr device_handler_; UeventListener uevent_listener_; @@ -116,7 +116,7 @@ class FirstStageMountVBootV1 : public FirstStageMount { ~FirstStageMountVBootV1() override = default; protected: - bool GetDmVerityDevices() override; + bool GetDmVerityDevices(std::set* devices) override; bool SetUpDmVerity(FstabEntry* fstab_entry) override; }; @@ -128,7 +128,7 @@ class FirstStageMountVBootV2 : public FirstStageMount { ~FirstStageMountVBootV2() override = default; protected: - bool GetDmVerityDevices() override; + bool GetDmVerityDevices(std::set* devices) override; bool SetUpDmVerity(FstabEntry* fstab_entry) override; bool InitAvbHandle(); @@ -252,7 +252,13 @@ bool FirstStageMount::DoFirstStageMount() { } bool FirstStageMount::InitDevices() { - return GetDmLinearMetadataDevice() && GetDmVerityDevices() && InitRequiredDevices(); + std::set devices; + GetDmLinearMetadataDevice(&devices); + + if (!GetDmVerityDevices(&devices)) { + return false; + } + return InitRequiredDevices(std::move(devices)); } bool FirstStageMount::IsDmLinearEnabled() { @@ -262,45 +268,46 @@ bool FirstStageMount::IsDmLinearEnabled() { return false; } -bool FirstStageMount::GetDmLinearMetadataDevice() { +void FirstStageMount::GetDmLinearMetadataDevice(std::set* devices) { // Add any additional devices required for dm-linear mappings. if (!IsDmLinearEnabled()) { - return true; + return; } - required_devices_partition_names_.emplace(super_partition_name_); - return true; + devices->emplace(super_partition_name_); } -// Creates devices with uevent->partition_name matching one in the member variable -// required_devices_partition_names_. Found partitions will then be removed from it -// for the subsequent member function to check which devices are NOT created. -bool FirstStageMount::InitRequiredDevices() { +// Creates devices with uevent->partition_name matching ones in the given set. +// Found partitions will then be removed from it for the subsequent member +// function to check which devices are NOT created. +bool FirstStageMount::InitRequiredDevices(std::set devices) { if (!InitDeviceMapper()) { return false; } - if (required_devices_partition_names_.empty()) { + if (devices.empty()) { return true; } - auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); }; + auto uevent_callback = [&, this](const Uevent& uevent) { + return UeventCallback(uevent, &devices); + }; uevent_listener_.RegenerateUevents(uevent_callback); - // UeventCallback() will remove found partitions from required_devices_partition_names_. - // So if it isn't empty here, it means some partitions are not found. - if (!required_devices_partition_names_.empty()) { + // UeventCallback() will remove found partitions from |devices|. So if it + // isn't empty here, it means some partitions are not found. + if (!devices.empty()) { LOG(INFO) << __PRETTY_FUNCTION__ << ": partition(s) not found in /sys, waiting for their uevent(s): " - << android::base::Join(required_devices_partition_names_, ", "); + << android::base::Join(devices, ", "); Timer t; uevent_listener_.Poll(uevent_callback, 10s); LOG(INFO) << "Wait for partitions returned after " << t; } - if (!required_devices_partition_names_.empty()) { + if (!devices.empty()) { LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: " - << android::base::Join(required_devices_partition_names_, ", "); + << android::base::Join(devices, ", "); return false; } @@ -333,27 +340,20 @@ bool FirstStageMount::InitDeviceMapper() { } bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) { + std::set devices; + auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata); for (const auto& partition_name : partition_names) { // The super partition was found in the earlier pass. if (partition_name == super_partition_name_) { continue; } - required_devices_partition_names_.emplace(partition_name); + devices.emplace(partition_name); } - if (required_devices_partition_names_.empty()) { + if (devices.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; + return InitRequiredDevices(std::move(devices)); } bool FirstStageMount::CreateLogicalPartitions() { @@ -372,6 +372,11 @@ bool FirstStageMount::CreateLogicalPartitions() { return false; } if (sm->NeedSnapshotsInFirstStageMount()) { + // When COW images are present for snapshots, they are stored on + // the data partition. + if (!InitRequiredDevices({"userdata"})) { + return false; + } return sm->CreateLogicalAndSnapshotPartitions(lp_metadata_partition_); } } @@ -387,20 +392,21 @@ bool FirstStageMount::CreateLogicalPartitions() { return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), lp_metadata_partition_); } -ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent) { +ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const Uevent& uevent, + std::set* required_devices) { // Matches partition name to create device nodes. // Both required_devices_partition_names_ and uevent->partition_name have A/B // suffix when A/B is used. - auto iter = required_devices_partition_names_.find(name); - if (iter != required_devices_partition_names_.end()) { + auto iter = required_devices->find(name); + if (iter != required_devices->end()) { LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter; if (IsDmLinearEnabled() && name == super_partition_name_) { std::vector links = device_handler_->GetBlockDeviceSymlinks(uevent); lp_metadata_partition_ = links[0]; } - required_devices_partition_names_.erase(iter); + required_devices->erase(iter); device_handler_->HandleUevent(uevent); - if (required_devices_partition_names_.empty()) { + if (required_devices->empty()) { return ListenerAction::kStop; } else { return ListenerAction::kContinue; @@ -409,18 +415,19 @@ ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const return ListenerAction::kContinue; } -ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) { +ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent, + std::set* required_devices) { // Ignores everything that is not a block device. if (uevent.subsystem != "block") { return ListenerAction::kContinue; } if (!uevent.partition_name.empty()) { - return HandleBlockDevice(uevent.partition_name, uevent); + return HandleBlockDevice(uevent.partition_name, uevent, required_devices); } else { size_t base_idx = uevent.path.rfind('/'); if (base_idx != std::string::npos) { - return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent); + return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent, required_devices); } } // Not found a partition or find an unneeded partition, continue to find others. @@ -577,17 +584,7 @@ bool FirstStageMount::MountPartitions() { const auto devices = fs_mgr_overlayfs_required_devices(&fstab_); for (auto const& device : devices) { if (android::base::StartsWith(device, "/dev/block/by-name/")) { - required_devices_partition_names_.emplace(basename(device.c_str())); - auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); }; - uevent_listener_.RegenerateUevents(uevent_callback); - if (!required_devices_partition_names_.empty()) { - uevent_listener_.Poll(uevent_callback, 10s); - if (!required_devices_partition_names_.empty()) { - LOG(ERROR) << __PRETTY_FUNCTION__ - << ": partition(s) not found after polling timeout: " - << android::base::Join(required_devices_partition_names_, ", "); - } - } + InitRequiredDevices({basename(device.c_str())}); } else { InitMappedDevice(device); } @@ -641,7 +638,7 @@ void FirstStageMount::UseGsiIfPresent() { gsi_not_on_userdata_ = (super_name != "userdata"); } -bool FirstStageMountVBootV1::GetDmVerityDevices() { +bool FirstStageMountVBootV1::GetDmVerityDevices(std::set* devices) { need_dm_verity_ = false; for (const auto& fstab_entry : fstab_) { @@ -660,7 +657,7 @@ bool FirstStageMountVBootV1::GetDmVerityDevices() { // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used. for (const auto& fstab_entry : fstab_) { if (!fstab_entry.fs_mgr_flags.logical) { - required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str())); + devices->emplace(basename(fstab_entry.blk_device.c_str())); } } @@ -711,7 +708,7 @@ FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab) } } -bool FirstStageMountVBootV2::GetDmVerityDevices() { +bool FirstStageMountVBootV2::GetDmVerityDevices(std::set* devices) { need_dm_verity_ = false; std::set logical_partitions; @@ -725,7 +722,7 @@ bool FirstStageMountVBootV2::GetDmVerityDevices() { // Don't try to find logical partitions via uevent regeneration. logical_partitions.emplace(basename(fstab_entry.blk_device.c_str())); } else { - required_devices_partition_names_.emplace(basename(fstab_entry.blk_device.c_str())); + devices->emplace(basename(fstab_entry.blk_device.c_str())); } } @@ -742,11 +739,11 @@ bool FirstStageMountVBootV2::GetDmVerityDevices() { if (logical_partitions.count(partition_name)) { continue; } - // required_devices_partition_names_ is of type std::set so it's not an issue - // to emplace a partition twice. e.g., /vendor might be in both places: + // devices is of type std::set so it's not an issue to emplace a + // partition twice. e.g., /vendor might be in both places: // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor" // - mount_fstab_recs_: /vendor_a - required_devices_partition_names_.emplace(partition_name); + devices->emplace(partition_name); } } return true;