From 53eb316e26a1772877940e2ccfe9d3e8959a7a6e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 8 Oct 2026 07:54:55 +0900 Subject: [PATCH] TEST-17-UDEV: fix the device watch test - Match the watch rules against the root block device's kernel name instead of a hard-coded 'sda', which is not portable (e.g. 'vda' on virtio). - The nowatch check used 'test ! -e', but the watch symlinks form a bidirectional (circular) pair (ID -> wd -> ID), so dereferencing them with -e always fails with ELOOP and 'test ! -e' always succeeds, regardless of whether the watch is still present. Use '(! test -L ...)', which does not dereference the symlink. - Drop never worked checks for the 1st and 2nd invocations. - Drop unnecessary 'function' keyword. - Drop unnecessary 00-debug.rules. - Fix broken drop-in config file. - Restart udevd after the drop-in config file. - Trigger block devices after rules change to restore the original watches. - Also verify that the device's inode is listed in the inotify fd's fdinfo. (cherry picked from commit 8bcd2c8ee03b16ed84b5f5554c02a3bf2e900587) --- test/units/TEST-17-UDEV.watch.sh | 81 ++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/test/units/TEST-17-UDEV.watch.sh b/test/units/TEST-17-UDEV.watch.sh index 189a2d5561..43822e7291 100755 --- a/test/units/TEST-17-UDEV.watch.sh +++ b/test/units/TEST-17-UDEV.watch.sh @@ -8,7 +8,7 @@ set -o pipefail # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh -function check_validity() { +check_validity() { local f ID_OR_HANDLE for f in /run/udev/watch/*; do @@ -22,7 +22,7 @@ function check_validity() { done } -function check() { +check() { for _ in {1..2}; do systemctl reset-failed systemd-udevd.service systemctl restart systemd-udevd.service @@ -52,32 +52,56 @@ function check() { done } -# Check if the first invocation (should be in initrd) pushed the inotify fd to fdstore, -# and the next invocation gained the fd from service manager. -# TNote the service may be started without generating debugging logs. Let's check failure log. -if ! journalctl -n 1 -q -u systemd-udevd.service --invocation=1 --grep 'Pushed inotify fd to service manager.'; then - assert_eq "$(journalctl -n 1 -q -u systemd-udevd.service --invocation=1 --grep 'Failed to push inotify fd to service manager.' || :)" "" -fi -if ! journalctl -n 1 -q -u systemd-udevd.service --invocation=2 --grep 'Received inotify fd \(\d+\) from service manager.'; then - assert_eq "$(journalctl -n 1 -q -u systemd-udevd.service --invocation=2 --grep 'Pushed inotify fd to service manager.' || :)" "" -fi +udevd_inotify_fdinfo() { + local pid fd + + # Print the path of systemd-udevd's inotify group fdinfo. + + pid="$(systemctl show --property MainPID --value systemd-udevd.service)" + [[ "${pid:-0}" -gt 0 ]] || return 1 + + for fd in /proc/"$pid"/fd/*; do + if [[ "$(readlink "$fd" 2>/dev/null)" == "anon_inode:inotify" ]]; then + echo "/proc/$pid/fdinfo/${fd##*/}" + return 0 + fi + done + + return 1 +} + +device_is_watched() { + local devnode="${1:?}" + local ino fdinfo + + fdinfo="$(udevd_inotify_fdinfo)" || exit 1 + ino="$(printf '%x' "$(stat -c '%i' "$devnode")")" + grep -qE "^inotify wd:[0-9a-f]+ ino:${ino} " "$fdinfo" +} + +device_is_watched_by_link() { + local devnode="${1:?}" + local id + + id="$(udevadm info "$devnode" | awk '$1 == "J:" { print $2 }')" + test -L "/run/udev/watch/${id}" +} mkdir -p /run/systemd/system/systemd-udevd.service.d/ cat >/run/systemd/system/systemd-udevd.service.d/10-debug.conf </run/udev/rules.d/00-debug.rules </run/udev/rules.d/50-testsuite.rules </run/udev/rules.d/99-testsuite.rules </run/udev/rules.d/50-testsuite.rules </run/udev/rules.d/99-testsuite.rules <