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

Commit 8eec38f4 authored by Bowgo Tsai's avatar Bowgo Tsai
Browse files

Adds /dev/block/by-name/<partition> symlinks

During uevent processing, some "by-name" symlinks will be created.
    /dev/block/<type>/<device>/by-name/<partition>

<type> can be: platform, pci or vbd.
<device> might be: soc.0/f9824900.sdhci, soc.0/f9824900.sdhci, etc.
<partition> might be: system, vendor, system_a, system_b, etc.

e.g., on a non-A/B device:
    /dev/block/platform/soc.0/f9824900.sdhci/by-name/system
    /dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor

On a A/B device:
    /dev/block/platform/soc/1da4000.ufshc/by-name/system_a
    /dev/block/platform/soc/1da4000.ufshc/by-name/system_b
    /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a
    /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_b

However, those symlinks are "device-specific".

This change adds the "generic" symlinks in ueventd, in addition to
the existing symlinks, when the possible "boot devices" are specified
in device tree. e.g.,

    &firmware_android {
	compatible = "android,firmware";
	boot_devices ="soc/1da4000.ufshc,soc.0/f9824900.sdhci";
    }

The following symlinks will then be created on the aforementioned non-A/B
and A/B devices, respectively.

    /dev/block/by-name/system
    /dev/block/by-name/vendor

    /dev/block/by-name/system_a
    /dev/block/by-name/system_b
    /dev/block/by-name/vendor_a
    /dev/block/by-name/vendor_b

Note that both <type> and <device> are skipped in the newly create symlinks.
It assumes there is no more than one devices with the same <partition>,
which is the assumption of current first stage mount flow.

Finally, when 'boot_devices' in DT is absent, it fallbacks to extract
'boot_devices' from fstab settings. e.g., using 'soc/1da4000.ufshc',
'soc.0/f9824900.sdhci' for a fstab with the following content:

   /dev/block/platform/soc/1da4000.ufshc/by-name/system
   /dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor

Bug: 78613232
Test: adb shell ls /dev/block/by-name
Change-Id: Iec920b5a72409b6a2bdbeeb290f0a3acd2046b5d
parent 60fab88e
Loading
Loading
Loading
Loading
+60 −0
Original line number Original line Diff line number Diff line
@@ -686,6 +686,49 @@ static struct fstab *in_place_merge(struct fstab *a, struct fstab *b)
    return a;
    return a;
}
}


/* Extracts <device>s from the by-name symlinks specified in a fstab:
 *   /dev/block/<type>/<device>/by-name/<partition>
 *
 * <type> can be: platform, pci or vbd.
 *
 * For example, given the following entries in the input fstab:
 *   /dev/block/platform/soc/1da4000.ufshc/by-name/system
 *   /dev/block/pci/soc.0/f9824900.sdhci/by-name/vendor
 * it returns a set { "soc/1da4000.ufshc", "soc.0/f9824900.sdhci" }.
 */
static std::set<std::string> extract_boot_devices(const fstab& fstab) {
    std::set<std::string> boot_devices;

    for (int i = 0; i < fstab.num_entries; i++) {
        std::string blk_device(fstab.recs[i].blk_device);
        // Skips blk_device that doesn't conform to the format.
        if (!android::base::StartsWith(blk_device, "/dev/block") ||
            android::base::StartsWith(blk_device, "/dev/block/by-name") ||
            android::base::StartsWith(blk_device, "/dev/block/bootdevice/by-name")) {
            continue;
        }
        // Skips non-by_name blk_device.
        // /dev/block/<type>/<device>/by-name/<partition>
        //                           ^ slash_by_name
        auto slash_by_name = blk_device.find("/by-name");
        if (slash_by_name == std::string::npos) continue;
        blk_device.erase(slash_by_name);  // erases /by-name/<partition>

        // Erases /dev/block/, now we have <type>/<device>
        blk_device.erase(0, std::string("/dev/block/").size());

        // <type>/<device>
        //       ^ first_slash
        auto first_slash = blk_device.find('/');
        if (first_slash == std::string::npos) continue;

        auto boot_device = blk_device.substr(first_slash + 1);
        if (!boot_device.empty()) boot_devices.insert(std::move(boot_device));
    }

    return boot_devices;
}

struct fstab *fs_mgr_read_fstab(const char *fstab_path)
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
{
{
    FILE *fstab_file;
    FILE *fstab_file;
@@ -863,6 +906,23 @@ struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const st
    return nullptr;
    return nullptr;
}
}


