Merge pull request #27483 from yuwata/udev-id-path-usb-revision

udev: include USB revision in ID_PATH
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2023-05-25 10:24:45 +02:00 committed by GitHub
commit 21392bcb1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 183 additions and 61 deletions

View File

@ -3,6 +3,9 @@
ACTION!="remove", SUBSYSTEM=="drm", SUBSYSTEMS=="pci|usb|platform", IMPORT{builtin}="path_id"
# by-path
ENV{ID_PATH}=="?*", KERNEL=="card*", SYMLINK+="dri/by-path/$env{ID_PATH}-card"
ENV{ID_PATH}=="?*", KERNEL=="controlD*", SYMLINK+="dri/by-path/$env{ID_PATH}-control"
ENV{ID_PATH}=="?*", KERNEL=="renderD*", SYMLINK+="dri/by-path/$env{ID_PATH}-render"
KERNEL=="card*", ENV{ID_PATH}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH}-card"
KERNEL=="card*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH_WITH_USB_REVISION}-card"
KERNEL=="controlD*", ENV{ID_PATH}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH}-control"
KERNEL=="controlD*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH_WITH_USB_REVISION}-control"
KERNEL=="renderD*", ENV{ID_PATH}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH}-render"
KERNEL=="renderD*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="dri/by-path/$env{ID_PATH_WITH_USB_REVISION}-render"

View File

@ -10,5 +10,6 @@ ENV{ID_SERIAL}=="?*", ENV{ID_USB_INTERFACE_NUM}=="", SYMLINK+="snd/by-id/$env{ID
IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH}"
ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="snd/by-path/$env{ID_PATH_WITH_USB_REVISION}"
LABEL="persistent_alsa_end"

View File

@ -33,10 +33,14 @@ SUBSYSTEMS=="usb", ENV{ID_BUS}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", A
# by-path
SUBSYSTEMS=="pci|usb|platform|acpi", IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", KERNEL=="mouse*|js*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}"
ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}"
ENV{.INPUT_CLASS}=="?*", KERNEL=="mouse*|js*", ENV{ID_PATH}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-$env{.INPUT_CLASS}"
ENV{.INPUT_CLASS}=="?*", KERNEL=="mouse*|js*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="input/by-path/$env{ID_PATH_WITH_USB_REVISION}-$env{.INPUT_CLASS}"
ENV{.INPUT_CLASS}=="?*", KERNEL=="event*", ENV{ID_PATH}=="?*", SYMLINK+="input/by-path/$env{ID_PATH}-event-$env{.INPUT_CLASS}"
ENV{.INPUT_CLASS}=="?*", KERNEL=="event*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="input/by-path/$env{ID_PATH_WITH_USB_REVISION}-event-$env{.INPUT_CLASS}"
# allow empty class for platform, usb and i2c devices; platform supports only a single interface that way
SUBSYSTEMS=="usb|platform|i2c", ENV{ID_PATH}=="?*", KERNEL=="event*", ENV{.INPUT_CLASS}=="", \
SUBSYSTEMS=="usb|platform|i2c", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ENV{ID_PATH}=="?*", \
SYMLINK+="input/by-path/$env{ID_PATH}-event"
SUBSYSTEMS=="usb|platform|i2c", KERNEL=="event*", ENV{.INPUT_CLASS}=="", ENV{ID_PATH_WITH_USB_REVISION}=="?*", \
SYMLINK+="input/by-path/$env{ID_PATH_WITH_USB_REVISION}-event"
LABEL="persistent_input_end"

View File

@ -6,16 +6,23 @@ ACTION=="remove", GOTO="persistent_storage_tape_end"
ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_tape_end"
# type 8 devices are "Medium Changers"
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{program}="scsi_id --sg-version=3 --export --allowlisted -d $devnode", \
SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL} tape/by-id/scsi-$env{ID_SERIAL}-changer"
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", GOTO="medium_changer_begin"
GOTO="medium_changer_end"
LABEL="medium_changer_begin"
IMPORT{program}="scsi_id --sg-version=3 --export --allowlisted -d $devnode"
ENV{ID_SERIAL}=="?*", SYMLINK+="tape/by-id/scsi-$env{ID_SERIAL} tape/by-id/scsi-$env{ID_SERIAL}-changer"
# iSCSI devices from the same host have all the same ID_SERIAL,
# but additionally a property named ID_SCSI_SERIAL.
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", ENV{ID_SCSI_SERIAL}=="?*", \
SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}"
ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/scsi-$env{ID_SCSI_SERIAL}"
SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="8", IMPORT{builtin}="path_id", \
SYMLINK+="tape/by-path/$env{ID_PATH}-changer"
IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-changer"
ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH_WITH_USB_REVISION}-changer"
LABEL="medium_changer_end"
SUBSYSTEM!="scsi_tape", GOTO="persistent_storage_tape_end"
@ -31,6 +38,8 @@ KERNEL=="nst*[0-9]", ENV{ID_SCSI_SERIAL}=="?*", SYMLINK+="tape/by-id/$env{ID_BUS
# by-path (parent device path)
KERNEL=="st*[0-9]|nst*[0-9]", IMPORT{builtin}="path_id"
KERNEL=="st*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}"
KERNEL=="st*[0-9]", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH_WITH_USB_REVISION}"
KERNEL=="nst*[0-9]", ENV{ID_PATH}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH}-nst"
KERNEL=="nst*[0-9]", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="tape/by-path/$env{ID_PATH_WITH_USB_REVISION}-nst"
LABEL="persistent_storage_tape_end"

