Merge "gsid: Add a command-line option for verifying image maps."
diff --git a/OWNERS b/OWNERS
index 8a0a10e..09f4d71 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 30545
dvander@google.com
sspatil@google.com
elsk@google.com
diff --git a/gsi_service.cpp b/gsi_service.cpp
index 98963ef..c7b3a28 100644
--- a/gsi_service.cpp
+++ b/gsi_service.cpp
@@ -155,13 +155,34 @@
binder::Status GsiService::closeInstall(int* _aidl_return) {
ENFORCE_SYSTEM;
std::lock_guard<std::mutex> guard(lock_);
+
+ installer_ = {};
+
auto dsu_slot = GetDsuSlot(install_dir_);
std::string file = GetCompleteIndication(dsu_slot);
if (!WriteStringToFile("OK", file)) {
PLOG(ERROR) << "write failed: " << file;
- *_aidl_return = INSTALL_ERROR_GENERIC;
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
}
- *_aidl_return = INSTALL_OK;
+
+ // Create installation complete marker files, but set disabled immediately.
+ if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
+ PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
+ }
+ RestoreconMetadataFiles();
+
+ // DisableGsi() creates the DSU install status file and mark it as "disabled".
+ if (!DisableGsi()) {
+ PLOG(ERROR) << "cannot write DSU status file: " << kDsuInstallStatusFile;
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
+ }
+
+ SetProperty(kGsiInstalledProp, "1");
+ *_aidl_return = IGsiService::INSTALL_OK;
return binder::Status::ok();
}
@@ -217,7 +238,8 @@
return binder::Status::ok();
}
// It is important to not reset |installer_| here because other methods such
- // as enableGsi() relies on the state of |installer_|.
+ // as isGsiInstallInProgress() relies on the state of |installer_|.
+ // TODO: Maybe don't do this, use a dedicated |in_progress_| flag?
*_aidl_return = installer_->FinishInstall();
return binder::Status::ok();
}
@@ -303,6 +325,7 @@
}
binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
+ ENFORCE_SYSTEM_OR_SHELL;
std::lock_guard<std::mutex> guard(lock_);
if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) {
@@ -311,22 +334,14 @@
return binder::Status::ok();
}
RestoreconMetadataFiles();
+
if (installer_) {
- ENFORCE_SYSTEM;
- installer_ = {};
- // Note: create the install status file last, since this is the actual boot
- // indicator.
- if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
- *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
- } else {
- *_aidl_return = INSTALL_OK;
- }
- } else {
- ENFORCE_SYSTEM_OR_SHELL;
- *_aidl_return = ReenableGsi(one_shot);
+ LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?";
+ *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
+ return binder::Status::ok();
}
- installer_ = nullptr;
+ *_aidl_return = ReenableGsi(one_shot);
return binder::Status::ok();
}
@@ -516,12 +531,12 @@
if (statvfs(install_dir_.c_str(), &info)) {
PLOG(ERROR) << "Could not statvfs(" << install_dir_ << ")";
} else {
- // Keep the storage device at least 40% free, plus 1% for jitter.
- constexpr int jitter = 1;
- const uint64_t reserved_blocks =
- static_cast<uint64_t>(info.f_blocks) * (kMinimumFreeSpaceThreshold + jitter) / 100;
- if (info.f_bavail > reserved_blocks) {
- size = (info.f_bavail - reserved_blocks) * info.f_frsize;
+ uint64_t free_space = static_cast<uint64_t>(info.f_bavail) * info.f_frsize;
+ const auto free_space_threshold =
+ PartitionInstaller::GetMinimumFreeSpaceThreshold(install_dir_);
+ if (free_space_threshold.has_value() && free_space > *free_space_threshold) {
+ // Round down to multiples of filesystem block size.
+ size = (free_space - *free_space_threshold) / info.f_frsize * info.f_frsize;
}
}
@@ -530,7 +545,7 @@
return binder::Status::ok();
}
-bool GsiService::CreateInstallStatusFile() {
+bool GsiService::ResetBootAttemptCounter() {
if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
PLOG(ERROR) << "write " << kDsuInstallStatusFile;
return false;
@@ -936,13 +951,7 @@
LOG(ERROR) << "GSI is not currently disabled";
return INSTALL_ERROR_GENERIC;
}
- if (IsGsiRunning()) {
- if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
- return IGsiService::INSTALL_ERROR_GENERIC;
- }
- return IGsiService::INSTALL_OK;
- }
- if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
+ if (!SetBootMode(one_shot) || !ResetBootAttemptCounter()) {
return IGsiService::INSTALL_ERROR_GENERIC;
}
return IGsiService::INSTALL_OK;
diff --git a/gsi_service.h b/gsi_service.h
index a6b3389..0ec7620 100644
--- a/gsi_service.h
+++ b/gsi_service.h
@@ -101,7 +101,11 @@
enum class AccessLevel { System, SystemOrShell };
binder::Status CheckUid(AccessLevel level = AccessLevel::System);
- bool CreateInstallStatusFile();
+
+ // Mark install completion, and reset boot attempt counter.
+ // Next boot will try to boot into DSU.
+ bool ResetBootAttemptCounter();
+
bool SetBootMode(bool one_shot);
static android::wp<GsiService> sInstance;
diff --git a/libgsi_private.h b/libgsi_private.h
index 82814a9..51c7915 100644
--- a/libgsi_private.h
+++ b/libgsi_private.h
@@ -28,8 +28,5 @@
static constexpr char kInstallStatusWipe[] = "wipe";
static constexpr char kInstallStatusDisabled[] = "disabled";
-// We are looking for /data to have at least 40% free space.
-static constexpr uint32_t kMinimumFreeSpaceThreshold = 40;
-
} // namespace gsi
} // namespace android
diff --git a/partition_installer.cpp b/partition_installer.cpp
index 79af71a..5450169 100644
--- a/partition_installer.cpp
+++ b/partition_installer.cpp
@@ -22,9 +22,11 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/ext4_utils.h>
+#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <libdm/dm.h>
#include <libgsi/libgsi.h>
+#include <liblp/partition_opener.h>
#include "file_paths.h"
#include "gsi_service.h"
@@ -127,17 +129,18 @@
// This is the same as android::vold::GetFreebytes() but we also
// need the total file system size so we open code it here.
uint64_t free_space = static_cast<uint64_t>(sb.f_bavail) * sb.f_frsize;
- uint64_t fs_size = static_cast<uint64_t>(sb.f_blocks) * sb.f_frsize;
if (free_space <= (size_)) {
LOG(ERROR) << "not enough free space (only " << free_space << " bytes available)";
return IGsiService::INSTALL_ERROR_NO_SPACE;
}
- // We are asking for 40% of the /data to be empty.
- // TODO: may be not hard code it like this
- double free_space_percent = ((1.0 * free_space) / fs_size) * 100;
- if (free_space_percent < kMinimumFreeSpaceThreshold) {
- LOG(ERROR) << "free space " << static_cast<uint64_t>(free_space_percent)
- << "% is below the minimum threshold of " << kMinimumFreeSpaceThreshold << "%";
+
+ const auto free_space_threshold = GetMinimumFreeSpaceThreshold(install_dir_);
+ if (!free_space_threshold.has_value()) {
+ return IGsiService::INSTALL_ERROR_GENERIC;
+ }
+ if (free_space < size_ + *free_space_threshold) {
+ LOG(ERROR) << "post-installation free space (" << free_space << " - " << size_
+ << ") would be below the minimum threshold of " << *free_space_threshold;
return IGsiService::INSTALL_ERROR_FILE_SYSTEM_CLUTTERED;
}
return IGsiService::INSTALL_OK;
@@ -345,5 +348,23 @@
return IGsiService::INSTALL_OK;
}
+std::optional<uint64_t> PartitionInstaller::GetMinimumFreeSpaceThreshold(
+ const std::string& install_dir) {
+ // No need to retain any space if we were not installing to the internal storage.
+ if (!android::base::StartsWith(install_dir, "/data"s)) {
+ return 0;
+ }
+ // Dynamic Partitions device must have a "super" block device.
+ BlockDeviceInfo info;
+ PartitionOpener opener;
+ if (!opener.GetInfo(fs_mgr_get_super_partition_name(), &info)) {
+ // We shouldn't reach here, but handle it just in case.
+ LOG(ERROR) << "could not get block device info of super";
+ return std::nullopt;
+ }
+ // Reserve |super partition| of storage space so we don't disable VAB.
+ return info.size;
+}
+
} // namespace gsi
} // namespace android
diff --git a/partition_installer.h b/partition_installer.h
index 920af47..1cb9535 100644
--- a/partition_installer.h
+++ b/partition_installer.h
@@ -53,6 +53,9 @@
static int WipeWritable(const std::string& active_dsu, const std::string& install_dir,
const std::string& name);
+ // Returns the minimum free space to reserve for /data.
+ static std::optional<uint64_t> GetMinimumFreeSpaceThreshold(const std::string& install_dir);
+
// Finish a partition installation and release resources.
// If the installation is incomplete or corrupted, the backing image would
// be cleaned up and an error code is returned.