From 7e8882a96fdfcfd863beffadac494038387453c2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 13 Apr 2026 17:57:10 +0200 Subject: [PATCH] stat-util: add vfs_free_bytes() The casts and the right fields to multiply aren't entirely trivial, let's add a helper for it. --- src/basic/stat-util.c | 17 +++++++++++++++++ src/basic/stat-util.h | 2 ++ src/coredump/coredump-submit.c | 6 +++--- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 06634b7df60..e0dc59a863b 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -898,3 +898,20 @@ mode_t inode_type_from_string(const char *s) { return MODE_INVALID; } + +int vfs_free_bytes(int fd, uint64_t *ret) { + assert(fd >= 0); + assert(ret); + + /* Safely returns the current available disk space (for root, i.e. including any space reserved for + * root) of the disk referenced by the fd, converted to bytes. */ + + struct statvfs sv; + if (fstatvfs(fd, &sv) < 0) + return -errno; + + if (!MUL_SAFE(ret, (uint64_t) sv.f_frsize, (uint64_t) sv.f_bfree)) + return -ERANGE; + + return 0; +} diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index ec04a2b80cd..de9ee03f440 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -161,3 +161,5 @@ static inline bool inode_type_can_hardlink(mode_t m) { * type). */ return IN_SET(m & S_IFMT, S_IFSOCK, S_IFLNK, S_IFREG, S_IFBLK, S_IFCHR, S_IFIFO); } + +int vfs_free_bytes(int fd, uint64_t *ret); diff --git a/src/coredump/coredump-submit.c b/src/coredump/coredump-submit.c index 6ce03cdec07..42d92a32e9c 100644 --- a/src/coredump/coredump-submit.c +++ b/src/coredump/coredump-submit.c @@ -305,7 +305,6 @@ static int save_external_coredump( if (storage_on_tmpfs && config->compress) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; uint64_t cgroup_limit = UINT64_MAX; - struct statvfs sv; /* If we can't get the cgroup limit, just ignore it, but don't fail, * try anyway with the config settings. */ @@ -335,8 +334,9 @@ static int save_external_coredump( /* tmpfs might get full quickly, so check the available space too. But don't worry about * errors here, failing to access the storage location will be better logged when writing to * it. */ - if (fstatvfs(fd, &sv) >= 0) - max_size = MIN((uint64_t)sv.f_frsize * (uint64_t)sv.f_bfree, max_size); + uint64_t free_bytes; + if (vfs_free_bytes(fd, &free_bytes) >= 0) + max_size = MIN(free_bytes, max_size); /* Impose a lower minimum, otherwise we will miss the basic headers. */ max_size = MAX(PROCESS_SIZE_MIN, max_size); /* Ensure we can always switch to compressing on the fly in case we are running out of space -- 2.47.3