You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
8.1 KiB
190 lines
8.1 KiB
From be88b819ecec075187ac313b8ab15d8ed8004b54 Mon Sep 17 00:00:00 2001 |
|
From: Jan Synacek <jsynacek@redhat.com> |
|
Date: Wed, 11 Sep 2019 12:35:18 +0200 |
|
Subject: [PATCH] udev: introduce CONST key name |
|
|
|
Currently, there is no way to match against system-wide constants, such |
|
as architecture or virtualization type, without forking helper binaries. |
|
That potentially results in a huge number of spawned processes which |
|
output always the same answer. |
|
|
|
This patch introduces a special CONST keyword which takes a hard-coded |
|
string as its key and returns a value assigned to that key. Currently |
|
implemented are CONST{arch} and CONST{virt}, which can be used to match |
|
against the system's architecture and virtualization type. |
|
|
|
(based on commit 4801d8afe2ff1c1c075c9f0bc5631612172e0bb7) |
|
|
|
Resolves: #1748051 |
|
--- |
|
man/udev.xml | 26 ++++++++++++++++++++++++++ |
|
rules/40-redhat.rules | 4 ++-- |
|
src/udev/udev-rules.c | 39 +++++++++++++++++++++++++++++++++++++++ |
|
test/rule-syntax-check.py | 2 +- |
|
4 files changed, 68 insertions(+), 3 deletions(-) |
|
|
|
diff --git a/man/udev.xml b/man/udev.xml |
|
index a948ea79a9..fc02edd214 100644 |
|
--- a/man/udev.xml |
|
+++ b/man/udev.xml |
|
@@ -240,6 +240,32 @@ |
|
</listitem> |
|
</varlistentry> |
|
|
|
+ <varlistentry> |
|
+ <term><varname>CONST{<replaceable>key</replaceable>}</varname></term> |
|
+ <listitem> |
|
+ <para>Match against a system-wide constant. Supported keys are:</para> |
|
+ <variablelist> |
|
+ <varlistentry> |
|
+ <term><literal>arch</literal></term> |
|
+ <listitem> |
|
+ <para>System's architecture. See <option>ConditionArchitecture=</option> in |
|
+ <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> |
|
+ for possible values.</para> |
|
+ </listitem> |
|
+ </varlistentry> |
|
+ <varlistentry> |
|
+ <term><literal>virt</literal></term> |
|
+ <listitem> |
|
+ <para>System's virtualization environment. See |
|
+ <citerefentry><refentrytitle>systemd-detect-virt</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
|
+ for possible values.</para> |
|
+ </listitem> |
|
+ </varlistentry> |
|
+ </variablelist> |
|
+ <para>Unknown keys will never match.</para> |
|
+ </listitem> |
|
+ </varlistentry> |
|
+ |
|
<varlistentry> |
|
<term><varname>TAG</varname></term> |
|
<listitem> |
|
diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules |
|
index 2c690e522e..83d823e172 100644 |
|
--- a/rules/40-redhat.rules |
|
+++ b/rules/40-redhat.rules |
|
@@ -6,10 +6,10 @@ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online} |
|
# Memory hotadd request |
|
SUBSYSTEM!="memory", GOTO="memory_hotplug_end" |
|
ACTION!="add", GOTO="memory_hotplug_end" |
|
-PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end" |
|
+CONST{arch}=="s390*", GOTO="memory_hotplug_end" |
|
|
|
ENV{.state}="online" |
|
-PROGRAM="/bin/systemd-detect-virt", RESULT=="none", ENV{.state}="online_movable" |
|
+CONST{virt}=="none", ENV{.state}="online_movable" |
|
ATTR{state}=="offline", ATTR{state}="$env{.state}" |
|
|
|
LABEL="memory_hotplug_end" |
|
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c |
|
index c9a0197534..9211f563b1 100644 |
|
--- a/src/udev/udev-rules.c |
|
+++ b/src/udev/udev-rules.c |
|
@@ -29,12 +29,14 @@ |
|
#include <fnmatch.h> |
|
#include <time.h> |
|
|
|
+#include "architecture.h" |
|
#include "udev.h" |
|
#include "path-util.h" |
|
#include "conf-files.h" |
|
#include "strbuf.h" |
|
#include "strv.h" |
|
#include "util.h" |
|
+#include "virt.h" |
|
|
|
#define PREALLOC_TOKEN 2048 |
|
|
|
@@ -123,6 +125,7 @@ enum token_type { |
|
TK_M_DEVLINK, /* val */ |
|
TK_M_NAME, /* val */ |
|
TK_M_ENV, /* val, attr */ |
|
+ TK_M_CONST, /* val, attr */ |
|
TK_M_TAG, /* val */ |
|
TK_M_SUBSYSTEM, /* val */ |
|
TK_M_DRIVER, /* val */ |
|
@@ -257,6 +260,7 @@ static const char *token_str(enum token_type type) { |
|
[TK_M_DEVLINK] = "M DEVLINK", |
|
[TK_M_NAME] = "M NAME", |
|
[TK_M_ENV] = "M ENV", |
|
+ [TK_M_CONST] = "M CONST", |
|
[TK_M_TAG] = "M TAG", |
|
[TK_M_SUBSYSTEM] = "M SUBSYSTEM", |
|
[TK_M_DRIVER] = "M DRIVER", |
|
@@ -365,6 +369,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) { |
|
case TK_M_ATTR: |
|
case TK_M_ATTRS: |
|
case TK_M_ENV: |
|
+ case TK_M_CONST: |
|
case TK_A_ATTR: |
|
case TK_A_ENV: |
|
log_debug("%s %s '%s' '%s'(%s)", |
|
@@ -905,6 +910,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, |
|
token->key.builtin_cmd = *(enum udev_builtin_cmd *)data; |
|
break; |
|
case TK_M_ENV: |
|
+ case TK_M_CONST: |
|
case TK_M_ATTR: |
|
case TK_M_ATTRS: |
|
case TK_A_ATTR: |
|
@@ -1264,6 +1270,22 @@ static int add_rule(struct udev_rules *rules, char *line, |
|
continue; |
|
} |
|
|
|
+ if (startswith(key, "CONST{")) { |
|
+ attr = get_key_attribute(rules->udev, key + STRLEN("CONST")); |
|
+ if (attr == NULL || !STR_IN_SET(attr, "arch", "virt")) { |
|
+ log_error("error parsing CONST attribute"); |
|
+ goto invalid; |
|
+ } |
|
+ if (op == OP_REMOVE) { |
|
+ log_error("invalid CONST operation"); |
|
+ goto invalid; |
|
+ } |
|
+ if (op < OP_MATCH_MAX) { |
|
+ if (rule_add_key(&rule_tmp, TK_M_CONST, op, value, attr) != 0) |
|
+ goto invalid; |
|
+ } |
|
+ continue; |
|
+ } |
|
if (streq(key, "TAG")) { |
|
if (op < OP_MATCH_MAX) |
|
rule_add_key(&rule_tmp, TK_M_TAG, op, value, NULL); |
|
@@ -1959,6 +1981,23 @@ int udev_rules_apply_to_event(struct udev_rules *rules, |
|
goto nomatch; |
|
break; |
|
} |
|
+ case TK_M_CONST: { |
|
+ const char *key_name = rules_str(rules, cur->key.attr_off); |
|
+ const char *value = NULL; |
|
+ int q; |
|
+ |
|
+ if (streq(key_name, "arch")) { |
|
+ q = uname_architecture(); |
|
+ value = architecture_to_string(q); |
|
+ } else if (streq(key_name, "virt")) { |
|
+ q = detect_virtualization(&value); |
|
+ } else |
|
+ assert_not_reached("Invalid CONST key"); |
|
+ |
|
+ if (match_key(rules, cur, value)) |
|
+ goto nomatch; |
|
+ break; |
|
+ } |
|
case TK_M_TAG: { |
|
struct udev_list_entry *list_entry; |
|
bool match = false; |
|
diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py |
|
index 80bbe65bea..c6d003b167 100644 |
|
--- a/test/rule-syntax-check.py |
|
+++ b/test/rule-syntax-check.py |
|
@@ -34,7 +34,7 @@ else: |
|
rules_files = glob(os.path.join(rules_dir, '*.rules')) |
|
|
|
no_args_tests = re.compile('(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|RESULT|TEST)\s*(?:=|!)=\s*"([^"]*)"$') |
|
-args_tests = re.compile('(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$') |
|
+args_tests = re.compile('(ATTRS?|ENV|CONST|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*"([^"]*)"$') |
|
no_args_assign = re.compile('(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|PROGRAM|RUN|LABEL|GOTO|WAIT_FOR|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*"([^"]*)"$') |
|
args_assign = re.compile('(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*"([^"]*)"$') |
|
|
|
|