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
diff --git a/init/devices.cpp b/init/devices.cpp
index 688ad61..ada1e28 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -329,6 +329,10 @@
<< 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 @@
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 @@
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