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.
This commit is contained in:
Franck Bui 2023-01-17 14:30:48 +09:00 committed by Yu Watanabe
parent 841dfd3dc0
commit aeefa4d248
3 changed files with 25 additions and 7 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;