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
This commit is contained in:
parent
60fab88ecc
commit
8eec38f4e4
|
@ -686,6 +686,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;
|
||||
|
@ -863,6 +906,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;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <set>
|
||||
#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);
|
||||
|
||||
std::string fs_mgr_get_slot_suffix();
|
||||
std::set<std::string> fs_mgr_get_boot_devices();
|
||||
|
||||
#endif /* __CORE_FS_TAB_H */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ class FirstStageMount {
|
|||
std::unique_ptr<LogicalPartitionTable> dm_linear_table_;
|
||||
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_;
|
||||
};
|
||||
|
||||
|
@ -147,6 +147,11 @@ FirstStageMount::FirstStageMount()
|
|||
if (IsDmLinearEnabled()) {
|
||||
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() {
|
||||
|
@ -205,7 +210,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;
|
||||
}
|
||||
|
@ -262,7 +267,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 {
|
||||
|
@ -299,7 +304,7 @@ bool FirstStageMount::InitMappedDevice(const std::string& dm_device) {
|
|||
auto verity_callback = [&device_name, &dm_device, this, &found](const Uevent& uevent) {
|
||||
if (uevent.device_name == device_name) {
|
||||
LOG(VERBOSE) << "Creating device-mapper device : " << dm_device;
|
||||
device_handler_.HandleDeviceEvent(uevent);
|
||||
device_handler_->HandleDeviceEvent(uevent);
|
||||
found = true;
|
||||
return ListenerAction::kStop;
|
||||
}
|
||||
|
@ -469,7 +474,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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue