]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev-builtin-path_id: emit 'sf-<N>' token for auxiliary sub-functions
authorJiri Pirko <jiri@nvidia.com>
Mon, 11 May 2026 10:58:05 +0000 (12:58 +0200)
committerJiri Pirko <jiri@nvidia.com>
Tue, 19 May 2026 12:39:20 +0000 (14:39 +0200)
Some drivers expose sub-functions (SFs) of a PCI Physical or Virtual
Function as auxiliary devices that carry a stable 'sfnum' sysfs
attribute — the user-defined sub-function number (e.g. the value
passed to "devlink port add ... sfnum N"). The SF's leaf devices
(uverbs, infiniband, net, ...) sit below this aux device in sysfs:

  /sys/devices/.../<PF or VF BDF>/<sf aux>/.../<leaf>

Currently path_id walks straight past the aux device, so all leaf
devices below an SF end up sharing ID_PATH=pci-<BDF> with their
parent PF or VF. For uverbs this causes a /dev/infiniband/by-path/
symlink collision, and for any other consumer of ID_PATH/ID_PATH_TAG
it makes PF and SF (or VF and VF-SF) indistinguishable.

Recognise the 'auxiliary' subsystem in path_id's walk: when the aux
device exposes 'sfnum', prepend an 'sf-<N>' token; otherwise leave
it untokenised. The result for an SF whose parent PF is at PCI
0000:c1:00.0 and which was added with "sfnum 88" is:

  ID_PATH=pci-0000:c1:00.0-sf-88
  ID_PATH_TAG=pci-0000_c1_00_0-sf-88

This is parallel to how net_id's NAMING_SUBFUNC scheme appends 'S<N>'
on top of the PF base name. Aux devices without 'sfnum' keep the
pre-patch behaviour: the walk skips over them with no token. Existing
ID_PATH values for PF and VF leaf devices are therefore unchanged,
the change is purely additive, and there is no need to gate it behind
a naming scheme (path_id itself is unversioned).

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
src/udev/udev-builtin-path_id.c

index f5d33cd24666349d9ce6d67ec6f61bea6b9e443a..8ae66b30f2676b344cb9a6e43f53737e4190fdff 100644 (file)
@@ -711,6 +711,18 @@ static int builtin_path_id(UdevEvent *event, int argc, char *argv[]) {
                                 path_prepend(&path, "serio-%s", sysnum);
                                 parent = skip_subsystem(parent, "serio");
                         }
+                } else if (device_in_subsystem(parent, "auxiliary") > 0) {
+                        unsigned sfnum;
+
+                        /* sfnum is the user-defined sub-function number (devlink port add ...
+                         * sfnum N). Prepend it so an SF leaf device gets an ID_PATH distinct
+                         * from its parent PF/VF; aux devices without 'sfnum' emit no token to
+                         * preserve pre-patch ID_PATH values. */
+                        if (device_get_sysattr_unsigned(parent, "sfnum", &sfnum) >= 0) {
+                                path_prepend(&path, "sf-%u", sfnum);
+                                if (compat_path)
+                                        path_prepend(&compat_path, "sf-%u", sfnum);
+                        }
                 } else if (device_in_subsystem(parent, "pci") > 0) {
                         path_prepend(&path, "pci-%s", sysname);
                         if (compat_path)