diff options
author | Bowgo Tsai <bowgotsai@google.com> | 2018-05-16 18:33:44 +0800 |
---|---|---|
committer | Bowgo Tsai <bowgotsai@google.com> | 2018-05-19 09:31:35 +0800 |
commit | 5ee7dae840eaebdd1aec47632e2a32e1ba7dd90a (patch) | |
tree | 3b8104eb360e70ef781dcc01375cbbef37165b18 | |
parent | ff17cc31e5aa49fc8cce1693f813d150a7343ab5 (diff) | |
download | core-5ee7dae840eaebdd1aec47632e2a32e1ba7dd90a.tar.gz |
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
Merged-In: Iec920b5a72409b6a2bdbeeb290f0a3acd2046b5d
(cherry picked from commit 8eec38f4e463d8cd980562ec49432c17972cc5cb)
-rw-r--r-- | fs_mgr/fs_mgr_fstab.cpp | 60 | ||||
-rw-r--r-- | fs_mgr/include_fstab/fstab/fstab.h | 2 | ||||
-rw-r--r-- | init/devices.cpp | 20 | ||||
-rw-r--r-- | init/devices.h | 6 | ||||
-rw-r--r-- | init/init_first_stage.cpp | 15 | ||||
-rw-r--r-- | init/ueventd.cpp | 4 |
6 files changed, 95 insertions, 12 deletions
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 9d504d6d5..68cc530dd 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -679,6 +679,49 @@ static struct fstab *in_place_merge(struct fstab *a, struct fstab *b) 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) { FILE *fstab_file; @@ -855,6 +898,23 @@ struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const st 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) { return fstab->fs_mgr_flags & MF_VOLDMANAGED; diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h index 8c585dd2f..e8da2ac85 100644 --- a/fs_mgr/include_fstab/fstab/fstab.h +++ b/fs_mgr/include_fstab/fstab/fstab.h @@ -22,6 +22,7 @@ #include <stdint.h> #include <stdio.h> +#include <set> #include <string> /* @@ -87,5 +88,6 @@ int fs_mgr_is_quota(const struct fstab_rec* fstab); int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab); std::string fs_mgr_get_slot_suffix(); +std::set<std::string> fs_mgr_get_boot_devices(); #endif /* __CORE_FS_TAB_H */ diff --git a/init/devices.cpp b/init/devices.cpp index 688ad6196..ada1e2870 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -329,6 +329,10 @@ std::vector<std::string> DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev << 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('/'); @@ -346,8 +350,14 @@ void DeviceHandler::HandleDevice(const std::string& action, const std::string& d PLOG(ERROR) << "Failed to create directory " << Dirname(link); } - if (symlink(devpath.c_str(), link.c_str()) && errno != EEXIST) { - PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link; + if (symlink(devpath.c_str(), link.c_str())) { + if (errno != EEXIST) { + 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, 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)), sysfs_permissions_(std::move(sysfs_permissions)), subsystems_(std::move(subsystems)), + boot_devices_(std::move(boot_devices)), skip_restorecon_(skip_restorecon), sysfs_mount_point_("/sys") {} DeviceHandler::DeviceHandler() : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, - std::vector<Subsystem>{}, false) {} + std::vector<Subsystem>{}, std::set<std::string>{}, false) {} } // namespace init } // namespace android diff --git a/init/devices.h b/init/devices.h index 1f8f1e8a9..f9035da3d 100644 --- a/init/devices.h +++ b/init/devices.h @@ -21,6 +21,7 @@ #include <sys/types.h> #include <algorithm> +#include <set> #include <string> #include <vector> @@ -103,8 +104,8 @@ class DeviceHandler { DeviceHandler(); DeviceHandler(std::vector<Permissions> dev_permissions, - std::vector<SysfsPermissions> sysfs_permissions, - std::vector<Subsystem> subsystems, bool skip_restorecon); + std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> subsystems, + std::set<std::string> boot_devices, bool skip_restorecon); ~DeviceHandler(){}; void HandleDeviceEvent(const Uevent& uevent); @@ -125,6 +126,7 @@ class DeviceHandler { std::vector<Permissions> dev_permissions_; std::vector<SysfsPermissions> sysfs_permissions_; std::vector<Subsystem> subsystems_; + std::set<std::string> boot_devices_; bool skip_restorecon_; std::string sysfs_mount_point_; }; diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp index 1dfceb459..033ce419a 100644 --- a/init/init_first_stage.cpp +++ b/init/init_first_stage.cpp @@ -72,7 +72,7 @@ class FirstStageMount { std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_; std::vector<fstab_rec*> mount_fstab_recs_; std::set<std::string> required_devices_partition_names_; - DeviceHandler device_handler_; + std::unique_ptr<DeviceHandler> device_handler_; UeventListener uevent_listener_; }; @@ -127,6 +127,11 @@ FirstStageMount::FirstStageMount() for (int i = 0; i < device_tree_fstab_->num_entries; i++) { mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]); } + + 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() { @@ -165,7 +170,7 @@ bool FirstStageMount::InitRequiredDevices() { bool found = false; auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) { if (uevent.path == dm_path) { - device_handler_.HandleDeviceEvent(uevent); + device_handler_->HandleDeviceEvent(uevent); found = true; return ListenerAction::kStop; } @@ -215,7 +220,7 @@ ListenerAction FirstStageMount::HandleBlockDevice(const std::string& name, const if (iter != required_devices_partition_names_.end()) { LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter; required_devices_partition_names_.erase(iter); - device_handler_.HandleDeviceEvent(uevent); + device_handler_->HandleDeviceEvent(uevent); if (required_devices_partition_names_.empty()) { return ListenerAction::kStop; } else { @@ -252,7 +257,7 @@ bool FirstStageMount::InitVerityDevice(const std::string& verity_device) { auto verity_callback = [&device_name, &verity_device, this, &found](const Uevent& uevent) { if (uevent.device_name == device_name) { LOG(VERBOSE) << "Creating dm-verity device : " << verity_device; - device_handler_.HandleDeviceEvent(uevent); + device_handler_->HandleDeviceEvent(uevent); found = true; return ListenerAction::kStop; } @@ -414,7 +419,7 @@ ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) { // is not empty. e.g., // - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem // - /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()) { auto[it, inserted] = by_name_symlink_map_.emplace(uevent.partition_name, links[0]); if (!inserted) { diff --git a/init/ueventd.cpp b/init/ueventd.cpp index 1435d82ef..a284203ba 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -30,6 +30,7 @@ #include <android-base/chrono_utils.h> #include <android-base/logging.h> #include <android-base/properties.h> +#include <fstab/fstab.h> #include <selinux/android.h> #include <selinux/selinux.h> @@ -242,8 +243,9 @@ DeviceHandler CreateDeviceHandler() { std::string hardware = android::base::GetProperty("ro.hardware", ""); parser.ParseConfig("/ueventd." + hardware + ".rc"); + auto boot_devices = fs_mgr_get_boot_devices(); return DeviceHandler(std::move(dev_permissions), std::move(sysfs_permissions), - std::move(subsystems), true); + std::move(subsystems), std::move(boot_devices), true); } int ueventd_main(int argc, char** argv) { |