View File

@ -112,15 +112,19 @@ KERNEL=="msblk[0-9]p[0-9]|mspblk[0-9]p[0-9]", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}
ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id"
ENV{DEVTYPE}=="disk", SUBSYSTEMS=="nvme-subsystem", IMPORT{builtin}="path_id"
KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n"
KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_WITH_USB_REVISION}-boot%n"
KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
# compatible links for ATA devices
KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}"
KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_WITH_USB_REVISION}"
ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
ENV{DEVTYPE}=="partition", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}-part%n"
ENV{DEVTYPE}=="partition", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_WITH_USB_REVISION}-part%n"
# legacy virtio-pci by-path links (deprecated)
KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}"
KERNEL=="vd*[!0-9]", ENV{ID_PATH_WITH_USB_REVISION}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH_WITH_USB_REVISION}"
KERNEL=="vd*[0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}-part%n"
KERNEL=="vd*[0-9]", ENV{ID_PATH_WITH_USB_REVISION}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH_WITH_USB_REVISION}-part%n"
{% if HAVE_BLKID %}
# allow admin to disable probing the filesystem for slow devices like floppy disk drives

View File

@ -14,7 +14,9 @@ TEST!="index", GOTO="persistent_v4l_end"
ATTR{index}!="?*", GOTO="persistent_v4l_end"
IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", KERNEL=="video*|vbi*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}"
ENV{ID_PATH}=="?*", KERNEL=="audio*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}"
KERNEL=="video*|vbi*", ENV{ID_PATH}=="?*", SYMLINK+="v4l/by-path/$env{ID_PATH}-video-index$attr{index}"
KERNEL=="video*|vbi*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="v4l/by-path/$env{ID_PATH_WITH_USB_REVISION}-video-index$attr{index}"
KERNEL=="audio*", ENV{ID_PATH}=="?*", SYMLINK+="v4l/by-path/$env{ID_PATH}-audio-index$attr{index}"
KERNEL=="audio*", ENV{ID_PATH_WITH_USB_REVISION}=="?*", SYMLINK+="v4l/by-path/$env{ID_PATH_WITH_USB_REVISION}-audio-index$attr{index}"
LABEL="persistent_v4l_end"

View File

@ -15,7 +15,9 @@ SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}"
IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH}"
ENV{ID_PATH_WITH_USB_REVISION}=="?*", ENV{.ID_PORT}=="", SYMLINK+="serial/by-path/$env{ID_PATH_WITH_USB_REVISION}"
ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH}-port$env{.ID_PORT}"
ENV{ID_PATH_WITH_USB_REVISION}=="?*", ENV{.ID_PORT}=="?*", SYMLINK+="serial/by-path/$env{ID_PATH_WITH_USB_REVISION}-port$env{.ID_PORT}"
ENV{ID_BUS}=="", GOTO="serial_end"
ENV{ID_SERIAL}=="", GOTO="serial_end"

View File

