adb remount -R should enable DSU if suitable

If executing `adb remount -R` and DSU is running but disabled, then
enable the DSU (one-shot mode) so that the reboot afterwards would stay
within the DSU guest system.
Normally reboot within a DSU guest system would bring the device back to
the host system. However when doing adb remount -R, we actually doesn't
want to exit DSU, but wish to reboot back into DSU guest system again
with remount machinery (overlayfs) properly set up.

Also sort the header include order.

Bug: 165925766
Test: Within a DSU guest system, DSU disabled, adb remount -R
  => After reboot, system is DSU and overlayfs is mounted
Test: adb-remount-test.sh within DSU guest system
Change-Id: I72a7a568e985b183d357ae6e1a7d0113e9921200
This commit is contained in:
Yo Chiang 2021-01-21 18:14:47 +08:00
parent f5835fa714
commit d542910553
2 changed files with 43 additions and 3 deletions

View File

@ -170,6 +170,7 @@ cc_binary {
defaults: ["fs_mgr_defaults"],
static_libs: [
"libavb_user",
"libgsid",
"libutils",
"libvold_binder",
],

View File

@ -16,7 +16,6 @@
#include <errno.h>
#include <getopt.h>
#include <libavb_user/libavb_user.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/types.h>
@ -40,6 +39,8 @@
#include <fs_mgr_overlayfs.h>
#include <fs_mgr_priv.h>
#include <fstab/fstab.h>
#include <libavb_user/libavb_user.h>
#include <libgsi/libgsid.h>
namespace {
@ -52,7 +53,9 @@ namespace {
"\tpartition\tspecific partition(s) (empty does all)\n"
"\n"
"Remount specified partition(s) read-write, by name or mount point.\n"
"-R notwithstanding, verity must be disabled on partition(s).";
"-R notwithstanding, verity must be disabled on partition(s).\n"
"-R within a DSU guest system reboots into the DSU instead of the host system,\n"
"this command would enable DSU (one-shot) if not already enabled.";
::exit(exit_status);
}
@ -137,7 +140,8 @@ enum RemountStatus {
REMOUNT_FAILED,
MUST_REBOOT,
BINDER_ERROR,
CHECKPOINTING
CHECKPOINTING,
GSID_ERROR,
};
static int do_remount(int argc, char* argv[]) {
@ -340,6 +344,41 @@ static int do_remount(int argc, char* argv[]) {
++it;
}
// If (1) remount requires a reboot to take effect, (2) system is currently
// running a DSU guest and (3) DSU is disabled, then enable DSU so that the
// next reboot would not take us back to the host system but stay within
// the guest system.
if (reboot_later) {
if (auto gsid = android::gsi::GetGsiService()) {
auto dsu_running = false;
if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
LOG(ERROR) << "Failed to get DSU running state: " << status;
return BINDER_ERROR;
}
auto dsu_enabled = false;
if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
LOG(ERROR) << "Failed to get DSU enabled state: " << status;
return BINDER_ERROR;
}
if (dsu_running && !dsu_enabled) {
std::string dsu_slot;
if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
LOG(ERROR) << "Failed to get active DSU slot: " << status;
return BINDER_ERROR;
}
LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
"DSU guest system after reboot";
int error = 0;
if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error);
!status.isOk() || error != android::gsi::IGsiService::INSTALL_OK) {
LOG(ERROR) << "Failed to enable DSU: " << status << ", error code: " << error;
return !status.isOk() ? BINDER_ERROR : GSID_ERROR;
}
LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
}
}
}
if (partitions.empty() || just_disabled_verity) {
if (reboot_later) reboot(setup_overlayfs);
if (user_please_reboot_later) {