Userspace reboot: Support remounting userdata for f2fs
Test: adb reboot userspace
Test: adb shell /system/bin/vdc startCheckpoint 1;
adb reboot userspace
Bug: 135984674
Change-Id: I227f2c1cc18495d893decb2df5173fc7a7919df6
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 2f2ead0..b2c6461 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -42,6 +42,8 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <memory>
+
#include <ApexProperties.sysprop.h>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
@@ -627,6 +629,8 @@
return Error() << "Invalid code: " << code;
}
+static int initial_mount_fstab_return_code = -1;
+
/* mount_all <fstab> [ <path> ]* [--<options>]*
*
* This function might request a reboot, in which case it will
@@ -662,6 +666,7 @@
if (!ReadFstabFromFile(fstab_file, &fstab)) {
return Error() << "Could not read fstab";
}
+
auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
property_set(prop_name, std::to_string(t.duration().count()));
@@ -673,6 +678,7 @@
if (queue_event) {
/* queue_fs_event will queue event based on mount_fstab return code
* and return processed return code*/
+ initial_mount_fstab_return_code = mount_fstab_return_code;
auto queue_fs_result = queue_fs_event(mount_fstab_return_code);
if (!queue_fs_result) {
return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
@@ -1132,6 +1138,25 @@
return ExecWithFunctionOnFailure(args, reboot);
}
+static Result<void> do_remount_userdata(const BuiltinArguments& args) {
+ if (initial_mount_fstab_return_code == -1) {
+ return Error() << "Calling remount_userdata too early";
+ }
+ Fstab fstab;
+ if (!ReadDefaultFstab(&fstab)) {
+ // TODO(b/135984674): should we reboot here?
+ return Error() << "Failed to read fstab";
+ }
+ // TODO(b/135984674): check that fstab contains /data.
+ if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) {
+ TriggerShutdown("reboot,mount-userdata-failed");
+ }
+ if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result) {
+ return Error() << "queue_fs_event() failed: " << result.error();
+ }
+ return {};
+}
+
static Result<void> do_installkey(const BuiltinArguments& args) {
if (!is_file_crypto()) return {};
@@ -1243,6 +1268,7 @@
{"umount", {1, 1, {false, do_umount}}},
{"umount_all", {1, 1, {false, do_umount_all}}},
{"readahead", {1, 2, {true, do_readahead}}},
+ {"remount_userdata", {0, 0, {false, do_remount_userdata}}},
{"restart", {1, 1, {false, do_restart}}},
{"restorecon", {1, kMax, {true, do_restorecon}}},
{"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}},
diff --git a/init/reboot.cpp b/init/reboot.cpp
index d77b975..f2e260e 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -181,10 +181,17 @@
}
}
-static void ShutdownVold() {
+static Result<void> ShutdownVold() {
const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
int status;
- logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true, nullptr);
+ if (logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true,
+ nullptr) != 0) {
+ return ErrnoError() << "Failed to call 'vdc volume shutdown'";
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return {};
+ }
+ return Error() << "'vdc volume shutdown' failed : " << status;
}
static void LogShutdownTime(UmountStat stat, Timer* t) {
@@ -426,11 +433,11 @@
#define ZRAM_DEVICE "/dev/block/zram0"
#define ZRAM_RESET "/sys/block/zram0/reset"
#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
-static void KillZramBackingDevice() {
+static Result<void> KillZramBackingDevice() {
std::string backing_dev;
- if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return;
+ if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return {};
- if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return;
+ if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return {};
// cut the last "\n"
backing_dev.erase(backing_dev.length() - 1);
@@ -439,28 +446,29 @@
Timer swap_timer;
LOG(INFO) << "swapoff() start...";
if (swapoff(ZRAM_DEVICE) == -1) {
- LOG(ERROR) << "zram_backing_dev: swapoff (" << backing_dev << ")" << " failed";
- return;
+ return ErrnoError() << "zram_backing_dev: swapoff (" << backing_dev << ")"
+ << " failed";
}
LOG(INFO) << "swapoff() took " << swap_timer;;
if (!WriteStringToFile("1", ZRAM_RESET)) {
- LOG(ERROR) << "zram_backing_dev: reset (" << backing_dev << ")" << " failed";
- return;
+ return Error() << "zram_backing_dev: reset (" << backing_dev << ")"
+ << " failed";
}
// clear loopback device
unique_fd loop(TEMP_FAILURE_RETRY(open(backing_dev.c_str(), O_RDWR | O_CLOEXEC)));
if (loop.get() < 0) {
- LOG(ERROR) << "zram_backing_dev: open(" << backing_dev << ")" << " failed";
- return;
+ return ErrnoError() << "zram_backing_dev: open(" << backing_dev << ")"
+ << " failed";
}
if (ioctl(loop.get(), LOOP_CLR_FD, 0) < 0) {
- LOG(ERROR) << "zram_backing_dev: loop_clear (" << backing_dev << ")" << " failed";
- return;
+ return ErrnoError() << "zram_backing_dev: loop_clear (" << backing_dev << ")"
+ << " failed";
}
LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
+ return {};
}
// Stops given services, waits for them to be stopped for |timeout| ms.
@@ -738,7 +746,23 @@
// TODO(b/135984674): store information about offending services for debugging.
return Error() << r << " post-data services are still running";
}
- // TODO(b/135984674): remount userdata
+ // We only really need to restart vold if userdata is ext4 filesystem.
+ // TODO(b/135984674): get userdata fs type here, and do nothing in case of f2fs.
+ // First shutdown volumes managed by vold. They will be recreated by
+ // system_server.
+ Service* vold_service = ServiceList::GetInstance().FindService("vold");
+ if (vold_service != nullptr && vold_service->IsRunning()) {
+ if (auto result = ShutdownVold(); !result) {
+ return result;
+ }
+ LOG(INFO) << "Restarting vold";
+ vold_service->Restart();
+ }
+ // Again, we only need to kill zram backing device in case of ext4 userdata.
+ // TODO(b/135984674): get userdata fs type here, and do nothing in case of f2fs.
+ if (auto result = KillZramBackingDevice(); !result) {
+ return result;
+ }
if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
false /* SIGKILL */);
r > 0) {