Merge "update shutdown sequence and use shutdown_timeout to cover all wait"

This commit is contained in:
Keun-young Park 2017-03-27 22:27:29 +00:00 committed by Gerrit Code Review
commit 59cebb6e6f
1 changed files with 26 additions and 19 deletions

View File

@ -263,6 +263,8 @@ static bool UmountPartitions(std::vector<MountEntry>* partitions, int maxRetry,
return umountDone;
}
static void KillAllProcesses() { android::base::WriteStringToFile("i", "/proc/sysrq-trigger"); }
/* Try umounting all emulated file systems R/W block device cfile systems.
* This will just try umount and give it up if it fails.
* For fs like ext4, this is ok as file system will be marked as unclean shutdown
@ -272,7 +274,8 @@ static bool UmountPartitions(std::vector<MountEntry>* partitions, int maxRetry,
*
* return true when umount was successful. false when timed out.
*/
static UmountStat TryUmountAndFsck(bool runFsck) {
static UmountStat TryUmountAndFsck(bool runFsck, int timeoutMs) {
Timer t;
std::vector<MountEntry> emulatedPartitions;
std::vector<MountEntry> blockDevRwPartitions;
@ -297,12 +300,20 @@ static UmountStat TryUmountAndFsck(bool runFsck) {
* still happen while waiting for /data. If the current waiting is not good enough, give
* up and leave it to e2fsck after reboot to fix it.
*/
/* TODO update max waiting time based on usage data */
if (!UmountPartitions(&blockDevRwPartitions, 100, 0)) {
/* Last resort, detach and hope it finish before shutdown. */
UmountPartitions(&blockDevRwPartitions, 1, MNT_DETACH);
stat = UMOUNT_STAT_TIMEOUT;
int remainingTimeMs = timeoutMs - t.duration_ms();
// each retry takes 100ms, and run at least once.
int retry = std::max(remainingTimeMs / 100, 1);
if (!UmountPartitions(&blockDevRwPartitions, retry, 0)) {
/* Last resort, kill all and try again */
LOG(WARNING) << "umount still failing, trying kill all";
KillAllProcesses();
DoSync();
if (!UmountPartitions(&blockDevRwPartitions, 1, 0)) {
stat = UMOUNT_STAT_TIMEOUT;
}
}
// fsck part is excluded from timeout check. It only runs for user initiated shutdown
// and should not affect reboot time.
if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
for (auto& entry : blockDevRwPartitions) {
DoFsck(entry);
@ -312,8 +323,6 @@ static UmountStat TryUmountAndFsck(bool runFsck) {
return stat;
}
static void KillAllProcesses() { android::base::WriteStringToFile("i", "/proc/sysrq-trigger"); }
static void __attribute__((noreturn)) DoThermalOff() {
LOG(WARNING) << "Thermal system shutdown";
DoSync();
@ -334,11 +343,10 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
}
std::string timeout = property_get("ro.build.shutdown_timeout");
unsigned int delay = 0;
if (!android::base::ParseUint(timeout, &delay)) {
delay = 3; // force service termination by default
} else {
LOG(INFO) << "ro.build.shutdown_timeout set:" << delay;
/* TODO update default waiting time based on usage data */
unsigned int shutdownTimeout = 10; // default value
if (android::base::ParseUint(timeout, &shutdownTimeout)) {
LOG(INFO) << "ro.build.shutdown_timeout set:" << shutdownTimeout;
}
static const constexpr char* shutdown_critical_services[] = {"vold", "watchdogd"};
@ -353,7 +361,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
}
// optional shutdown step
// 1. terminate all services except shutdown critical ones. wait for delay to finish
if (delay > 0) {
if (shutdownTimeout > 0) {
LOG(INFO) << "terminating init services";
// tombstoned can write to data when other services are killed. so finish it first.
static const constexpr char* first_to_kill[] = {"tombstoned"};
@ -368,7 +376,9 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
});
int service_count = 0;
while (t.duration_s() < delay) {
// Up to half as long as shutdownTimeout or 3 seconds, whichever is lower.
unsigned int terminationWaitTimeout = std::min<unsigned int>((shutdownTimeout + 1) / 2, 3);
while (t.duration_s() < terminationWaitTimeout) {
ServiceManager::GetInstance().ReapAnyOutstandingChildren();
service_count = 0;
@ -409,12 +419,9 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
} else {
LOG(INFO) << "vold not running, skipping vold shutdown";
}
if (delay == 0) { // no processes terminated. kill all instead.
KillAllProcesses();
}
// 4. sync, try umount, and optionally run fsck for user shutdown
DoSync();
UmountStat stat = TryUmountAndFsck(runFsck);
UmountStat stat = TryUmountAndFsck(runFsck, shutdownTimeout * 1000 - t.duration_ms());
LogShutdownTime(stat, &t);
// Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
RebootSystem(cmd, rebootTarget);