recovery: add --fsck_unshare_blocks option for adb remount
Allow "adb remount" on deduplicated filesystems to reboot into recovery
and run e2fsck to undo deduplication. The e2fsck binary is copied from
the system partition into tmpfs, and the system partition is unmounted
so e2fsck can run safely.
Bug: 64109868
Test: recovery with --fsck_unshare_blocks; adb remount
Change-Id: I7558749b018b58f3c4339e51a95831dbd5be1ae3
diff --git a/recovery.cpp b/recovery.cpp
index 56b2567..98cbfed 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -55,6 +55,7 @@
#include "adb_install.h"
#include "common.h"
#include "device.h"
+#include "fsck_unshare_blocks.h"
#include "fuse_sdcard_provider.h"
#include "fuse_sideload.h"
#include "install.h"
@@ -969,6 +970,7 @@
[](const std::string& arg) { return const_cast<char*>(arg.c_str()); });
static constexpr struct option OPTIONS[] = {
+ { "fsck_unshare_blocks", no_argument, nullptr, 0 },
{ "just_exit", no_argument, nullptr, 'x' },
{ "locale", required_argument, nullptr, 0 },
{ "prompt_and_wipe_data", no_argument, nullptr, 0 },
@@ -997,6 +999,7 @@
bool sideload_auto_reboot = false;
bool just_exit = false;
bool shutdown_after = false;
+ bool fsck_unshare_blocks = false;
int retry_count = 0;
bool security_update = false;
std::string locale;
@@ -1014,7 +1017,9 @@
break;
case 0: {
std::string option = OPTIONS[option_index].name;
- if (option == "locale") {
+ if (option == "fsck_unshare_blocks") {
+ fsck_unshare_blocks = true;
+ } else if (option == "locale") {
// Handled in recovery_main.cpp
} else if (option == "prompt_and_wipe_data") {
should_prompt_and_wipe_data = true;
@@ -1181,6 +1186,10 @@
if (sideload_auto_reboot) {
ui->Print("Rebooting automatically.\n");
}
+ } else if (fsck_unshare_blocks) {
+ if (!do_fsck_unshare_blocks()) {
+ status = INSTALL_ERROR;
+ }
} else if (!just_exit) {
// If this is an eng or userdebug build, automatically turn on the text display if no command
// is specified. Note that this should be called before setting the background to avoid