aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Gottula <justin@jgottula.com>2021-06-30 01:54:38 +0000
committerBrian Behlendorf <behlendorf1@llnl.gov>2021-07-02 20:09:39 +0000
commitf1aef8d4df83c8dc27e366fa1c720f91661d89c2 (patch)
treecdc016fddeadd595dccbc2ad568a5cb0ab13d943
parent17c794e7b0723b1f90229771ddf1dc2ac227f224 (diff)
downloadsrc-f1aef8d4df83c8dc27e366fa1c720f91661d89c2.tar.gz
src-f1aef8d4df83c8dc27e366fa1c720f91661d89c2.zip
Udev rules: use match (==) rather than assign (=) for PROGRAM
Assignment syntax (=) can be used for the PROGRAM key. But the PROGRAM key is really a match key, not an assign key. The internal logic used by udev to decide whether a PROGRAM key "matched" or not (which determines whether the remainder of the rule is evaluated) depends on whether the operator was OP_MATCH (==) or OP_NOMATCH (!=). [1] The man page claims that '"=", ":=", and "+=" have the same effect as "=="' for PROGRAM keys. And, after a brief perusal, the udev source code does seem to confirm that operators other than OP_MATCH (==) or OP_NOMATCH (!=) are implicitly converted to OP_MATCH (==). [2] But it's not entirely clear that this is definitely the case: anecdotal testing seems to indicate that when OP_ASSIGN (=) is used, the program's exit status is disregarded and the remainder of the rule is processed regardless of whether it was, in fact, a successful exit. The bottom line here is that, if zvol_id hits some snag and returns a nonzero exit status, then we almost certainly do NOT want to continue on with the rule and use whatever the stdout contents may have been to mindlessly create /dev/zvol/* symlinks. Therefore, let's be extra-sure and use the match (==) operator explicitly, to eliminate any possibility that udev might do the wrong thing, and ensure that a nonzero exit status will definitely short-circuit the rest of the rule, bypassing the SYMLINK+= assignments. [1] udev, file src/udev/udev-rules.c, func udev_rule_apply_token_to_event, switch case TK_M_PROGRAM if r != 0 (nonzero exit status): return token->op == OP_NOMATCH; switch case TK_M_PROGRAM if r == 0 (zero exit status): return token->op == OP_MATCH; func retval 0 => key is considered to have matched func retval 1 => key is considered to have NOT matched [2] udev, file src/udev/udev-rules.c, func parse_token, at func start: bool is_match = IN_SET(op, OP_MATCH, OP_NOMATCH); in else-if case streq(key, "PROGRAM"): if (!is_match) op = OP_MATCH; Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Pavel Zakharov <pavel.zakharov@delphix.com> Signed-off-by: Justin Gottula <justin@jgottula.com> Closes #12302
-rw-r--r--udev/rules.d/60-zvol.rules.in2
1 files changed, 1 insertions, 1 deletions
diff --git a/udev/rules.d/60-zvol.rules.in b/udev/rules.d/60-zvol.rules.in
index 5e1829029c6b..a3c7d2acf752 100644
--- a/udev/rules.d/60-zvol.rules.in
+++ b/udev/rules.d/60-zvol.rules.in
@@ -3,4 +3,4 @@
# persistent disk links: /dev/zvol/dataset_name
# also creates compatibility symlink of /dev/dataset_name
-KERNEL=="zd*", SUBSYSTEM=="block", ACTION=="add|change", PROGRAM="@udevdir@/zvol_id $devnode", SYMLINK+="zvol/%c %c"
+KERNEL=="zd*", SUBSYSTEM=="block", ACTION=="add|change", PROGRAM=="@udevdir@/zvol_id $devnode", SYMLINK+="zvol/%c %c"