From: Yu Watanabe Date: Fri, 21 Jul 2023 01:26:13 +0000 (+0900) Subject: udev: re-introduce symlinks for loopback block device X-Git-Tag: v255-rc1~776 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a05926fbe6ed92e60e0afc9857ced91a532f791;p=thirdparty%2Fsystemd.git udev: re-introduce symlinks for loopback block device But the directories are changed from /dev/loop/by-ref/ -> /dev/disk/by-loop-ref/ and /dev/loop/by-inode/ -> /dev/disk/by-loop-inode/. As /dev/loop/ is used by losetup command for other purpose. See issue #28475. This effectively reverts commits 9915cc60868c77e7e8cecb669ddb90516dffc7df, 5022fab15fc16204d163883ca818fd6092dc919c, and c0d998248e10e1dcf18108fdbb70f259acd452eb. --- diff --git a/NEWS b/NEWS index e369b60af29..6492b713f36 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,23 @@ CHANGES WITH 255 in spe: by default when combined with --scope, will be changed in a future release to be enabled by default. + Device Management: + + * udev will now create symlinks to loopback block devices in the + /dev/disk/by-loop-ref/ directory that are based on the .lo_file_name + string field selected during allocation. The systemd-dissect tool and + the util-linux losetup command now supports a complementing new + switch --loop-ref= for selecting the string. This means a loopback + block device may now be allocated under a caller-chosen reference and + can subsequently be referenced by that without first having to look + up the block device name the caller ended up with. + + * udev also creates symlinks to loopback block devices in the + /dev/disk/by-loop-inode/ directory based on the .st_dev/st_ino fields + of the inode attached to the loopback block device. This means that + attaching a file to a loopback device will implicitly make a handle + available to be found via that file's inode information. + Network Management: * The "duid-only" option for DHCPv4 client's ClientIdentifier= setting diff --git a/man/systemd-dissect.xml b/man/systemd-dissect.xml index 9a3ed6ce7b2..27c5d3c7a84 100644 --- a/man/systemd-dissect.xml +++ b/man/systemd-dissect.xml @@ -413,7 +413,14 @@ .lo_file_name field for the block device. Note this is distinct from the /sys/class/block/loopX/loop/backing_file attribute file that always reports a path referring to the actual backing file. The latter is subject to mount namespace translation, the - former is not. + former is not. + + This setting is particularly useful in combination with the command, + as it allows later referencing the allocated loop device via + /dev/disk/by-loop-ref/… symlinks. Example: first, set up the loopback device + via systemd-dissect attach --loop-ref=quux foo.raw, and then reference it in a + command via the specified filename: cfdisk /dev/disk/by-loop-ref/quux. + diff --git a/rules.d/60-persistent-storage.rules.in b/rules.d/60-persistent-storage.rules.in index d5e0f5f705e..39a65550457 100644 --- a/rules.d/60-persistent-storage.rules.in +++ b/rules.d/60-persistent-storage.rules.in @@ -161,4 +161,13 @@ ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/ # the right device, to access specific disks in a race-free fashion) ENV{DISKSEQ}=="?*", ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}$env{.PART_SUFFIX}" +# Create symlinks that allow referencing loopback devices by their backing file's inode number +ENV{ID_LOOP_BACKING_DEVICE}!="", ENV{ID_LOOP_BACKING_INODE}!="", SYMLINK+="disk/by-loop-inode/$env{ID_LOOP_BACKING_DEVICE}-$env{ID_LOOP_BACKING_INODE}$env{.PART_SUFFIX}" + +# Similar, but uses the .lo_file_name field of the loopback device (note that +# this is basically just a free-form string passed from userspace to the kernel +# when the device is created, it is not necessarily a file system path like the +# "loop/backing_file" sysfs attribute, which is always an absolute path) +ENV{ID_LOOP_BACKING_FILENAME_ENC}!="", SYMLINK+="disk/by-loop-ref/$env{ID_LOOP_BACKING_FILENAME_ENC}$env{.PART_SUFFIX}" + LABEL="persistent_storage_end" diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 9c31d265b6f..cab8ef3e7a9 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -1156,7 +1156,11 @@ int loop_device_set_filename(LoopDevice *d, const char *name) { /* Sets the .lo_file_name of the loopback device. This is supposed to contain the path to the file * backing the block device, but is actually just a free-form string you can pass to the kernel. Most * tools that actually care for the backing file path use the sysfs attribute file loop/backing_file - * which is a kernel generated string, subject to file system namespaces and such. */ + * which is a kernel generated string, subject to file system namespaces and such. + * + * .lo_file_name is useful since userspace can select it freely when creating a loopback block + * device, and we can use it for /dev/disk/by-loop-ref/ symlinks, and similar, so that apps can + * recognize their own loopback files. */ if (name && strlen(name) >= sizeof(info.lo_file_name)) return -ENOBUFS; diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh index efdbe6ac74e..21e9c755263 100755 --- a/test/units/testsuite-50.sh +++ b/test/units/testsuite-50.sh @@ -470,6 +470,48 @@ mount -t ddi "${image}.gpt" "$T" -o ro,X-mount.mkdir,discard umount -R "$T" rmdir "$T" +LOOP="$(systemd-dissect --attach --loop-ref=waldo "${image}.raw")" + +# Wait until the symlinks we want to test are established +udevadm trigger -w "$LOOP" + +# Check if the /dev/loop/* symlinks really reference the right device +test /dev/disk/by-loop-ref/waldo -ef "$LOOP" + +if [ "$(stat -c '%Hd:%Ld' "${image}.raw")" != '?d:?d' ] ; then + # Old stat didn't know the %Hd and %Ld specifiers and turned them into ?d + # instead. Let's simply skip the test on such old systems. + test "$(stat -c '/dev/disk/by-loop-inode/%Hd:%Ld-%i' "${image}.raw")" -ef "$LOOP" +fi + +# Detach by loopback device +systemd-dissect --detach "$LOOP" + +# Test long reference name. +# Note, sizeof_field(struct loop_info64, lo_file_name) == 64, +# and --loop-ref accepts upto 63 characters, and udev creates symlink +# based on the name when it has upto _62_ characters. +name="$(for _ in {1..62}; do echo -n 'x'; done)" +LOOP="$(systemd-dissect --attach --loop-ref="$name" "${image}.raw")" +udevadm trigger -w "$LOOP" + +# Check if the /dev/disk/by-loop-ref/$name symlink really references the right device +test "/dev/disk/by-loop-ref/$name" -ef "$LOOP" + +# Detach by the /dev/disk/by-loop-ref symlink +systemd-dissect --detach "/dev/disk/by-loop-ref/$name" + +name="$(for _ in {1..63}; do echo -n 'x'; done)" +LOOP="$(systemd-dissect --attach --loop-ref="$name" "${image}.raw")" +udevadm trigger -w "$LOOP" + +# Check if the /dev/disk/by-loop-ref/$name symlink does not exist +test ! -e "/dev/disk/by-loop-ref/$name" + +# Detach by backing inode +systemd-dissect --detach "${image}.raw" +(! systemd-dissect --detach "${image}.raw") + # check for confext functionality mkdir -p /run/confexts/test/etc/extension-release.d echo "ID=_any" >/run/confexts/test/etc/extension-release.d/extension-release.test