Cleanup logic in KillZramBackingDevice

Since this function is used in userspace reboot, we need to be more
diligent with error handling, e.g.:

* If init fails to read /sys/block/zram0/backing_dev, then fail and
fallback to hard reboot.
* Always call swapoff.
* Always reset zram.
* Tear down loop device only if zram is backed by a loop device.

Test: adb reboot userspace
Bug: 153917129
Change-Id: I4709da1d08cf427ad9c898cfb2506b6a29f1d680
Merged-In: I4709da1d08cf427ad9c898cfb2506b6a29f1d680
(cherry picked from commit a840d405eb)
This commit is contained in:
Nikita Ioffe 2020-04-16 21:37:03 +01:00
parent 10f8f5e363
commit a3be996673

View file

@ -203,6 +203,7 @@ static void TurnOffBacklight() {
}
static Result<void> CallVdc(const std::string& system, const std::string& cmd) {
LOG(INFO) << "Calling /system/bin/vdc " << system << " " << cmd;
const char* vdc_argv[] = {"/system/bin/vdc", system.c_str(), cmd.c_str()};
int status;
if (logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true,
@ -456,10 +457,14 @@ static UmountStat TryUmountAndFsck(unsigned int cmd, bool run_fsck,
#define ZRAM_RESET "/sys/block/zram0/reset"
#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
static Result<void> KillZramBackingDevice() {
if (access(ZRAM_BACK_DEV, F_OK) != 0 && errno == ENOENT) {
LOG(INFO) << "No zram backing device configured";
return {};
}
std::string backing_dev;
if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return {};
if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return {};
if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) {
return ErrnoError() << "Failed to read " << ZRAM_BACK_DEV;
}
// cut the last "\n"
backing_dev.erase(backing_dev.length() - 1);
@ -478,6 +483,11 @@ static Result<void> KillZramBackingDevice() {
<< " failed";
}
if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) {
LOG(INFO) << backing_dev << " is not a loop device. Exiting early";
return {};
}
// clear loopback device
unique_fd loop(TEMP_FAILURE_RETRY(open(backing_dev.c_str(), O_RDWR | O_CLOEXEC)));
if (loop.get() < 0) {
@ -785,7 +795,7 @@ static Result<void> DoUserspaceReboot() {
}
auto sigterm_timeout = GetMillisProperty("init.userspace_reboot.sigterm.timeoutmillis", 5s);
auto sigkill_timeout = GetMillisProperty("init.userspace_reboot.sigkill.timeoutmillis", 10s);
LOG(INFO) << "Timeout to terminate services : " << sigterm_timeout.count() << "ms"
LOG(INFO) << "Timeout to terminate services: " << sigterm_timeout.count() << "ms "
<< "Timeout to kill services: " << sigkill_timeout.count() << "ms";
StopServicesAndLogViolations(stop_first, sigterm_timeout, true /* SIGTERM */);
if (int r = StopServicesAndLogViolations(stop_first, sigkill_timeout, false /* SIGKILL */);