From 645cdedb2fe69c57fc10df7efe933cbdcadfb8aa Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Fri, 12 Feb 2021 02:10:58 +0800 Subject: gsid: suggestScratchSize() respect kMinimumFreeSpaceThreshold gsid should take kMinimumFreeSpaceThreshold into account when calculating the suggested scratch partition size. Also use uint64_t to store any calculated intermediate result, so we can stay confortable from overflowing, and downcast the result to int64_t in the end, after we clamped the value within int64_t range. Bug: 165925766 Bug: 179980369 Test: Install DSU and verify adb remount works Change-Id: I919c723369d7d788c5c83a19e6b87f077fb2521b --- gsi_service.cpp | 18 +++++++++++------- libgsi_private.h | 3 +++ partition_installer.cpp | 4 ---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/gsi_service.cpp b/gsi_service.cpp index cc6497a..66e01ee 100644 --- a/gsi_service.cpp +++ b/gsi_service.cpp @@ -510,20 +510,24 @@ binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_ret binder::Status GsiService::suggestScratchSize(int64_t* _aidl_return) { ENFORCE_SYSTEM; - static constexpr int64_t kMinScratchSize = 512_MiB; - static constexpr int64_t kMaxScratchSize = 2_GiB; + static constexpr uint64_t kMinScratchSize = 512_MiB; + static constexpr uint64_t kMaxScratchSize = 2_GiB; - int64_t size = 0; + uint64_t size = 0; struct statvfs info; if (statvfs(install_dir_.c_str(), &info)) { PLOG(ERROR) << "Could not statvfs(" << install_dir_ << ")"; } else { - const int64_t available_space = static_cast(info.f_bavail) * info.f_frsize; - LOG(INFO) << "Available space of " << install_dir_ << ": " << available_space; - // Use up to half of free space. Don't exhaust the storage device with scratch partition. - size = available_space / 2; + // Keep the storage device at least 40% free, plus 1% for jitter. + constexpr int jitter = 1; + const uint64_t reserved_blocks = + static_cast(info.f_blocks) * (kMinimumFreeSpaceThreshold + jitter) / 100; + if (info.f_bavail > reserved_blocks) { + size = (info.f_bavail - reserved_blocks) * info.f_frsize; + } } + // We can safely downcast the result here, since we clamped the result within int64_t range. *_aidl_return = std::clamp(size, kMinScratchSize, kMaxScratchSize); return binder::Status::ok(); } diff --git a/libgsi_private.h b/libgsi_private.h index 51c7915..82814a9 100644 --- a/libgsi_private.h +++ b/libgsi_private.h @@ -28,5 +28,8 @@ static constexpr char kInstallStatusOk[] = "ok"; 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 35ac884..fea1483 100644 --- a/partition_installer.cpp +++ b/partition_installer.cpp @@ -39,10 +39,6 @@ using namespace android::fiemap; using namespace android::fs_mgr; using android::base::unique_fd; -// The default size of userdata.img for GSI. -// We are looking for /data to have atleast 40% free space -static constexpr uint32_t kMinimumFreeSpaceThreshold = 40; - PartitionInstaller::PartitionInstaller(GsiService* service, const std::string& install_dir, const std::string& name, const std::string& active_dsu, int64_t size, bool read_only) -- cgit v1.2.3 From 23a996fde114247e6f2f67df37d955a640e9775b Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Fri, 12 Feb 2021 01:57:44 +0800 Subject: Explicitly cast to 64bit integer when calculating filesystem size Else the result may overflow on platforms that have 32bit long. Bug: 179980369 Test: Install DSU on 32bit cuttlefish and observe logcat. Test: Try installing with different userdata size and verify the calculated filesystem size. Change-Id: I50b140590972e733e0e45047b2ce8a6735d205f7 --- partition_installer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/partition_installer.cpp b/partition_installer.cpp index fea1483..79af71a 100644 --- a/partition_installer.cpp +++ b/partition_installer.cpp @@ -126,8 +126,8 @@ int PartitionInstaller::PerformSanityChecks() { // 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 = 1ULL * sb.f_bavail * sb.f_frsize; - uint64_t fs_size = sb.f_blocks * sb.f_frsize; + uint64_t free_space = static_cast(sb.f_bavail) * sb.f_frsize; + uint64_t fs_size = static_cast(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; -- cgit v1.2.3