std::set<std::string> fs_mgr_get_boot_devices() {
    // boot_devices can be specified in device tree.
    std::string dt_value;
    std::string file_name = get_android_dt_dir() + "/boot_devices";
    if (read_dt_file(file_name, &dt_value)) {
        auto boot_devices = android::base::Split(dt_value, ",");
        return std::set<std::string>(boot_devices.begin(), boot_devices.end());
    }

    // Fallback to extract boot devices from fstab.
    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
                                                               fs_mgr_free_fstab);
    if (fstab) return extract_boot_devices(*fstab);

    return {};
}

int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
{
{
    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
    return fstab->fs_mgr_flags & MF_VOLDMANAGED;
+2 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio.h>


#include <set>
#include <string>
#include <string>


/*
/*
@@ -89,5 +90,6 @@ int fs_mgr_is_logical(const struct fstab_rec* fstab);
int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);


std::string fs_mgr_get_slot_suffix();
std::string fs_mgr_get_slot_suffix();
std::set<std::string> fs_mgr_get_boot_devices();


#endif /* __CORE_FS_TAB_H */
#endif /* __CORE_FS_TAB_H */
+16 −4
Original line number Original line Diff line number Diff line
@@ -329,6 +329,10 @@ std::vector<std::string> DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev
                         << partition_name_sanitized << "'";
                         << partition_name_sanitized << "'";
        }
        }
        links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
        links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
        // Adds symlink: /dev/block/by-name/<partition_name>.
        if (boot_devices_.find(device) != boot_devices_.end()) {
            links.emplace_back("/dev/block/by-name/" + partition_name_sanitized);
        }
    }
    }


    auto last_slash = uevent.path.rfind('/');
    auto last_slash = uevent.path.rfind('/');
@@ -346,8 +350,14 @@ void DeviceHandler::HandleDevice(const std::string& action, const std::string& d
                PLOG(ERROR) << "Failed to create directory " << Dirname(link);
                PLOG(ERROR) << "Failed to create directory " << Dirname(link);
            }
            }


            if (symlink(devpath.c_str(), link.c_str()) && errno != EEXIST) {
            if (symlink(devpath.c_str(), link.c_str())) {
                if (errno != EEXIST) {
                    PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link;
                    PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link;
                } else if (std::string link_path;
                           Readlink(link, &link_path) && link_path != devpath) {
                    PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link
                                << ", which already links to: " << link_path;
                }
            }
            }
        }
        }
    }
    }
@@ -411,16 +421,18 @@ void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) {


DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
                             std::vector<SysfsPermissions> sysfs_permissions,
                             std::vector<SysfsPermissions> sysfs_permissions,
                             std::vector<Subsystem> subsystems, bool skip_restorecon)
                             std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
                             bool skip_restorecon)
    : dev_permissions_(std::move(dev_permissions)),
    : dev_permissions_(std::move(dev_permissions)),
      sysfs_permissions_(std::move(sysfs_permissions)),
      sysfs_permissions_(std::move(sysfs_permissions)),
      subsystems_(std::move(subsystems)),
      subsystems_(std::move(subsystems)),
      boot_devices_(std::move(boot_devices)),
      skip_restorecon_(skip_restorecon),
      skip_restorecon_(skip_restorecon),
      sysfs_mount_point_("/sys") {}
      sysfs_mount_point_("/sys") {}


DeviceHandler::DeviceHandler()
DeviceHandler::DeviceHandler()
    : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
    : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
                    std::vector<Subsystem>{}, false) {}
                    std::vector<Subsystem>{}, std::set<std::string>{}, false) {}


}  // namespace init
}  // namespace init
}  // namespace android
}  // namespace android
+4 −2
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/types.h>


#include <algorithm>
#include <algorithm>
#include <set>
#include <string>
#include <string>
#include <vector>
#include <vector>


