]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
udevHandleOneDevice: Remove old instance of device on "move"
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 20 Apr 2020 14:12:03 +0000 (16:12 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 22 Apr 2020 10:51:15 +0000 (12:51 +0200)
When a device is "move"-d (this basically means it was renamed),
we add the new device onto our list but keep the old there too.
Fortunately, udev sets this DEVPATH_OLD property which points to
the old device path. We can use it to remove the old instance.

To test this try renaming an interface, for instance:

  # ip link set tunl0 name tunl1
  # ip link set tunl1 name tunl0

One problem with udev is that it sends old ifname in INTERFACE
property, which creates a problem for us, the property is where
we get the ifname from and use it then to query all kind of info
about the interface. Well, if it is non-existent then we can't
query anything. This happens if ifname rename is suppressed
(net.ifnames=0 on kernel cmd line for instance). Fortunately, we
can use "kernel" source for udev events which has always the
fresh info.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
src/node_device/node_device_udev.c

index e9a76a7b010f565618a22d8864198411283aa2ed..386f23ef3a18fddbbbda679c57a264a349d77734 100644 (file)
@@ -1507,7 +1507,14 @@ udevHandleOneDevice(struct udev_device *device)
         return udevRemoveOneDevice(device);
 
     if (STREQ(action, "move")) {
-        /* TODO: implement a way of finding and removing the old device */
+        const char *devpath_old = udevGetDeviceProperty(device, "DEVPATH_OLD");
+
+        if (devpath_old) {
+            g_autofree char *devpath_old_fixed = g_strdup_printf("/sys%s", devpath_old);
+
+            udevRemoveOneDeviceSysPath(devpath_old_fixed);
+        }
+
         return udevAddOneDevice(device);
     }
 
@@ -1872,7 +1879,7 @@ nodeStateInitialize(bool privileged,
 
     virObjectLock(priv);
 
-    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
+    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "kernel");
     if (!priv->udev_monitor) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("udev_monitor_new_from_netlink returned NULL"));