From: Danilo Krummrich Date: Mon, 14 Jun 2021 15:46:00 +0000 (+0200) Subject: udevadm: trigger: implement --initialized-match/nomatch arguments X-Git-Tag: v251-rc1~78^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F22662%2Fhead;p=thirdparty%2Fsystemd.git udevadm: trigger: implement --initialized-match/nomatch arguments systemd-udev-trigger.service by default triggeres all devices regardless of whether they were already recognized by systemd-udevd. There are machines (especially in embedded environments) where systemd-udev-trigger.service is configured to run at a later stage of the boot sequence, which can lead to quite a lot of devices being triggered although they were already recognized by systemd-udevd. Re-triggering a lot of devices is a relatively expensive operation and therefore should be avoided if unnecessary. Therefore this patch introduces --initialized-nomatch, which filters out devices that are already present in the udev database. For consistance reasons --initialized-match is implemented as well, which filters out devices that are *not* already present in the udev database. Replaces #19949. --- diff --git a/man/udevadm.xml b/man/udevadm.xml index 24ed4a29c71..af485711222 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -395,6 +395,35 @@ then each matching result is ORed, that is, all children of each specified device are triggered. + + + + + When is specified, trigger events for devices + that are already initialized by systemd-udevd, and skip devices that + are not initialized yet. + When is specified, trigger events for devices + that are not initialized by systemd-udevd yet, and skip devices that + are already initialized. + Here, initialized devices are those for which at least one udev rule already + completed execution – for any action but remove — that set a property + or other device setting (and thus has an entry in the udev device database). Devices are + no longer considered initialized if a remove action is seen for them + (which removes their entry in the udev device database). Note that devices that have no + udev rules are never considered initialized, but might still be announced via the sd-device + API (or similar). Typically, it is thus essential that applications which intend to use + such a match, make sure a suitable udev rule is installed that sets at least one property + on devices that shall be matched. + WARNING: can potentially save a significant + amount of time compared to re-triggering all devices in the system and e.g. can be used to + optimize boot time. However, this is not safe to be used in a boot sequence in general. + Especially, when udev rules for a device depend on its parent devices (e.g. + ATTRS or IMPORT{parent} keys, see + udev7 + for more details), the final state of the device becomes easily unstable with this option. + + + diff --git a/shell-completion/bash/udevadm b/shell-completion/bash/udevadm index 4d52597cbfd..23ce02365c7 100644 --- a/shell-completion/bash/udevadm +++ b/shell-completion/bash/udevadm @@ -51,7 +51,8 @@ _udevadm() { [INFO_STANDALONE]='-r --root -a --attribute-walk -x --export -e --export-db -c --cleanup-db -w --wait-for-initialization --value' [INFO_ARG]='-q --query -p --path -n --name -P --export-prefix -d --device-id-of-file --property' - [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid' + [TRIGGER_STANDALONE]='-v --verbose -n --dry-run -q --quiet -w --settle --wait-daemon --uuid + --initialized-match --initialized-nomatch' [TRIGGER_ARG]='-t --type -c --action -s --subsystem-match -S --subsystem-nomatch -a --attr-match -A --attr-nomatch -p --property-match -g --tag-match -y --sysname-match --name-match -b --parent-match diff --git a/shell-completion/zsh/_udevadm b/shell-completion/zsh/_udevadm index 8a10237e3d6..63df8b7c9ec 100644 --- a/shell-completion/zsh/_udevadm +++ b/shell-completion/zsh/_udevadm @@ -34,6 +34,8 @@ _udevadm_trigger(){ '--tag-match=property[Trigger events for devices with a matching tag.]' \ '--sysname-match=[Trigger events for devices with a matching sys device name.]' \ '--parent-match=[Trigger events for all children of a given device.]' \ + '--initialized-match[Trigger events for devices that are already initialized.]' \ + '--initialized-nomatch[Trigger events for devices that are not initialized yet.]' \ '--uuid[Print synthetic uevent UUID.]' \ '--prioritized-subsystem=[Trigger events for devices which belong to a matching subsystem earlier.]' } diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c index e4b3150e603..56921e2cc62 100644 --- a/src/udev/udevadm-trigger.c +++ b/src/udev/udevadm-trigger.c @@ -11,6 +11,7 @@ #include "device-util.h" #include "fd-util.h" #include "fileio.h" +#include "parse-util.h" #include "path-util.h" #include "process-util.h" #include "set.h" @@ -226,6 +227,8 @@ static int help(void) { " -y --sysname-match=NAME Trigger devices with this /sys path\n" " --name-match=NAME Trigger devices with this /dev name\n" " -b --parent-match=NAME Trigger devices with that parent device\n" + " --initialized-match Trigger devices that are already initialized\n" + " --initialized-nomatch Trigger devices that are not initialized yet\n" " -w --settle Wait for the triggered events to complete\n" " --wait-daemon[=SECONDS] Wait for udevd daemon to be initialized\n" " before triggering uevents\n" @@ -243,6 +246,8 @@ int trigger_main(int argc, char *argv[], void *userdata) { ARG_PING, ARG_UUID, ARG_PRIORITIZED_SUBSYSTEM, + ARG_INITIALIZED_MATCH, + ARG_INITIALIZED_NOMATCH, }; static const struct option options[] = { @@ -260,6 +265,8 @@ int trigger_main(int argc, char *argv[], void *userdata) { { "sysname-match", required_argument, NULL, 'y' }, { "name-match", required_argument, NULL, ARG_NAME }, { "parent-match", required_argument, NULL, 'b' }, + { "initialized-match", no_argument, NULL, ARG_INITIALIZED_MATCH }, + { "initialized-nomatch", no_argument, NULL, ARG_INITIALIZED_NOMATCH }, { "settle", no_argument, NULL, 'w' }, { "wait-daemon", optional_argument, NULL, ARG_PING }, { "version", no_argument, NULL, 'V' }, @@ -426,6 +433,12 @@ int trigger_main(int argc, char *argv[], void *userdata) { } break; } + case ARG_INITIALIZED_MATCH: + case ARG_INITIALIZED_NOMATCH: + r = device_enumerator_add_match_is_initialized(e, c == ARG_INITIALIZED_MATCH ? MATCH_INITIALIZED_YES : MATCH_INITIALIZED_NO); + if (r < 0) + return log_error_errno(r, "Failed to set initialized filter: %m"); + break; case 'V': return print_version(); case 'h':