From: Michael Biebl <biebl@debian.org>
Date: Thu, 18 Jul 2013 01:04:07 +0200
Subject: Revert "udev: network device renaming - immediately give up if the
 target name isn't available"

This reverts commit 97595710b77aa162ca5e20da57d0a1ed7355eaad.

Since we are keeping the old persistent network interface naming for
now, and make the new naming scheme [1] explictly opt-in [2], re-apply
this old hack to make the renaming less likely to fail.

[1] http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
[2] d5051f7666e25ecf2b32c7076ce18c1de969d01b
---
 src/udev/udev-event.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index 5213a4a..4d6afad 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -754,6 +754,7 @@ static int rename_netif(struct udev_event *event)
         char name[IFNAMSIZ];
         const char *oldname;
         int r;
+        int loop;
 
         oldname = udev_device_get_sysname(dev);
 
@@ -767,12 +768,44 @@ static int rename_netif(struct udev_event *event)
                 return r;
 
         r = rtnl_set_link_name(rtnl, udev_device_get_ifindex(dev), name);
-        if (r < 0)
-                log_error("error changing net interface name %s to %s: %s",
-                          oldname, name, strerror(-r));
-        else
+        if (r >= 0) {
                 print_kmsg("renamed network interface %s to %s\n", oldname, name);
+                goto out;
+        }
+
+        /* keep trying if the destination interface name already exists */
+        if (r != -EEXIST)
+                goto out;
 
+        /* free our own name, another process may wait for us */
+        snprintf(name, IFNAMSIZ, "rename%u", udev_device_get_ifindex(dev));
+        r = rtnl_set_link_name(rtnl, udev_device_get_ifindex(dev), name);
+        if (r < 0)
+          goto out;
+
+        /* log temporary name */
+        print_kmsg("renamed network interface %s to %s\n", oldname, name);
+
+        /* wait a maximum of 90 seconds for our target to become available */
+        strscpy(name, IFNAMSIZ, event->name);
+        loop = 90 * 20;
+        while (loop--) {
+                const struct timespec duration = { 0, 1000 * 1000 * 1000 / 20 };
+
+                nanosleep(&duration, NULL);
+
+                r = rtnl_set_link_name(rtnl, udev_device_get_ifindex(dev), name);
+                if (r >= 0) {
+                        print_kmsg("renamed network interface %s to %s\n", oldname, name);
+                        break;
+                }
+                if (r != -EEXIST)
+                        break;
+        }
+
+out:
+        if (r < 0)
+                log_error("error changing net interface name %s to %s: %m\n", oldname, name);
         return r;
 }
 
