From: Franck Bui Date: Tue, 17 Jan 2023 05:30:48 +0000 (+0900) Subject: udev: support '-=' operator for SYMLINK X-Git-Tag: v253-rc1~86^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aeefa4d248279a259cdf53036e4bd4ff5dfa1525;p=thirdparty%2Fsystemd.git udev: support '-=' operator for SYMLINK For some (corner) cases, it might be desirable to disable the generation of some persistent storage symlinks that 60-persistent-storage.rules creates. For example on big setups with a high number of partitions which uses the same label name, this can result in a noticeable slow-down in the (re)start of the udevd as there are many contenders for the symlink /dev/disk/by-partlabel. However it's currently pretty hard to overwrite just some specific part of the rule file. Indeed one need to copy and modify the whole rule file in /etc but will lost any upcoming updates/fixes that the distro might release in the future. With this simple patch, one can now disable the generation of the "by-partlabel" symlinks (for example) with the following single rule: $ cat /etc/udev/rules.d/99-no-by-partlabel.rules ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK-="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}" Closes #24607. --- diff --git a/src/libsystemd/sd-device/device-private.h b/src/libsystemd/sd-device/device-private.h index d9a519a4d98..740c58438cf 100644 --- a/src/libsystemd/sd-device/device-private.h +++ b/src/libsystemd/sd-device/device-private.h @@ -38,6 +38,7 @@ void device_set_db_persist(sd_device *device); void device_set_devlink_priority(sd_device *device, int priority); int device_ensure_usec_initialized(sd_device *device, sd_device *device_old); int device_add_devlink(sd_device *device, const char *devlink); +void device_remove_devlink(sd_device *device, const char *devlink); bool device_has_devlink(sd_device *device, const char *devlink); int device_add_property(sd_device *device, const char *property, const char *value); int device_add_propertyf(sd_device *device, const char *key, const char *format, ...) _printf_(3, 4); diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index c3160b04bb7..8c65ee34698 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -1489,6 +1489,20 @@ int device_add_devlink(sd_device *device, const char *devlink) { return 0; } +void device_remove_devlink(sd_device *device, const char *devlink) { + _cleanup_free_ char *s = NULL; + + assert(device); + assert(devlink); + + s = set_remove(device->devlinks, devlink); + if (!s) + return; + + device->devlinks_generation++; + device->property_devlinks_outdated = true; +} + bool device_has_devlink(sd_device *device, const char *devlink) { assert(device); assert(devlink); diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 52bf66ab0b9..5bd09a64d1d 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -579,9 +579,6 @@ static int parse_token(UdevRules *rules, const char *key, char *attr, UdevRuleOp } else if (streq(key, "SYMLINK")) { if (attr) return log_token_invalid_attr(rules, key); - if (op == OP_REMOVE) - return log_token_invalid_op(rules, key); - if (!is_match) { check_value_format_and_warn(rules, key, value, false); r = rule_line_add_token(rule_line, TK_A_DEVLINK, op, value, NULL); @@ -2313,11 +2310,17 @@ static int udev_rule_apply_token_to_event( if (truncated) continue; - r = device_add_devlink(dev, filename); - if (r < 0) - return log_rule_error_errno(dev, rules, r, "Failed to add devlink '%s': %m", filename); + if (token->op == OP_REMOVE) { + device_remove_devlink(dev, filename); + log_rule_debug(dev, rules, "Dropped SYMLINK '%s'", p); + } else { + r = device_add_devlink(dev, filename); + if (r < 0) + return log_rule_error_errno(dev, rules, r, "Failed to add devlink '%s': %m", filename); + + log_rule_debug(dev, rules, "Added SYMLINK '%s'", p); + } - log_rule_debug(dev, rules, "LINK '%s'", p); p = next; } break;