Enhance the fault tolerance of GSID installation
The gsid may function abnormally when an installation get interrupted.
case 1.
$ gsi_tool install
... use ctrl+C to stop ...
$ gsi_tool wipe
Could not remove GSI install.
case 2
When it's interrupted. The installer destructor does not have the
the chance to run therefore it can be a resource leak because the
backing files, e.g. system_gsi and userdata_gsi are not released.
Neither can they be enabled because the IsGsiInstalled() == false.
This CL fixes cases above by making a integrity model based on
IsGsiInstalled() as an atomic switch, e.g.
if (IsGsiInstalled()) {
The installation must be complete and the enableGsi() must work.
} else {
All resources that have been allocated must be cleaned up.
a. Clean up methods and command must work.
b. runStartup method must do the clean up.
}
All corresponding changes are based on this model.
Bug: 140014207
Test: \
1. gsi_tool install & reboot
2. gsi_tool install & ctrl+C & gsi_tool status & gsi_tool wipe & gsi_tool status
3. gsi_tool install & ctrl+C & gsi_tool status & reboot & gsi_tool status
Change-Id: I0dcf043d65b50f0dd82eac1f428a295e94c81812
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 0f43f8b..5c9f90b 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -225,14 +225,7 @@
ENFORCE_SYSTEM_OR_SHELL;
std::lock_guard<std::mutex> guard(parent_->lock());
- // Just in case an install was left hanging.
- std::string install_dir;
- if (installer_) {
- install_dir = installer_->install_dir();
- } else {
- install_dir = GetInstalledImageDir();
- }
-
+ std::string install_dir = GetActiveInstalledImageDir();
if (IsGsiRunning()) {
// Can't remove gsi files while running.
*_aidl_return = UninstallGsi();
@@ -290,9 +283,7 @@
ENFORCE_SYSTEM;
std::lock_guard<std::mutex> guard(parent_->lock());
- if (IsGsiInstalled()) {
- *_aidl_return = GetInstalledImageDir();
- }
+ *_aidl_return = GetActiveInstalledImageDir();
return binder::Status::ok();
}
@@ -305,8 +296,8 @@
return binder::Status::ok();
}
- auto installer = std::make_unique<GsiInstaller>(this, GetInstalledImageDir());
- *_aidl_return = installer->WipeUserdata();
+ std::string install_dir = GetActiveInstalledImageDir();
+ *_aidl_return = GsiInstaller::WipeWritable(install_dir, "userdata");
return binder::Status::ok();
}
@@ -550,6 +541,15 @@
return INSTALL_OK;
}
+std::string GsiService::GetActiveInstalledImageDir() {
+ // Just in case an install was left hanging.
+ if (installer_) {
+ return installer_->install_dir();
+ } else {
+ return GetInstalledImageDir();
+ }
+}
+
std::string GsiService::GetInstalledImageDir() {
// If there's no install left, just return /data/gsi since that's where
// installs go by default.
@@ -576,8 +576,7 @@
return INSTALL_ERROR_GENERIC;
}
- installer_ = std::make_unique<GsiInstaller>(this, GetInstalledImageDir());
- return installer_->ReenableGsi(one_shot);
+ return GsiInstaller::ReenableGsi(one_shot);
}
bool GsiService::RemoveGsiFiles(const std::string& install_dir, bool wipeUserdata) {
@@ -587,9 +586,11 @@
for (auto&& image : images) {
if (!android::base::EndsWith(image, "_gsi")) {
continue;
- } else if (!android::base::StartsWith(image, "userdata")) {
- ok &= manager->DeleteBackingImage(image);
- } else if (wipeUserdata) {
+ }
+ if (manager->IsImageMapped(image)) {
+ ok &= manager->UnmapImageDevice(image);
+ }
+ if (!android::base::StartsWith(image, "userdata") || wipeUserdata) {
ok &= manager->DeleteBackingImage(image);
}
}
@@ -626,8 +627,16 @@
return true;
}
+void GsiService::CleanCorruptedInstallation() {
+ auto install_dir = GetInstalledImageDir();
+ if (!RemoveGsiFiles(install_dir, true)) {
+ LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << install_dir;
+ }
+}
+
void GsiService::RunStartupTasks() {
if (!IsGsiInstalled()) {
+ CleanCorruptedInstallation();
return;
}