libmount: preserve reused loop devices and request direct I/O
v2 cover libmount: preserve reused loop devices and request direct I/O
Hi Karel,
This revision addresses your review of PR #4646. The reused-device fix is now separate from the direct-I/O option.
Changes in v2:
- Add a specific diagnostic for direct-I/O mode conflicts.
- Use ul_strtobool() and the test-suite cleanup helpers.
- Document buffered-I/O fallback and how to check the effective mode.
- Add the option comment header and reused-device debug message.
- Remove the AI attribution trailer as requested.
Built mount, umount, losetup and findmnt with Meson. As root in a private mount namespace, loop-reuse, loop-direct-io, regfile and fstab-loop all passed. The direct-I/O test also checks boolean aliases and the conflict diagnostic.
Thanks,
Tianyi
Tianyi Chen (2):
libmount: keep reused loop devices attached on mount failure
libmount: support explicit loop direct I/O requests
libmount/src/hook_loopdev.c | 41 +++++++++++++- sys-utils/mount.8.adoc | 13 ++++- tests/expected/mount/loop-direct-io | 6 +++ tests/expected/mount/loop-reuse | 1 + tests/ts/mount/loop-direct-io | 84 +++++++++++++++++++++++++++++ tests/ts/mount/loop-reuse | 23 ++++++++ 6 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 tests/expected/mount/loop-direct-io create mode 100644 tests/expected/mount/loop-reuse create mode 100755 tests/ts/mount/loop-direct-io create mode 100755 tests/ts/mount/loop-reuse
base-commit: 55e3c4dba6101a47ecaae71c91edbe10c59b8d56
Signature · 1 line
2.55.0
PATCH v2 1/2 libmount: keep reused loop devices attached on mount failure
A loop device found by overlap detection may have been set up by the caller. Do not detach it when a later mount step fails; only close the reference acquired by this mount.
Add a regression test using a preconfigured device and an invalid filesystem option.
--- libmount/src/hook_loopdev.c | 7 +++++++ tests/expected/mount/loop-reuse | 1 + tests/ts/mount/loop-reuse | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/expected/mount/loop-reuse create mode 100755 tests/ts/mount/loop-reuse
libmount/src/hook_loopdev.c +7 -0
@@ -21,6 +21,7 @@struct hook_data {int loopdev_fd; +bool reused; };static int delete_loopdev (struct libmnt_context *cxt,struct hook_data *hd);
@@ -350,6 +351,7 @@ static int setup_loopdev(struct libmnt_context *cxt, }while (1 ); success: + hd->reused = reuse;if (!rc) rc =mnt_fs_set_source (cxt->fs,loopcxt_get_device (&lc));
@@ -408,6 +410,11 @@ static int delete_loopdev(struct libmnt_context *cxt, struct hook_data *hd) hd->loopdev_fd =-1 ; } +if (hd && hd->reused) { +DBG_OBJ (LOOP , cxt,ul_debug ("keeping reused device" )); +return 0 ; + } + rc =loopdev_detach (src);/* see lib/loopdev.c */ DBG_OBJ (LOOP , cxt,ul_debug ("deleted [rc=%d]" , rc));
tests/expected/mount/loop-reuse new file +1 -0
@@ -0,0 +1 @@ +reused device preserved: OK
tests/ts/mount/loop-reuse new file +23 -0
@@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-2.0-or-later + +TS_TOPDIR="${0%/*}/../.." +TS_DESC="keep reused loop device on failure" + +. "$TS_TOPDIR"/functions.sh +ts_init "$*" +ts_check_test_command "$TS_CMD_MOUNT" +ts_check_test_command "$TS_CMD_UMOUNT" +ts_skip_nonroot +ts_check_losetup +ts_check_prog "mkfs.ext2" + +ts_device_init +mkfs.ext2 -F "$TS_LODEV" &> /dev/null || ts_die "Cannot make filesystem" +mkdir -p "$TS_MOUNTPOINT" +$TS_CMD_MOUNT -t ext2 -o loop,invalid-fs-option "$TS_OUTDIR/$TS_TESTNAME.img" \ + "$TS_MOUNTPOINT" &> /dev/null && ts_die "Accepted invalid filesystem option" +[ "$($TS_CMD_LOSETUP -j "$TS_OUTDIR/$TS_TESTNAME.img" | cut -d: -f1)" = "$TS_LODEV" ] || + ts_die "Failed mount detached reused device" +ts_log "reused device preserved: OK" +ts_finalize
Signature · 1 line
2.55.0
PATCH v2 2/2 libmount: support explicit loop direct I/O requests
In reply to Tianyi ChenAllow X-loopdev.direct-io=on|off to select the direct I/O mode when mounting a file through a loop device. Pass the flag to the existing loop setup path and require a matching mode when reusing a device. Omitting the option preserves the current behavior.
Add an explicit diagnostic for direct I/O mode conflicts and document that the option is a request whose result should be checked with losetup. Parse the boolean with ul_strtobool and cover the option with the standard loop-device test cleanup helpers.
--- libmount/src/hook_loopdev.c | 34 +++++++++++- sys-utils/mount.8.adoc | 13 ++++- tests/expected/mount/loop-direct-io | 6 +++ tests/ts/mount/loop-direct-io | 84 +++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 3 deletions(-) create mode 100644 tests/expected/mount/loop-direct-io create mode 100755 tests/ts/mount/loop-direct-io
libmount/src/hook_loopdev.c +32 -2
@@ -139,7 +139,7 @@ static int setup_loopdev(struct libmnt_context *cxt, {const char *backing_file, *loopdev =NULL ;struct loopdev_cxt lc; -int rc =0 , lo_flags =0 ; +int rc =0 , lo_flags =0 , direct_io =-1 ;uint64_t offset =0 , sizelimit =0 ;bool reuse = FALSE;struct libmnt_opt *opt, *loopopt =NULL ;
@@ -155,6 +155,23 @@ static int setup_loopdev(struct libmnt_context *cxt, lo_flags |=LO_FLAGS_READ_ONLY ; } +/* +* X-loopdev.direct-io= +*/ + opt =mnt_optlist_get_named (ol,"X-loopdev.direct-io" , cxt->map_userspace); +if (opt) { +const char *value =mnt_opt_get_value (opt); +bool enabled; + +if (ul_strtobool (value, &enabled) !=0 ) { + rc = -MNT_ERR_MOUNTOPT ; + goto done_no_deinit; + } + direct_io = enabled; +if (enabled) + lo_flags |=LO_FLAGS_DIRECT_IO ; + } +/* * loop= */
@@ -258,6 +275,18 @@ static int setup_loopdev(struct libmnt_context *cxt, goto done; } +if (direct_io !=-1 && !!loopcxt_is_dio (&lc) != direct_io) { +const char *dev =loopcxt_get_device (&lc); + +DBG_OBJ (LOOP , cxt,ul_debug ("%s has incompatible direct I/O mode" , + dev)); +/* TRANSLATORS: Do not translate "e ". It is a message classifier. */ +mnt_context_sprintf_mesg (cxt, +_ ("e loop device %s has incompatible direct I/O mode" ), dev); + rc = -MNT_ERR_LOOPOVERLAP ; + goto done; + } +/* This is no more supported, but check to be safe. */ if (loopcxt_get_encrypt_type (&lc, &lc_encrypt_type) ==0 && lc_encrypt_type !=LO_CRYPT_NONE ) {
@@ -454,7 +483,8 @@ static int is_loopdev_required(struct libmnt_context *cxt, struct libmnt_optlistreturn 0 ;/* loop= (sizelimit= or offset=) explicitly specified */ -if (flags & (MNT_MS_LOOP |MNT_MS_OFFSET |MNT_MS_SIZELIMIT )) { +if (flags & (MNT_MS_LOOP |MNT_MS_OFFSET |MNT_MS_SIZELIMIT ) + ||mnt_optlist_get_named (ol,"X-loopdev.direct-io" , cxt->map_userspace)) {DBG_OBJ (LOOP , cxt,ul_debug ("loopdev specific options detected" ));return 1 ; }
sys-utils/mount.8.adoc +12 -1
@@ -796,6 +796,17 @@ ____ mount -t auto -o'X-mount.auto-fstypes="noext2,ext3"' /dev/sdc1 /mnt/test ____ +*X-loopdev.direct-io*=*on*|*off*:: +Request enabling or disabling direct I/O when setting up a loop device. The +kernel may fall back to buffered I/O, for example when the backing file +offset is unaligned or the block size is too small. Direct I/O is a request, +not a guarantee; check the effective mode with *losetup --list -O NAME,DIO*. If a loop device already exists for +the same file, offset and size limit, its direct I/O mode must match; otherwise +the mount fails without changing the existing device. Without this option, new +loop devices use buffered I/O and existing devices can be reused in either +mode. This option does not change an existing mount or apply when no loop +device is needed. See also *losetup*(8) *--direct-io*. + *X-mount.mkdir*[**=**_mode_]:: Allow to make a target directory (mountpoint) if it does not exist yet. The optional argument _mode_ specifies the filesystem access mode used for *mkdir*(2) in octal notation. The default mode is 0755. This functionality is supported only for root users or when *mount* is executed without suid permissions. The option is also supported as *x-mount.mkdir*, but this notation is deprecated since v2.30. See also *--mkdir* command line option.
@@ -1708,7 +1719,7 @@ ____ *mount -t ext4 /tmp/disk.img /mnt* ____ -This type of mount knows about three options, namely *loop*, *offset* and *sizelimit*, that are really options to *losetup*(8). (These options can be used in addition to those specific to the filesystem type.) +Loop device setup accepts *loop*, *offset*, *sizelimit* and *X-loopdev.direct-io*, corresponding to options of *losetup*(8). (These options can be used in addition to those specific to the filesystem type.) Since Linux 2.6.25 auto-destruction of loop devices is supported, meaning that any loop device allocated by *mount* will be freed by *umount* independently of _/etc/mtab_.
tests/expected/mount/loop-direct-io new file +6 -0
@@ -0,0 +1,6 @@ +invalid options: OK +new device (on): OK +new device (off): OK +new device (default): OK +reuse and failed mount (on): OK +reuse and failed mount (off): OK
tests/ts/mount/loop-direct-io new file +84 -0
84 lines not on this page · raw message
Signature · 1 line
2.55.0