Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8d2a179 authored by David Anderson's avatar David Anderson Committed by android-build-merger
Browse files

Merge "init: Make sure /dev/block/by-name/userdata is created in snapshot mode."

am: 0e70ce26

Change-Id: I737eecbc9b3ee76652f097d3b003c2c8708809fd
parents 98af6698 0e70ce26
Loading
Loading
Loading
Loading
+60 −63
Original line number Diff line number Diff line
@@ -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<std::string>* required_devices);
    bool InitRequiredDevices(std::set<std::string> 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<std::string>* devices);
    bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
    void UseGsiIfPresent();

    ListenerAction UeventCallback(const Uevent& uevent);
    ListenerAction UeventCallback(const Uevent& uevent, std::set<std::string>* required_devices);

    // Pure virtual functions.
    virtual bool GetDmVerityDevices() = 0;
    virtual bool GetDmVerityDevices(std::set<std::string>* 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<std::string> required_devices_partition_names_;
    std::string super_partition_name_;
    std::unique_ptr<DeviceHandler> device_handler_;
    UeventListener uevent_listener_;
@@ -116,7 +116,7 @@ class FirstStageMountVBootV1 : public FirstStageMount {
    ~FirstStageMountVBootV1() override = default;

  protected:
    bool GetDmVerityDevices() override;
    bool GetDmVerityDevices(std::set<std::string>* 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<std::string>* 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<std::string> 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<std::string>* 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<std::string> 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<std::string> 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<std::string>* 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<std::string> 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<std::string>* 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<std::string>* 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<std::string>* devices) {
    need_dm_verity_ = false;

    std::set<std::string> 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;