summaryrefslogtreecommitdiff
path: root/src/udev/udev-builtin-net_id.c
diff options
context:
space:
mode:
authorStuart Hayes <stuart_hayes@dell.com>2018-01-16 16:08:10 -0500
committerStuart Hayes <stuart_hayes@dell.com>2018-03-26 13:57:12 -0400
commit9009d3b5c3b6d191be69215736be77583e0f23f9 (patch)
treecd313feed38c8bbb5edbf94b0a86caacf1a12891 /src/udev/udev-builtin-net_id.c
parent303d6b4ca6ebadca2f6faf63a76743e22efba242 (diff)
downloadsystemd-9009d3b5c3b6d191be69215736be77583e0f23f9.tar.gz
udev: net_id: search parent devices for PCI slot number
To generate predictable network device names, the code in udev-builting-net_id.c tries to match the PCI device address of the network device to the entries in /sys/bus/pci/slots. However, sometimes the slot number is not associated the network controller PCI device itself, but rather with one of its parents. This change will try to find a match in /sys/bus/pci/slots for the parents of the PCI network device, if it doesn't find a match for the device itself.
Diffstat (limited to 'src/udev/udev-builtin-net_id.c')
-rw-r--r--src/udev/udev-builtin-net_id.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c
index 6efa712930..3d3329b382 100644
--- a/src/udev/udev-builtin-net_id.c
+++ b/src/udev/udev-builtin-net_id.c
@@ -112,6 +112,7 @@
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "parse-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev.h"
@@ -233,15 +234,15 @@ static bool is_pci_multifunction(struct udev_device *dev) {
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
struct udev *udev = udev_device_get_udev(names->pcidev);
- unsigned domain, bus, slot, func, dev_port = 0;
+ unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0;
size_t l;
char *s;
const char *attr, *port_name;
_cleanup_udev_device_unref_ struct udev_device *pci = NULL;
+ struct udev_device *hotplug_slot_dev;
char slots[PATH_MAX];
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *dent;
- int hotplug_slot = 0;
if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4)
return -ENOENT;
@@ -281,27 +282,33 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
if (!dir)
return -errno;
- FOREACH_DIRENT_ALL(dent, dir, break) {
- int i;
- char *rest, str[PATH_MAX];
- _cleanup_free_ char *address = NULL;
-
- if (dent->d_name[0] == '.')
- continue;
- i = strtol(dent->d_name, &rest, 10);
- if (rest[0] != '\0')
- continue;
- if (i < 1)
- continue;
-
- if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
- read_one_line_file(str, &address) >= 0)
- /* match slot address with device by stripping the function */
- if (startswith(udev_device_get_sysname(names->pcidev), address))
- hotplug_slot = i;
-
+ hotplug_slot_dev = names->pcidev;
+ while (hotplug_slot_dev) {
+ FOREACH_DIRENT_ALL(dent, dir, break) {
+ unsigned i;
+ int r;
+ char str[PATH_MAX];
+ _cleanup_free_ char *address = NULL;
+
+ if (dent->d_name[0] == '.')
+ continue;
+ r = safe_atou_full(dent->d_name, 10, &i);
+ if (i < 1 || r < 0)
+ continue;
+
+ if (snprintf_ok(str, sizeof str, "%s/%s/address", slots, dent->d_name) &&
+ read_one_line_file(str, &address) >= 0)
+ /* match slot address with device by stripping the function */
+ if (startswith(udev_device_get_sysname(hotplug_slot_dev), address))
+ hotplug_slot = i;
+
+ if (hotplug_slot > 0)
+ break;
+ }
if (hotplug_slot > 0)
break;
+ rewinddir(dir);
+ hotplug_slot_dev = udev_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL);
}
if (hotplug_slot > 0) {