From 28460195c2ae90892bf556aff2b80705a8f37795 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 22 Apr 2010 18:12:36 +0200 Subject: add TAG= to improve event filtering and device enumeration --- udev/udev-event.c | 1 - udev/udev-rules.c | 14 ++++++++++++++ udev/udev.xml | 13 +++++++++++++ udev/udevadm-monitor.c | 17 ++++++++++++++++- udev/udevadm-trigger.c | 7 ++++++- udev/udevadm.xml | 13 +++++++++++++ 6 files changed, 62 insertions(+), 3 deletions(-) (limited to 'udev') diff --git a/udev/udev-event.c b/udev/udev-event.c index b2e1baee1f..212ccc7950 100644 --- a/udev/udev-event.c +++ b/udev/udev-event.c @@ -543,7 +543,6 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) if (strcmp(udev_device_get_action(dev), "remove") == 0) { udev_device_read_db(dev); - udev_device_set_info_loaded(dev); udev_device_delete_db(dev); if (major(udev_device_get_devnum(dev)) != 0) diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 6eb8350343..b5016d0bc3 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -157,6 +157,7 @@ enum token_type { TK_A_GROUP_ID, /* gid_t */ TK_A_MODE_ID, /* mode_t */ TK_A_ENV, /* val, attr */ + TK_A_TAG, /* val */ TK_A_NAME, /* val */ TK_A_DEVLINK, /* val */ TK_A_EVENT_TIMEOUT, /* int */ @@ -285,6 +286,7 @@ static const char *token_str(enum token_type type) [TK_A_GROUP_ID] = "A GROUP_ID", [TK_A_MODE_ID] = "A MODE_ID", [TK_A_ENV] = "A ENV", + [TK_A_TAG] = "A ENV", [TK_A_NAME] = "A NAME", [TK_A_DEVLINK] = "A DEVLINK", [TK_A_EVENT_TIMEOUT] = "A EVENT_TIMEOUT", @@ -354,6 +356,9 @@ static void dump_token(struct udev_rules *rules, struct token *token) dbg(rules->udev, "%s %s '%s' '%s'(%s)\n", token_str(type), operation_str(op), attr, value, string_glob_str(glob)); break; + case TK_A_TAG: + dbg(rules->udev, "%s %s '%s'\n", token_str(type), operation_str(op), value); + break; case TK_A_STRING_ESCAPE_NONE: case TK_A_STRING_ESCAPE_REPLACE: dbg(rules->udev, "%s\n", token_str(type)); @@ -1003,6 +1008,7 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, case TK_A_MODE: case TK_A_NAME: case TK_A_GOTO: + case TK_A_TAG: token->key.value_off = add_string(rule_tmp->rules, value); break; case TK_M_ENV: @@ -1350,6 +1356,11 @@ static int add_rule(struct udev_rules *rules, char *line, continue; } + if (strcmp(key, "TAG") == 0) { + rule_add_key(&rule_tmp, TK_A_TAG, op, value, NULL); + continue; + } + if (strcmp(key, "PROGRAM") == 0) { rule_add_key(&rule_tmp, TK_M_PROGRAM, op, value, NULL); continue; @@ -2408,6 +2419,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event } break; } + case TK_A_TAG: + udev_device_add_tag(event->dev, &rules->buf[cur->key.value_off]); + break; case TK_A_NAME: { const char *name = &rules->buf[cur->key.value_off]; diff --git a/udev/udev.xml b/udev/udev.xml index 192a6f1238..842fd5d52a 100644 --- a/udev/udev.xml +++ b/udev/udev.xml @@ -348,6 +348,19 @@ + + + + Attach a tag to a device. This is used to filter events for users + of libudev's monitor functionality, or to enumerate a group of tagged + devices. The implementation can only work efficiently if only a few + tags are attached to a device. It is only meant to be used in + contexts with specific device filter requirements, and not as a + general-purpose flag. Excessive use might result in inefficient event + handling. + + + diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c index d136c6070a..fb650846bc 100644 --- a/udev/udevadm-monitor.c +++ b/udev/udevadm-monitor.c @@ -73,6 +73,7 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) int print_kernel = 0; int print_udev = 0; struct udev_list_node subsystem_match_list; + struct udev_list_node tag_match_list; struct udev_monitor *udev_monitor = NULL; struct udev_monitor *kernel_monitor = NULL; fd_set readfds; @@ -84,13 +85,15 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) { "kernel", no_argument, NULL, 'k' }, { "udev", no_argument, NULL, 'u' }, { "subsystem-match", required_argument, NULL, 's' }, + { "tag-match", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, {} }; udev_list_init(&subsystem_match_list); + udev_list_init(&tag_match_list); while (1) { - option = getopt_long(argc, argv, "epkus:h", options, NULL); + option = getopt_long(argc, argv, "pekus:t:h", options, NULL); if (option == -1) break; @@ -119,12 +122,16 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) udev_list_entry_add(udev, &subsystem_match_list, subsys, devtype, 0, 0); break; } + case 't': + udev_list_entry_add(udev, &tag_match_list, optarg, NULL, 0, 0); + break; case 'h': printf("Usage: udevadm monitor [--property] [--kernel] [--udev] [--help]\n" " --property print the event properties\n" " --kernel print kernel uevents\n" " --udev print udev events\n" " --subsystem-match= filter events by subsystem\n" + " --tag-match= filter events by tag\n" " --help\n\n"); default: goto out; @@ -168,6 +175,13 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); } + udev_list_entry_foreach(entry, udev_list_get_entry(&tag_match_list)) { + const char *tag = udev_list_entry_get_name(entry); + + if (udev_monitor_filter_add_match_tag(udev_monitor, tag) < 0) + fprintf(stderr, "error: unable to apply tag filter '%s'\n", tag); + } + if (udev_monitor_enable_receiving(udev_monitor) < 0) { fprintf(stderr, "error: unable to subscribe to udev events\n"); rc = 2; @@ -244,5 +258,6 @@ out: udev_monitor_unref(udev_monitor); udev_monitor_unref(kernel_monitor); udev_list_cleanup_entries(udev, &subsystem_match_list); + udev_list_cleanup_entries(udev, &tag_match_list); return rc; } diff --git a/udev/udevadm-trigger.c b/udev/udevadm-trigger.c index 03aa53437f..3cb07dda9a 100644 --- a/udev/udevadm-trigger.c +++ b/udev/udevadm-trigger.c @@ -101,6 +101,7 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) { "attr-match", required_argument, NULL, 'a' }, { "attr-nomatch", required_argument, NULL, 'A' }, { "property-match", required_argument, NULL, 'p' }, + { "tag-match", required_argument, NULL, 'g' }, { "sysname-match", required_argument, NULL, 'y' }, { "help", no_argument, NULL, 'h' }, {} @@ -127,7 +128,7 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) const char *val; char buf[UTIL_PATH_SIZE]; - option = getopt_long(argc, argv, "vnFo:t:hcp:s:S:a:A:y:", options, NULL); + option = getopt_long(argc, argv, "vng:o:t:hcp:s:S:a:A:y:", options, NULL); if (option == -1) break; @@ -172,6 +173,9 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) key = keyval(optarg, &val, buf, sizeof(buf)); udev_enumerate_add_match_property(udev_enumerate, key, val); break; + case 'g': + udev_enumerate_add_match_tag(udev_enumerate, optarg); + break; case 'y': udev_enumerate_add_match_sysname(udev_enumerate, optarg); break; @@ -190,6 +194,7 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) " --attr-match=]> trigger devices with a matching attribute\n" " --attr-nomatch=]> exclude devices with a matching attribute\n" " --property-match== trigger devices with a matching property\n" + " --tag-match== trigger devices with a matching property\n" " --sysname-match= trigger devices with a matching name\n" " --help\n\n"); goto exit; diff --git a/udev/udevadm.xml b/udev/udevadm.xml index fa1742bada..73e6f110a6 100644 --- a/udev/udevadm.xml +++ b/udev/udevadm.xml @@ -216,6 +216,13 @@ specified multiple times and supports shell style pattern matching. + + + + Trigger events for devices with a matching tag. This option can be + specified multiple times. + + @@ -355,6 +362,12 @@ Filter events by subsystem[/devtype]. Only udev events with a matching subsystem value will pass. + + + + Filter events by property. Only udev events with a given tag attached will pass. + + -- cgit v1.2.3-54-g00ecf