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

Commit d6fccea0 authored by Tom Cherry's avatar Tom Cherry
Browse files

Revert "init: poll in first stage mount if required devices are not found"

Bug: 62864413

This reverts commit ccf0d393.

Change-Id: I343e304db4c0e7af2402397ef468cc743a3f08a9
parent ccf0d393
Loading
Loading
Loading
Loading
+47 −73
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <unistd.h>

#include <chrono>
#include <memory>
#include <set>
#include <string>
@@ -36,8 +35,6 @@
#include "uevent_listener.h"
#include "util.h"

using namespace std::chrono_literals;

// Class Declarations
// ------------------
class FirstStageMount {
@@ -52,11 +49,11 @@ class FirstStageMount {
    bool InitDevices();

  protected:
    bool InitRequiredDevices();
    bool InitVerityDevice(const std::string& verity_device);
    void InitRequiredDevices();
    void InitVerityDevice(const std::string& verity_device);
    bool MountPartitions();

    virtual ListenerAction UeventCallback(const Uevent& uevent);
    virtual RegenerationAction UeventCallback(const Uevent& uevent);

    // Pure virtual functions.
    virtual bool GetRequiredDevices() = 0;
@@ -89,7 +86,7 @@ class FirstStageMountVBootV2 : public FirstStageMount {
    ~FirstStageMountVBootV2() override = default;

  protected:
    ListenerAction UeventCallback(const Uevent& uevent) override;
    RegenerationAction UeventCallback(const Uevent& uevent) override;
    bool GetRequiredDevices() override;
    bool SetUpDmVerity(fstab_rec* fstab_rec) override;
    bool InitAvbHandle();
@@ -144,60 +141,49 @@ bool FirstStageMount::DoFirstStageMount() {
}

bool FirstStageMount::InitDevices() {
    return GetRequiredDevices() && InitRequiredDevices();
    if (!GetRequiredDevices()) return false;

    InitRequiredDevices();

    // InitRequiredDevices() 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()) {
        LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
                   << android::base::Join(required_devices_partition_names_, ", ");
        return false;
    } else {
        return true;
    }
}

// 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() {
void FirstStageMount::InitRequiredDevices() {
    if (required_devices_partition_names_.empty()) {
        return true;
        return;
    }

    if (need_dm_verity_) {
        const std::string dm_path = "/devices/virtual/misc/device-mapper";
        bool found = false;
        auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
        uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path,
                                                  [this, &dm_path](const Uevent& uevent) {
                                                      if (uevent.path == dm_path) {
                                                          device_handler_.HandleDeviceEvent(uevent);
                found = true;
                return ListenerAction::kStop;
            }
            return ListenerAction::kContinue;
        };
        uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
        if (!found) {
            uevent_listener_.Poll(dm_callback, 10s);
        }
        if (!found) {
            LOG(ERROR) << "device-mapper device not found";
            return false;
                                                          return RegenerationAction::kStop;
                                                      }
                                                      return RegenerationAction::kContinue;
                                                  });
    }

    auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); };
    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()) {
        uevent_listener_.Poll(uevent_callback, 10s);
    }

    if (!required_devices_partition_names_.empty()) {
        LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found: "
                   << android::base::Join(required_devices_partition_names_, ", ");
        return false;
    }

    return true;
    uevent_listener_.RegenerateUevents(
        [this](const Uevent& uevent) { return UeventCallback(uevent); });
}

ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) {
RegenerationAction FirstStageMount::UeventCallback(const Uevent& uevent) {
    // Ignores everything that is not a block device.
    if (uevent.subsystem != "block") {
        return ListenerAction::kContinue;
        return RegenerationAction::kContinue;
    }

    if (!uevent.partition_name.empty()) {
@@ -206,46 +192,34 @@ ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) {
        // suffix when A/B is used.
        auto iter = required_devices_partition_names_.find(uevent.partition_name);
        if (iter != required_devices_partition_names_.end()) {
            LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
            LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
            required_devices_partition_names_.erase(iter);
            device_handler_.HandleDeviceEvent(uevent);
            if (required_devices_partition_names_.empty()) {
                return ListenerAction::kStop;
                return RegenerationAction::kStop;
            } else {
                return ListenerAction::kContinue;
                return RegenerationAction::kContinue;
            }
        }
    }
    // Not found a partition or find an unneeded partition, continue to find others.
    return ListenerAction::kContinue;
    return RegenerationAction::kContinue;
}

// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
bool FirstStageMount::InitVerityDevice(const std::string& verity_device) {
void FirstStageMount::InitVerityDevice(const std::string& verity_device) {
    const std::string device_name(basename(verity_device.c_str()));
    const std::string syspath = "/sys/block/" + device_name;
    bool found = false;

    auto verity_callback = [&device_name, &verity_device, this, &found](const Uevent& uevent) {
    uevent_listener_.RegenerateUeventsForPath(
        syspath, [&device_name, &verity_device, this](const Uevent& uevent) {
            if (uevent.device_name == device_name) {
                LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
                device_handler_.HandleDeviceEvent(uevent);
            found = true;
            return ListenerAction::kStop;
                return RegenerationAction::kStop;
            }
        return ListenerAction::kContinue;
    };

    uevent_listener_.RegenerateUeventsForPath(syspath, verity_callback);
    if (!found) {
        uevent_listener_.Poll(verity_callback, 10s);
    }
    if (!found) {
        LOG(ERROR) << "dm-verity device not found";
        return false;
    }

    return true;
            return RegenerationAction::kContinue;
        });
}

bool FirstStageMount::MountPartitions() {
@@ -311,7 +285,7 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
        } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
            // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
            // Needs to create it because ueventd isn't started in init first stage.
            return InitVerityDevice(fstab_rec->blk_device);
            InitVerityDevice(fstab_rec->blk_device);
        } else {
            return false;
        }
@@ -371,7 +345,7 @@ bool FirstStageMountVBootV2::GetRequiredDevices() {
    return true;
}

ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) {
RegenerationAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) {
    // Check if this uevent corresponds to one of the required partitions and store its symlinks if
    // so, in order to create FsManagerAvbHandle later.
    // Note that the parent callback removes partitions from the list of required partitions
+16 −34
Original line number Diff line number Diff line
@@ -121,8 +121,8 @@ bool UeventListener::ReadUevent(Uevent* uevent) const {
// make sure we don't overrun the socket's buffer.
//

ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d,
                                                       const ListenerCallback& callback) const {
RegenerationAction UeventListener::RegenerateUeventsForDir(DIR* d,
                                                           RegenerateCallback callback) const {
    int dfd = dirfd(d);

    int fd = openat(dfd, "uevent", O_WRONLY);
@@ -132,7 +132,7 @@ ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d,

        Uevent uevent;
        while (ReadUevent(&uevent)) {
            if (callback(uevent) == ListenerAction::kStop) return ListenerAction::kStop;
            if (callback(uevent) == RegenerationAction::kStop) return RegenerationAction::kStop;
        }
    }

@@ -147,67 +147,49 @@ ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d,
        if (d2 == 0) {
            close(fd);
        } else {
            if (RegenerateUeventsForDir(d2.get(), callback) == ListenerAction::kStop) {
                return ListenerAction::kStop;
            if (RegenerateUeventsForDir(d2.get(), callback) == RegenerationAction::kStop) {
                return RegenerationAction::kStop;
            }
        }
    }

    // default is always to continue looking for uevents
    return ListenerAction::kContinue;
    return RegenerationAction::kContinue;
}

ListenerAction UeventListener::RegenerateUeventsForPath(const std::string& path,
                                                        const ListenerCallback& callback) const {
RegenerationAction UeventListener::RegenerateUeventsForPath(const std::string& path,
                                                            RegenerateCallback callback) const {
    std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path.c_str()), closedir);
    if (!d) return ListenerAction::kContinue;
    if (!d) return RegenerationAction::kContinue;

    return RegenerateUeventsForDir(d.get(), callback);
}

static const char* kRegenerationPaths[] = {"/sys/class", "/sys/block", "/sys/devices"};

