From 6c277195abb1118a135eed284dff83f4ba3b70a6 Mon Sep 17 00:00:00 2001 From: Richard Chang Date: Thu, 18 Jul 2024 08:03:59 +0000 Subject: [PATCH] fs_mgr: check available space before creating zram backing device This CL adds a check to ensure that there is enough free space on the device before creating the zram backing device. If there is not enough space, the zram backing device will not be created. Adding a system property 'ro.zram_backing_device_min_free_mb' to define the minimum free space reserved for booting. If the property is not set, skip the available space check. Bug: 322821637 Bug: 326877642 Test: Fill up userdata, enlarge zram backing device size on next boot. Change-Id: I135b4beee2a8a21f8214f6579368a8d0d8792255 --- fs_mgr/fs_mgr.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 5156754a8..90fbd5092 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2069,11 +2070,45 @@ static bool InstallZramDevice(const std::string& device) { return true; } +/* + * Zram backing device can be created as long as /data has at least `size` + * free space, though we may want to leave some extra space for the remaining + * boot process and other system activities. + */ +static bool ZramBackingDeviceSizeAvailable(off64_t size) { + constexpr const char* data_path = "/data"; + uint64_t min_free_mb = + android::base::GetUintProperty("ro.zram_backing_device_min_free_mb", 0); + + // No min_free property. Skip the available size check. + if (min_free_mb == 0) return true; + + struct statvfs vst; + if (statvfs(data_path, &vst) < 0) { + PERROR << "Cannot check available space: " << data_path; + return false; + } + + uint64_t size_free = static_cast(vst.f_bfree) * vst.f_frsize; + uint64_t size_required = size + (min_free_mb * 1024 * 1024); + if (size_required > size_free) { + PERROR << "Free space is not enough for zram backing device: " << size_required << " > " + << size_free; + return false; + } + return true; +} + static bool PrepareZramBackingDevice(off64_t size) { constexpr const char* file_path = "/data/per_boot/zram_swap"; if (size == 0) return true; + // Check available space + if (!ZramBackingDeviceSizeAvailable(size)) { + PERROR << "No space for target path: " << file_path; + return false; + } // Prepare target path unique_fd target_fd(TEMP_FAILURE_RETRY(open(file_path, O_RDWR | O_CREAT | O_CLOEXEC, 0600))); if (target_fd.get() == -1) { @@ -2082,6 +2117,7 @@ static bool PrepareZramBackingDevice(off64_t size) { } if (fallocate(target_fd.get(), 0, 0, size) < 0) { PERROR << "Cannot truncate target path: " << file_path; + unlink(file_path); return false; }