From: nkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com> Date: Wed, 15 Oct 2025 22:12:50 +0000 (+0200) Subject: loop-util: mirror discard limits from backing device X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=29ee9c6fb7c75c421f887c8579c65eb04d4f634d;p=thirdparty%2Fsystemd.git loop-util: mirror discard limits from backing device --- diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 53d7759e2ef..690f6aeb2a7 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -375,6 +375,44 @@ static int loop_configure( return 0; } +static int fd_get_max_discard(int fd, uint64_t *ret) { + struct stat st; + char sysfs_path[STRLEN("/sys/dev/block/" ":" "/queue/discard_max_bytes") + DECIMAL_STR_MAX(dev_t) * 2 + 1]; + _cleanup_free_ char *buffer = NULL; + int r; + + assert(ret); + + if (fstat(ASSERT_FD(fd), &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -ENOTBLK; + + xsprintf(sysfs_path, "/sys/dev/block/" DEVNUM_FORMAT_STR "/queue/discard_max_bytes", DEVNUM_FORMAT_VAL(st.st_rdev)); + + r = read_one_line_file(sysfs_path, &buffer); + if (r < 0) + return r; + + return safe_atou64(buffer, ret); +} + +static int fd_set_max_discard(int fd, uint64_t max_discard) { + struct stat st; + char sysfs_path[STRLEN("/sys/dev/block/" ":" "/queue/discard_max_bytes") + DECIMAL_STR_MAX(dev_t) * 2 + 1]; + + if (fstat(ASSERT_FD(fd), &st) < 0) + return -errno; + + if (!S_ISBLK(st.st_mode)) + return -ENOTBLK; + + xsprintf(sysfs_path, "/sys/dev/block/" DEVNUM_FORMAT_STR "/queue/discard_max_bytes", DEVNUM_FORMAT_VAL(st.st_rdev)); + + return write_string_filef(sysfs_path, WRITE_STRING_FILE_DISABLE_BUFFER, "%" PRIu64, max_discard); +} + static int loop_device_make_internal( const char *path, int fd, @@ -572,6 +610,19 @@ static int loop_device_make_internal( (void) usleep_safe(usec); } + if (S_ISBLK(st.st_mode)) { + uint64_t discard_max_bytes; + + r = fd_get_max_discard(fd, &discard_max_bytes); + if (r < 0) + log_debug_errno(r, "Failed to read 'discard_max_bytes' of backing device, ignoring: %m"); + else { + r = fd_set_max_discard(d->fd, discard_max_bytes); + if (r < 0) + log_debug_errno(r, "Failed to write 'discard_max_bytes' of loop device, ignoring: %m"); + } + } + d->backing_file = TAKE_PTR(backing_file); d->backing_inode = st.st_ino; d->backing_devno = st.st_dev;