@@ -103,8 +104,8 @@ class DeviceHandler {


    DeviceHandler();
    DeviceHandler();
    DeviceHandler(std::vector<Permissions> dev_permissions,
    DeviceHandler(std::vector<Permissions> dev_permissions,
                  std::vector<SysfsPermissions> sysfs_permissions,
                  std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> subsystems,
                  std::vector<Subsystem> subsystems, bool skip_restorecon);
                  std::set<std::string> boot_devices, bool skip_restorecon);
    ~DeviceHandler(){};
    ~DeviceHandler(){};


    void HandleDeviceEvent(const Uevent& uevent);
    void HandleDeviceEvent(const Uevent& uevent);
@@ -125,6 +126,7 @@ class DeviceHandler {
    std::vector<Permissions> dev_permissions_;
    std::vector<Permissions> dev_permissions_;
    std::vector<SysfsPermissions> sysfs_permissions_;
    std::vector<SysfsPermissions> sysfs_permissions_;
    std::vector<Subsystem> subsystems_;
    std::vector<Subsystem> subsystems_;
    std::set<std::string> boot_devices_;
    bool skip_restorecon_;
    bool skip_restorecon_;
    std::string sysfs_mount_point_;
    std::string sysfs_mount_point_;
};
};
+10 −5
Original line number Original line Diff line number Diff line
@@ -77,7 +77,7 @@ class FirstStageMount {
    std::unique_ptr<LogicalPartitionTable> dm_linear_table_;
    std::unique_ptr<LogicalPartitionTable> dm_linear_table_;
    std::vector<fstab_rec*> mount_fstab_recs_;
    std::vector<fstab_rec*> mount_fstab_recs_;
    std::set<std::string> required_devices_partition_names_;
    std::set<std::string> required_devices_partition_names_;
    DeviceHandler device_handler_;
    std::unique_ptr<DeviceHandler> device_handler_;
    UeventListener uevent_listener_;
    UeventListener uevent_listener_;
};
};


@@ -147,6 +147,11 @@ FirstStageMount::FirstStageMount()
    if (IsDmLinearEnabled()) {
    if (IsDmLinearEnabled()) {
        dm_linear_table_ = android::fs_mgr::LoadPartitionsFromDeviceTree();
        dm_linear_table_ = android::fs_mgr::LoadPartitionsFromDeviceTree();
    }
    }

    auto boot_devices = fs_mgr_get_boot_devices();
    device_handler_ =
        std::make_unique<DeviceHandler>(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
                                        std::vector<Subsystem>{}, std::move(boot_devices), false);
}
}


std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
@@ -205,7 +210,7 @@ bool FirstStageMount::InitRequiredDevices() {
        bool found = false;
        bool found = false;
        auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
        auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
            if (uevent.path == dm_path) {
            if (uevent.path == dm_path) {
                device_handler_.HandleDeviceEvent(uevent);
                device_handler_->HandleDeviceEvent(uevent);
                found = true;
                found = true;
                return ListenerAction::kStop;
                return ListenerAction::kStop;
            }
            }
@@ -262,7 +267,7 @@ ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const
    if (iter != required_devices_partition_names_.end()) {
    if (iter != required_devices_partition_names_.end()) {
        LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
        LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter;
        required_devices_partition_names_.erase(iter);
        required_devices_partition_names_.erase(iter);
        device_handler_.HandleDeviceEvent(uevent);
        device_handler_->HandleDeviceEvent(uevent);
        if (required_devices_partition_names_.empty()) {
        if (required_devices_partition_names_.empty()) {
            return ListenerAction::kStop;
            return ListenerAction::kStop;
        } else {
        } else {
@@ -299,7 +304,7 @@ bool FirstStageMount::InitMappedDevice(const std::string& dm_device) {
    auto verity_callback = [&device_name, &dm_device, this, &found](const Uevent& uevent) {
    auto verity_callback = [&device_name, &dm_device, this, &found](const Uevent& uevent) {
        if (uevent.device_name == device_name) {
        if (uevent.device_name == device_name) {
            LOG(VERBOSE) << "Creating device-mapper device : " << dm_device;
            LOG(VERBOSE) << "Creating device-mapper device : " << dm_device;
            device_handler_.HandleDeviceEvent(uevent);
            device_handler_->HandleDeviceEvent(uevent);
            found = true;
            found = true;
            return ListenerAction::kStop;
            return ListenerAction::kStop;
        }
        }
@@ -469,7 +474,7 @@ ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) {
        // is not empty. e.g.,
        // is not empty. e.g.,
        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
        //   - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
        //   - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
        std::vector<std::string> links = device_handler_.GetBlockDeviceSymlinks(uevent);
        std::vector<std::string> links = device_handler_->GetBlockDeviceSymlinks(uevent);
        if (!links.empty()) {
        if (!links.empty()) {
            auto[it, inserted] = by_name_symlink_map_.emplace(uevent.partition_name, links[0]);
            auto[it, inserted] = by_name_symlink_map_.emplace(uevent.partition_name, links[0]);
            if (!inserted) {
            if (!inserted) {
Loading