From: Lennart Poettering Date: Mon, 13 Apr 2026 15:57:10 +0000 (+0200) Subject: stat-util: add vfs_free_bytes() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7e8882a96fdfcfd863beffadac494038387453c2;p=thirdparty%2Fsystemd.git 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. --- 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