From 477f84cf9191c0b5a139786de0c569bb918d0286 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 11 May 2026 12:58:05 +0200 Subject: [PATCH] udev-builtin-path_id: emit 'sf-' token for auxiliary sub-functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/...///.../ Currently path_id walks straight past the aux device, so all leaf devices below an SF end up sharing ID_PATH=pci- 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-' 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' 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 --- src/udev/udev-builtin-path_id.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c index f5d33cd246..8ae66b30f2 100644 --- a/src/udev/udev-builtin-path_id.c +++ b/src/udev/udev-builtin-path_id.c @@ -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)