void UeventListener::RegenerateUevents(const ListenerCallback& callback) const {
void UeventListener::RegenerateUevents(RegenerateCallback callback) const {
    for (const auto path : kRegenerationPaths) {
        if (RegenerateUeventsForPath(path, callback) == ListenerAction::kStop) return;
        if (RegenerateUeventsForPath(path, callback) == RegenerationAction::kStop) return;
    }
}

void UeventListener::Poll(const ListenerCallback& callback,
                          const std::optional<std::chrono::milliseconds> relative_timeout) const {
    using namespace std::chrono;

void UeventListener::DoPolling(PollCallback callback) const {
    pollfd ufd;
    ufd.events = POLLIN;
    ufd.fd = device_fd_;

    auto start_time = steady_clock::now();

    while (true) {
        ufd.revents = 0;

        int timeout_ms = -1;
        if (relative_timeout) {
            auto now = steady_clock::now();
            auto time_elapsed = duration_cast<milliseconds>(now - start_time);
            if (time_elapsed > *relative_timeout) return;

            auto remaining_timeout = *relative_timeout - time_elapsed;
            timeout_ms = remaining_timeout.count();
        }

        int nr = poll(&ufd, 1, timeout_ms);
        if (nr == 0) return;
        if (nr < 0) {
            PLOG(ERROR) << "poll() of uevent socket failed, continuing";
        int nr = poll(&ufd, 1, -1);
        if (nr <= 0) {
            continue;
        }
        if (ufd.revents & POLLIN) {
            // We're non-blocking, so if we receive a poll event keep processing until
            // We're non-blocking, so if we receive a poll event keep processing until there
            // we have exhausted all uevent messages.
            Uevent uevent;
            while (ReadUevent(&uevent)) {
                if (callback(uevent) == ListenerAction::kStop) return;
                callback(uevent);
            }
        }
    }
+8 −10
Original line number Diff line number Diff line
@@ -19,9 +19,7 @@

#include <dirent.h>

#include <chrono>
#include <functional>
#include <optional>

#include <android-base/unique_fd.h>

@@ -29,26 +27,26 @@

#define UEVENT_MSG_LEN 2048

enum class ListenerAction {
enum class RegenerationAction {
    kStop = 0,  // Stop regenerating uevents as we've handled the one(s) we're interested in.
    kContinue,  // Continue regenerating uevents as we haven't seen the one(s) we're interested in.
};

using ListenerCallback = std::function<ListenerAction(const Uevent&)>;
using RegenerateCallback = std::function<RegenerationAction(const Uevent&)>;
using PollCallback = std::function<void(const Uevent&)>;

class UeventListener {
  public:
    UeventListener();

    void RegenerateUevents(const ListenerCallback& callback) const;
    ListenerAction RegenerateUeventsForPath(const std::string& path,
                                            const ListenerCallback& callback) const;
    void Poll(const ListenerCallback& callback,
              const std::optional<std::chrono::milliseconds> relative_timeout = {}) const;
    void RegenerateUevents(RegenerateCallback callback) const;
    RegenerationAction RegenerateUeventsForPath(const std::string& path,
                                                RegenerateCallback callback) const;
    void DoPolling(PollCallback callback) const;

  private:
    bool ReadUevent(Uevent* uevent) const;
    ListenerAction RegenerateUeventsForDir(DIR* d, const ListenerCallback& callback) const;
    RegenerationAction RegenerateUeventsForDir(DIR* d, RegenerateCallback callback) const;

    android::base::unique_fd device_fd_;
};
+2 −3
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ void ColdBoot::RegenerateUevents() {
        HandleFirmwareEvent(uevent);

        uevent_queue_.emplace_back(std::move(uevent));
        return ListenerAction::kContinue;
        return RegenerationAction::kContinue;
    });
}

@@ -266,10 +266,9 @@ int ueventd_main(int argc, char** argv) {
        cold_boot.Run();
    }

    uevent_listener.Poll([&device_handler](const Uevent& uevent) {
    uevent_listener.DoPolling([&device_handler](const Uevent& uevent) {
        HandleFirmwareEvent(uevent);
        device_handler.HandleDeviceEvent(uevent);
        return ListenerAction::kContinue;
    });

    return 0;