diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index 035e7290e0..054c3545d0 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -693,20 +693,46 @@ int device_clone_with_db(sd_device *device, sd_device **ret) { return 0; } -void device_cleanup_tags(sd_device *device) { +int device_copy_all_tags(sd_device *dest, sd_device *src) { + int r; + + assert(dest); + + if (!src) + return 0; + + FOREACH_DEVICE_TAG(src, tag) { + r = device_add_tag(dest, tag, /* both= */ false); + if (r < 0) + return r; + } + + return 0; +} + +int device_cleanup_tags(sd_device *device, sd_device *original) { + int r; + assert(device); - device->all_tags = set_free(device->all_tags); + _cleanup_set_free_ Set *saved = TAKE_PTR(device->all_tags); device->current_tags = set_free(device->current_tags); device->property_tags_outdated = true; device->tags_generation++; + + r = device_copy_all_tags(device, original); + if (r < 0) { + set_free_and_replace(device->all_tags, saved); + return r; + } + + return 0; } void device_cleanup_devlinks(sd_device *device) { assert(device); - set_free(device->devlinks); - device->devlinks = NULL; + device->devlinks = set_free(device->devlinks); device->property_devlinks_outdated = true; device->devlinks_generation++; } @@ -743,15 +769,9 @@ static int device_tag(sd_device *device, const char *tag, bool add) { return 0; } -int device_tag_index(sd_device *device, sd_device *device_old, bool add) { +int device_tag_index(sd_device *device, bool add) { int r = 0; - if (add && device_old) - /* delete possible left-over tags */ - FOREACH_DEVICE_TAG(device_old, tag) - if (!sd_device_has_tag(device, tag)) - RET_GATHER(r, device_tag(device_old, tag, false)); - FOREACH_DEVICE_TAG(device, tag) RET_GATHER(r, device_tag(device, tag, add)); diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h index 8f88b38c46..f2f349f2ac 100644 --- a/src/libsystemd/sd-device/device-private.h +++ b/src/libsystemd/sd-device/device-private.h @@ -45,7 +45,8 @@ int device_add_property(sd_device *device, const char *key, const char *value); int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) _printf_(3, 4); int device_add_tag(sd_device *device, const char *tag, bool both); void device_remove_tag(sd_device *device, const char *tag); -void device_cleanup_tags(sd_device *device); +int device_copy_all_tags(sd_device *dest, sd_device *src); +int device_cleanup_tags(sd_device *device, sd_device *original); void device_cleanup_devlinks(sd_device *device); uint64_t device_get_properties_generation(sd_device *device); @@ -58,7 +59,7 @@ int device_get_properties_strv(sd_device *device, char ***ret); int device_clone_with_db(sd_device *device, sd_device **ret); -int device_tag_index(sd_device *device, sd_device *device_old, bool add); +int device_tag_index(sd_device *device, bool add); bool device_should_have_db(sd_device *device); int device_has_db(sd_device *device); int device_update_db(sd_device *device); diff --git a/src/udev/udev-dump.c b/src/udev/udev-dump.c index e8d23377ff..57e008c73d 100644 --- a/src/udev/udev-dump.c +++ b/src/udev/udev-dump.c @@ -270,6 +270,20 @@ static int dump_event_json(UdevEvent *event, sd_json_format_flags_t flags, FILE return r; } + tags = strv_free(tags); + + FOREACH_DEVICE_CURRENT_TAG(dev, tag) { + r = strv_extend(&tags, tag); + if (r < 0) + return r; + } + + if (!strv_isempty(tags)) { + r = sd_json_variant_set_field_strv(&v, "currentTags", strv_sort(tags)); + if (r < 0) + return r; + } + char **properties; if (device_get_properties_strv(dev, &properties) >= 0 && !strv_isempty(properties)) { r = sd_json_variant_set_field_strv(&v, "properties", strv_sort(properties)); @@ -417,6 +431,12 @@ int dump_event(UdevEvent *event, sd_json_format_flags_t flags, FILE *f) { fprintf(f, " %s\n", tag); } + if (sd_device_get_current_tag_first(dev)) { + fprintf(f, "%sCurrent Tags:%s\n", ansi_highlight(), ansi_normal()); + FOREACH_DEVICE_CURRENT_TAG(dev, tag) + fprintf(f, " %s\n", tag); + } + char **properties; if (device_get_properties_strv(dev, &properties) >= 0 && !strv_isempty(properties)) { bool space = true; diff --git a/src/udev/udev-error.c b/src/udev/udev-error.c index 9f06ed4a1c..95739aaee6 100644 --- a/src/udev/udev-error.c +++ b/src/udev/udev-error.c @@ -63,7 +63,7 @@ int device_broadcast_on_error(sd_device *dev, sd_device_monitor *monitor) { /* delete state from disk */ (void) device_delete_db(dev); - (void) device_tag_index(dev, /* device_old= */ NULL, /* add= */ false); + (void) device_tag_index(dev, /* add= */ false); r = device_monitor_send(monitor, /* destination= */ NULL, dev); if (r < 0) { diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index ad7b9fc776..49c692944e 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -310,7 +310,7 @@ static int event_execute_rules_on_remove(UdevEvent *event, UdevRules *rules) { log_device_debug_errno(dev, r, "Failed to read database under /run/udev/data/: %m"); if (EVENT_MODE_DESTRUCTIVE(event)) { - r = device_tag_index(dev, NULL, false); + r = device_tag_index(dev, /* add= */ false); if (r < 0) log_device_debug_errno(dev, r, "Failed to remove corresponding tag files under /run/udev/tag/, ignoring: %m"); @@ -329,23 +329,6 @@ static int event_execute_rules_on_remove(UdevEvent *event, UdevRules *rules) { return r; } -static int copy_all_tags(sd_device *d, sd_device *s) { - int r; - - assert(d); - - if (!s) - return 0; - - FOREACH_DEVICE_TAG(s, tag) { - r = device_add_tag(d, tag, false); - if (r < 0) - return r; - } - - return 0; -} - static int update_clone(UdevEvent *event) { sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev_db_clone); int r; @@ -398,7 +381,7 @@ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) { if (r < 0) return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m"); - r = copy_all_tags(dev, event->dev_db_clone); + r = device_copy_all_tags(dev, event->dev_db_clone); if (r < 0) log_device_warning_errno(dev, r, "Failed to copy all tags from old database entry, ignoring: %m"); @@ -433,7 +416,7 @@ int udev_event_execute_rules(UdevEvent *event, UdevRules *rules) { if (EVENT_MODE_DESTRUCTIVE(event)) { /* (re)write database file */ - r = device_tag_index(dev, event->dev_db_clone, true); + r = device_tag_index(dev, /* add= */ true); if (r < 0) return log_device_debug_errno(dev, r, "Failed to update tags under /run/udev/tag/: %m"); } diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 06686e3715..f0e4fbccfd 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -2900,8 +2900,11 @@ static int udev_rule_apply_token_to_event( assert(IN_SET(token->op, OP_ASSIGN, OP_ADD)); - if (token->op == OP_ASSIGN) - device_cleanup_tags(dev); + if (token->op == OP_ASSIGN) { + r = device_cleanup_tags(dev, event->dev_db_clone); + if (r < 0) + log_event_warning_errno(event, token, r, "Failed to clear previously assigned tags, ignoring: %m"); + } r = device_add_tag(dev, buf, /* both= */ true); if (r == -ENOMEM)