init: add umount_all builtin.
umount_all is the cleanup step for mount_all.
In particular, the mount_all builtin creates a verity device,
'postinstall-verity', for the following line:
system /postinstall ... ... slotselect_other,logical,avb_keys=...
cppreopt umounts /postinstall but doesn't destroy the postinstall-verity
device, causing OTA to fail (because it cannot destroy the
system_[other] device). umount_all also destroy the verity device.
Note that mount_all does not map system_[other]; it is mapped by
first stage init. Hence, umount_all doesn't destroy it either. The OTA
client is reponsible for unmapping the device itself.
Bug: 129988285
Test: flash, boot, then check `dmctl list devices`, then OTA
Change-Id: Id3ab65b3860b6ea6cfec310ab13652009c81f415
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 8437e37..fc75072 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -451,13 +451,13 @@
if (false) DumpState();
}
-/* mount_fstab
+/* handle_fstab
*
- * Call fs_mgr_mount_all() to mount the given fstab
+ * Read the given fstab file and execute func on it.
*/
-static Result<int> mount_fstab(const char* fstabfile, int mount_mode) {
+static Result<int> handle_fstab(const std::string& fstabfile, std::function<int(Fstab*)> func) {
/*
- * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
+ * Call fs_mgr_[u]mount_all() to [u]mount all filesystems. We fork(2) and
* do the call in the child to provide protection to the main init
* process if anything goes wrong (crash or memory leak), and wait for
* the child to finish in the parent.
@@ -478,25 +478,51 @@
return Error() << "child aborted";
}
} else if (pid == 0) {
- /* child, call fs_mgr_mount_all() */
+ /* child, call fs_mgr_[u]mount_all() */
- // So we can always see what fs_mgr_mount_all() does.
+ // So we can always see what fs_mgr_[u]mount_all() does.
// Only needed if someone explicitly changes the default log level in their init.rc.
android::base::ScopedLogSeverity info(android::base::INFO);
Fstab fstab;
ReadFstabFromFile(fstabfile, &fstab);
- int child_ret = fs_mgr_mount_all(&fstab, mount_mode);
- if (child_ret == -1) {
- PLOG(ERROR) << "fs_mgr_mount_all returned an error";
- }
+ int child_ret = func(&fstab);
+
_exit(child_ret);
} else {
return Error() << "fork() failed";
}
}
+/* mount_fstab
+ *
+ * Call fs_mgr_mount_all() to mount the given fstab
+ */
+static Result<int> mount_fstab(const std::string& fstabfile, int mount_mode) {
+ return handle_fstab(fstabfile, [mount_mode](Fstab* fstab) {
+ int ret = fs_mgr_mount_all(fstab, mount_mode);
+ if (ret == -1) {
+ PLOG(ERROR) << "fs_mgr_mount_all returned an error";
+ }
+ return ret;
+ });
+}
+
+/* umount_fstab
+ *
+ * Call fs_mgr_umount_all() to umount the given fstab
+ */
+static Result<int> umount_fstab(const std::string& fstabfile) {
+ return handle_fstab(fstabfile, [](Fstab* fstab) {
+ int ret = fs_mgr_umount_all(fstab);
+ if (ret != 0) {
+ PLOG(ERROR) << "fs_mgr_umount_all returned " << ret;
+ }
+ return ret;
+ });
+}
+
/* Queue event based on fs_mgr return code.
*
* code: return code of fs_mgr_mount_all
@@ -583,7 +609,7 @@
bool import_rc = true;
bool queue_event = true;
int mount_mode = MOUNT_MODE_DEFAULT;
- const char* fstabfile = args[1].c_str();
+ const auto& fstabfile = args[1];
std::size_t path_arg_end = args.size();
const char* prop_post_fix = "default";
@@ -626,6 +652,15 @@
return Success();
}
+/* umount_all <fstab> */
+static Result<Success> do_umount_all(const BuiltinArguments& args) {
+ auto umount_fstab_return_code = umount_fstab(args[1]);
+ if (!umount_fstab_return_code) {
+ return Error() << "umount_fstab() failed " << umount_fstab_return_code.error();
+ }
+ return Success();
+}
+
static Result<Success> do_swapon_all(const BuiltinArguments& args) {
Fstab fstab;
if (!ReadFstabFromFile(args[1], &fstab)) {
@@ -1165,6 +1200,7 @@
{"mount", {3, kMax, {false, do_mount}}},
{"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
{"umount", {1, 1, {false, do_umount}}},
+ {"umount_all", {1, 1, {false, do_umount_all}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"restart", {1, 1, {false, do_restart}}},
{"restorecon", {1, kMax, {true, do_restorecon}}},