Activate system APEXes early
Summary: Boot sequence around apexd is changed to make it possible for pre-apexd processes to use libraries from APEXes. They no longer need to wait for the apexd to finish activating APEXes, which again can be done only after /data/ is mounted. This improves overall boot performance. Detail: This change fixes the problem that processes that are started before apexd (so called pre-apexd processes) can't access libraries that are provided only by the APEXes but are not found in the system partition (e.g. libdexfile_external.so, etc.). Main idea is to activate system APEXes (/system/apex/*.apex) before /data is mounted and then activate the updated APEXes (/data/apex/*.apex) after the /data mount. Detailed boot sequence is as follows. 1) init prepares the bootstrap and default mount namespaces. A tmpfs is mounted on /apex and the propagation type of the mountpoint is set to private. 2) before any other process is started, apexd is started in bootstrap mode. When executed in the mode, apexd only activates APEXes under /system/apex. Note that APEXes activated in this phase are mounted in the bootstrap mount namespace only. 3) other pre-apexd processes are started. They are in the bootstrap mount namespace and thus are provided with the libraries from the system APEXes. 4) /data is mounted. init switches into the default mount namespace and starts apexd as a daemon as usual. 5) apexd scans both /data/apex and /system/apex, and activate latest APEXes from the directories. Note that APEXes activated in this phase are mounted in the default namespaces only and thus are not visible to the pre-apexd processes. Bug: 125549215 Test: m; device boots Change-Id: I21c60d0ebe188fa4f24d6e6861f85ca204843069
This commit is contained in:
parent
4ba548d845
commit
dcbaf9f41b
|
@ -1119,13 +1119,21 @@ static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
|
|||
}
|
||||
|
||||
static Result<Success> do_setup_runtime_bionic(const BuiltinArguments& args) {
|
||||
if (SwitchToDefaultMountNamespace()) {
|
||||
if (SetupRuntimeBionic()) {
|
||||
return Success();
|
||||
} else {
|
||||
return Error() << "Failed to setup runtime bionic";
|
||||
}
|
||||
}
|
||||
|
||||
static Result<Success> do_enter_default_mount_ns(const BuiltinArguments& args) {
|
||||
if (SwitchToDefaultMountNamespace()) {
|
||||
return Success();
|
||||
} else {
|
||||
return Error() << "Failed to enter into default mount namespace";
|
||||
}
|
||||
}
|
||||
|
||||
// Builtin-function-map start
|
||||
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
||||
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
|
||||
|
@ -1177,6 +1185,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
|||
{"start", {1, 1, {false, do_start}}},
|
||||
{"stop", {1, 1, {false, do_stop}}},
|
||||
{"swapon_all", {1, 1, {false, do_swapon_all}}},
|
||||
{"enter_default_mount_ns", {0, 0, {false, do_enter_default_mount_ns}}},
|
||||
{"symlink", {2, 2, {true, do_symlink}}},
|
||||
{"sysclktz", {1, 1, {false, do_sysclktz}}},
|
||||
{"trigger", {1, 1, {false, do_trigger}}},
|
||||
|
|
|
@ -172,6 +172,11 @@ bool SetupMountNamespaces() {
|
|||
kBionicLibsMountPointDir64))
|
||||
return false;
|
||||
|
||||
// /apex is also a private mountpoint to give different sets of APEXes for
|
||||
// the bootstrap and default mount namespaces. The processes running with
|
||||
// the bootstrap namespace get APEXes from the read-only partition.
|
||||
if (!(MakePrivate("/apex"))) return false;
|
||||
|
||||
bootstrap_ns_fd.reset(OpenMountNamespace());
|
||||
bootstrap_ns_id = GetMountNamespaceId();
|
||||
|
||||
|
@ -227,6 +232,17 @@ bool SwitchToDefaultMountNamespace() {
|
|||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Switched to default mount namespace";
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(jiyong): remove this when /system/lib/libc.so becomes
|
||||
// a symlink to /apex/com.android.runtime/lib/bionic/libc.so
|
||||
bool SetupRuntimeBionic() {
|
||||
if (IsRecoveryMode()) {
|
||||
// We don't have multiple namespaces in recovery mode
|
||||
return true;
|
||||
}
|
||||
// Bind-mount bionic from the runtime APEX since it is now available. Note
|
||||
// that in case of IsBionicUpdatable() == false, these mounts are over the
|
||||
// existing existing bind mounts for the bootstrap bionic, which effectively
|
||||
|
@ -238,7 +254,7 @@ bool SwitchToDefaultMountNamespace() {
|
|||
kBionicLibsMountPointDir64))
|
||||
return false;
|
||||
|
||||
LOG(INFO) << "Switched to default mount namespace";
|
||||
LOG(INFO) << "Runtime bionic is set up";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace android {
|
|||
namespace init {
|
||||
|
||||
bool SetupMountNamespaces();
|
||||
bool SetupRuntimeBionic();
|
||||
bool SwitchToDefaultMountNamespace();
|
||||
bool SwitchToBootstrapMountNamespaceIfNeeded();
|
||||
|
||||
|
|
|
@ -13,12 +13,6 @@ import /init.${ro.zygote}.rc
|
|||
|
||||
# Cgroups are mounted right before early-init using list from /etc/cgroups.json
|
||||
on early-init
|
||||
# Mount shared so changes propagate into child namespaces
|
||||
# Do this before other processes are started from init. Otherwise,
|
||||
# processes launched while the propagation type of / is 'private'
|
||||
# won't get mount events from others.
|
||||
mount rootfs rootfs / shared rec
|
||||
|
||||
# Set init and its forked children's oom_adj.
|
||||
write /proc/1/oom_score_adj -1000
|
||||
|
||||
|
@ -43,6 +37,11 @@ on early-init
|
|||
|
||||
start ueventd
|
||||
|
||||
# Run apexd-bootstrap so that APEXes that provide critical libraries
|
||||
# become available. Note that this is executed as exec_start to ensure that
|
||||
# the libraries are available to the processes started after this statement.
|
||||
exec_start apexd-bootstrap
|
||||
|
||||
on init
|
||||
sysclktz 0
|
||||
|
||||
|
@ -281,9 +280,6 @@ on init
|
|||
# Start logd before any other services run to ensure we capture all of their logs.
|
||||
start logd
|
||||
|
||||
# Start apexd as soon as we can
|
||||
start apexd
|
||||
|
||||
# Start essential services.
|
||||
start servicemanager
|
||||
start hwservicemanager
|
||||
|
@ -419,8 +415,16 @@ on post-fs-data
|
|||
mkdir /data/bootchart 0755 shell shell
|
||||
bootchart start
|
||||
|
||||
# /data/apex is now available. Let apexd to scan and activate APEXes.
|
||||
setprop apexd.data.status ready
|
||||
# Make sure that apexd is started in the default namespace
|
||||
enter_default_mount_ns
|
||||
|
||||
# /data/apex is now available. Start apexd to scan and activate APEXes.
|
||||
mkdir /data/apex 0750 root system
|
||||
mkdir /data/apex/active 0750 root system
|
||||
mkdir /data/apex/backup 0700 root system
|
||||
mkdir /data/apex/sessions 0700 root system
|
||||
mkdir /data/pkg_staging 0750 system system
|
||||
start apexd
|
||||
|
||||
# Avoid predictable entropy pool. Carry over entropy from previous boot.
|
||||
copy /data/system/entropy.dat /dev/urandom
|
||||
|
@ -537,12 +541,6 @@ on post-fs-data
|
|||
|
||||
mkdir /data/anr 0775 system system
|
||||
|
||||
mkdir /data/apex 0750 root system
|
||||
mkdir /data/apex/active 0750 root system
|
||||
mkdir /data/apex/backup 0700 root system
|
||||
mkdir /data/apex/sessions 0700 root system
|
||||
mkdir /data/pkg_staging 0750 system system
|
||||
|
||||
# NFC: create data/nfc for nv storage
|
||||
mkdir /data/nfc 0770 nfc nfc
|
||||
mkdir /data/nfc/param 0770 nfc nfc
|
||||
|
@ -575,6 +573,12 @@ on post-fs-data
|
|||
mkdir /data/cache/backup_stage 0700 system system
|
||||
mkdir /data/cache/backup 0700 system system
|
||||
|
||||
# Wait for apexd to finish activating APEXes before starting more processes.
|
||||
wait_for_prop apexd.status ready
|
||||
# TODO(jiyong): remove setup_runtime_bionic
|
||||
setup_runtime_bionic
|
||||
parse_apex_configs
|
||||
|
||||
init_user0
|
||||
|
||||
# Set SELinux security contexts on upgrade or policy update.
|
||||
|
@ -583,14 +587,6 @@ on post-fs-data
|
|||
# load fsverity keys
|
||||
exec -- /system/bin/mini-keyctl -c /product/etc/security/cacerts_fsverity,/vendor/etc/security/cacerts_fsverity -k .fs-verity
|
||||
|
||||
# Wait for apexd to finish activating APEXes before starting more processes.
|
||||
# This certainly reduces the parallelism but is required to make as many processes
|
||||
# as possible to use the bionic libs from the runtime APEX. This takes less than 50ms
|
||||
# so the impact on the booting time is not significant.
|
||||
wait_for_prop apexd.status ready
|
||||
setup_runtime_bionic
|
||||
parse_apex_configs
|
||||
|
||||
# Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
|
||||
exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
|
||||
|
||||
|
|
Loading…
Reference in New Issue