init: reboot immediately if /data isn't mounted

All of the logic in reboot.cpp is meant to safely shutdown services,
safely unmount emulated RW file systems, then finally unmount the
remaining RW file systems, particularly /data.  If /data hasn't been
mounted, then none of this logic is required.

Running this logic caused a lock up when shutting down blueline from
early-init.  Vold, or potentially a related HAL, locked up during the
ShutdownVold() calls.  debuggerd separately locked up in the watchdog
thread.

Therefore, this change immediately reboots if /data is not mounted.
It also removes the lines to call into debuggerd.  debuggerd will not
run due to SELinux in any case, so it can only be used when hands-on
debugging a device.

Bug: 141082587
Test: shutdown with /data mounted continues as normal
Test: shutdown from early-init immediately shuts the device down
Change-Id: I79c72346b17c7dfe57e955d9739bcaf559badc14
This commit is contained in:
Tom Cherry 2019-09-19 11:16:19 -07:00
parent bac7609c48
commit 2436e6b15a
1 changed files with 36 additions and 9 deletions

View File

@ -60,6 +60,8 @@
#define PROC_SYSRQ "/proc/sysrq-trigger"
using namespace std::literals;
using android::base::GetBoolProperty;
using android::base::Split;
using android::base::Timer;
@ -170,9 +172,23 @@ static void LogShutdownTime(UmountStat stat, Timer* t) {
<< stat;
}
/* Find all read+write block devices and emulated devices in /proc/mounts
* and add them to correpsponding list.
*/
static bool IsDataMounted() {
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent);
if (fp == nullptr) {
PLOG(ERROR) << "Failed to open /proc/mounts";
return false;
}
mntent* mentry;
while ((mentry = getmntent(fp.get())) != nullptr) {
if (mentry->mnt_dir == "/data"s) {
return true;
}
}
return false;
}
// Find all read+write block devices and emulated devices in /proc/mounts and add them to
// the correpsponding list.
static bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions,
std::vector<MountEntry>* emulatedPartitions, bool dump) {
std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "re"), endmntent);
@ -295,12 +311,15 @@ void RebootMonitorThread(unsigned int cmd, const std::string& rebootTarget, sem_
LOG(ERROR) << "Reboot thread timed out";
if (android::base::GetBoolProperty("ro.debuggable", false) == true) {
if (false) {
// SEPolicy will block debuggerd from running and this is intentional.
// But these lines are left to be enabled during debugging.
LOG(INFO) << "Try to dump init process call trace:";
const char* vdc_argv[] = {"/system/bin/debuggerd", "-b", "1"};
int status;
android_fork_execvp_ext(arraysize(vdc_argv), (char**)vdc_argv, &status, true,
LOG_KLOG, true, nullptr, nullptr, 0);
}
LOG(INFO) << "Show stack for all active CPU:";
WriteStringToFile("l", PROC_SYSRQ);
@ -436,6 +455,14 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
Timer t;
LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
// If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to
// worry about unmounting it.
if (!IsDataMounted()) {
sync();
RebootSystem(cmd, rebootTarget);
abort();
}
// Ensure last reboot reason is reduced to canonical
// alias reported in bootloader or system boot reason.
size_t skip = 0;