From: Yu Watanabe Date: Sun, 22 Feb 2026 19:58:43 +0000 (+0900) Subject: sd-device: do not clear sd_device.all_tags even on TAG="hoge" X-Git-Tag: v260-rc1~37^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fc03d200c7e91481680802fce46c5e4244aa92a0;p=thirdparty%2Fsystemd.git sd-device: do not clear sd_device.all_tags even on TAG="hoge" The current tag concept has been introduced by e77b146f825ef1bb63c297cc713962b94422d2c6 (v247) to make symlinks in /run/udev/tags/ are 'sticky'. However, when TAG= (rather than TAG+=) is specified, then the tags assigned in the previous events were also cleared. This fixes the issue and now symlinks in /run/udev/tags/ are really 'sticky'. Fortunately, TAG= is mostly unused. So, the issue should not affect and the fix should not change anything on almost all systems. --- diff --git a/src/libsystemd/sd-device/device-private.c b/src/libsystemd/sd-device/device-private.c index 828697e6176..d640eeb2502 100644 --- a/src/libsystemd/sd-device/device-private.c +++ b/src/libsystemd/sd-device/device-private.c @@ -710,13 +710,23 @@ int device_copy_all_tags(sd_device *dest, sd_device *src) { return 0; } -void device_cleanup_tags(sd_device *device) { +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) { diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h index 376a4a479cd..90f4e103f5e 100644 --- a/src/libsystemd/sd-device/device-private.h +++ b/src/libsystemd/sd-device/device-private.h @@ -46,7 +46,7 @@ int device_add_propertyf(sd_device *device, const char *key, const char *format, int device_add_tag(sd_device *device, const char *tag, bool both); void device_remove_tag(sd_device *device, const char *tag); int device_copy_all_tags(sd_device *dest, sd_device *src); -void device_cleanup_tags(sd_device *device); +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); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 06686e3715e..f0e4fbccfd7 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)