@ -9,11 +9,13 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/usb/ch11.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include "alloc-util.h"
#include "device-util.h"
#include "dirent-util.h"
#include "fd-util.h"
#include "parse-util.h"
@ -487,8 +489,51 @@ static void handle_scsi_tape(sd_device *dev, char **path) {
path_prepend(path, "st%c", name[2]);
}
static int get_usb_revision(sd_device *dev) {
uint8_t protocol;
const char *s;
int r;
assert(dev);
/* Returns usb revision 1, 2, or 3. */
r = sd_device_get_sysattr_value(dev, "bDeviceProtocol", &s);
if (r < 0)
return r;
r = safe_atou8_full(s, 16, &protocol);
if (r < 0)
return r;
switch (protocol) {
case USB_HUB_PR_HS_NO_TT: /* Full speed hub (USB1) or Hi-speed hub without TT (USB2) */
/* See speed_show() in drivers/usb/core/sysfs.c of the kernel. */
r = sd_device_get_sysattr_value(dev, "speed", &s);
if (r < 0)
return r;
if (streq(s, "480"))
return 2;
return 1;
case USB_HUB_PR_HS_SINGLE_TT: /* Hi-speed hub with single TT */
case USB_HUB_PR_HS_MULTI_TT: /* Hi-speed hub with multiple TT */
return 2;
case USB_HUB_PR_SS: /* Super speed hub */
return 3;
default:
return -EPROTONOSUPPORT;
}
}
static sd_device *handle_usb(sd_device *parent, char **path) {
const char *devtype, *str, *port;
int r;
if (sd_device_get_devtype(parent, &devtype) < 0)
return parent;
@ -502,12 +547,28 @@ static sd_device *handle_usb(sd_device *parent, char **path) {
return parent;
port++;
/* USB host number may change across reboots (and probably even without reboot). The part after
* USB host number is determined by device topology and so does not change. Hence, drop the
* host number and always use '0' instead. */
parent = skip_subsystem(parent, "usb");
if (!parent)
return NULL;
/* USB host number may change across reboots (and probably even without reboot). The part after USB
* host number is determined by device topology and so does not change. Hence, drop the host number
* and always use '0' instead.
*
* xHCI host controllers may register two (or more?) USB root hubs for USB 2.0 and USB 3.0, and the
* sysname, whose host number replaced with 0, of a device under the hubs may conflict with others.
* To avoid the conflict, let's include the USB revision of the root hub to the PATH_ID.
* See issue https://github.com/systemd/systemd/issues/19406 for more details. */
r = get_usb_revision(parent);
if (r < 0) {
log_device_debug_errno(parent, r, "Failed to get the USB revision number, ignoring: %m");
path_prepend(path, "usb-0:%s", port);
return skip_subsystem(parent, "usb");
} else {
assert(r > 0);
path_prepend(path, "usbv%i-0:%s", r, port);
}
return parent;
}
static sd_device *handle_bcma(sd_device *parent, char **path) {
@ -589,6 +650,66 @@ static int find_real_nvme_parent(sd_device *dev, sd_device **ret) {
return 0;
}
static void add_id_with_usb_revision(sd_device *dev, bool test, char *path) {
char *p;
int r;
assert(dev);
assert(path);
/* When the path contains the USB revision, let's adds ID_PATH_WITH_USB_REVISION property and
* drop the version specifier for later use. */
p = strstrafter(path, "-usbv");
if (!p)
return;
if (!ascii_isdigit(p[0]))
return;
if (p[1] != '-')
return;
r = udev_builtin_add_property(dev, test, "ID_PATH_WITH_USB_REVISION", path);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to add ID_PATH_WITH_USB_REVISION property, ignoring: %m");
/* Drop the USB revision specifier for backward compatibility. */
memmove(p - 1, p + 1, strlen(p + 1) + 1);
}
static void add_id_tag(sd_device *dev, bool test, const char *path) {
char tag[UDEV_NAME_SIZE];
size_t i = 0;
int r;
/* compose valid udev tag name */
for (const char *p = path; *p; p++) {
if (ascii_isdigit(*p) ||
ascii_isalpha(*p) ||
*p == '-') {
tag[i++] = *p;
continue;
}
/* skip all leading '_' */
if (i == 0)
continue;
/* avoid second '_' */
if (tag[i-1] == '_')
continue;
tag[i++] = '_';
}
/* strip trailing '_' */
while (i > 0 && tag[i-1] == '_')
i--;
tag[i] = '\0';
r = udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to add ID_PATH_TAG property, ignoring: %m");
}
static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test) {
sd_device *dev = ASSERT_PTR(ASSERT_PTR(event)->dev);
_cleanup_(sd_device_unrefp) sd_device *dev_other_branch = NULL;
@ -748,37 +869,13 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[], bool test)
!supported_transport)
return -ENOENT;
{
char tag[UDEV_NAME_SIZE];
size_t i = 0;
add_id_with_usb_revision(dev, test, path);
/* compose valid udev tag name */
for (const char *p = path; *p; p++) {
if (ascii_isdigit(*p) ||
ascii_isalpha(*p) ||
*p == '-') {
tag[i++] = *p;
continue;
}
r = udev_builtin_add_property(dev, test, "ID_PATH", path);
if (r < 0)
log_device_debug_errno(dev, r, "Failed to add ID_PATH property, ignoring: %m");
/* skip all leading '_' */
if (i == 0)
continue;
/* avoid second '_' */
if (tag[i-1] == '_')
continue;
tag[i++] = '_';
}
/* strip trailing '_' */
while (i > 0 && tag[i-1] == '_')
i--;
tag[i] = '\0';
udev_builtin_add_property(dev, test, "ID_PATH", path);
udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag);
}
add_id_tag(dev, test, path);
/*
* Compatible link generation for ATA devices