Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c277195 authored by Richard Chang's avatar Richard Chang
Browse files

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
parent 196a8023
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/swap.h>
#include <sys/types.h>
#include <sys/utsname.h>
@@ -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<uint64_t>("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<uint64_t>(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;
    }