Re: [PATCH 5/5] netdevveth: Simplify virNetDevVethCreate by using virNetDevGenerateName

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/4/20 2:01 AM, Shi Lei wrote:
Simplify virNetDevVethCreate by using common GenerateName/ReserveName
functions.

Signed-off-by: Shi Lei <shi_lei@xxxxxxxxxxxxxx>
---
  src/lxc/lxc_process.c    |   3 +
  src/util/virnetdevveth.c | 146 +++++++++++----------------------------
  2 files changed, 43 insertions(+), 106 deletions(-)

diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 7e07f49f..5f277a22 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -287,6 +287,9 @@ virLXCProcessSetupInterfaceTap(virDomainDefPtr vm,
VIR_DEBUG("calling vethCreate()");
      parentVeth = net->ifname;
+    if (parentVeth)
+        virNetDevReserveName(parentVeth, VIR_NET_DEV_GEN_NAME_VETH, true);
+
      if (virNetDevVethCreate(&parentVeth, &containerVeth) < 0)
          return NULL;
      VIR_DEBUG("parentVeth: %s, containerVeth: %s", parentVeth, containerVeth);
diff --git a/src/util/virnetdevveth.c b/src/util/virnetdevveth.c
index b3eee1af..2e3d0c82 100644
--- a/src/util/virnetdevveth.c
+++ b/src/util/virnetdevveth.c
@@ -32,48 +32,6 @@
VIR_LOG_INIT("util.netdevveth"); -/* Functions */
-
-virMutex virNetDevVethCreateMutex = VIR_MUTEX_INITIALIZER;
-
-static int virNetDevVethExists(int devNum)
-{
-    int ret;
-    g_autofree char *path = NULL;
-
-    path = g_strdup_printf(SYSFS_NET_DIR "vnet%d/", devNum);
-    ret = virFileExists(path) ? 1 : 0;
-    VIR_DEBUG("Checked dev vnet%d usage: %d", devNum, ret);
-    return ret;
-}
-
-/**
- * virNetDevVethGetFreeNum:
- * @startDev: device number to start at (x in vethx)
- *
- * Looks in /sys/class/net/ to find the first available veth device
- * name.
- *
- * Returns non-negative device number on success or -1 in case of error
- */
-static int virNetDevVethGetFreeNum(int startDev)
-{
-    int devNum;
-
-#define MAX_DEV_NUM 65536
-
-    for (devNum = startDev; devNum < MAX_DEV_NUM; devNum++) {
-        int ret = virNetDevVethExists(devNum);
-        if (ret < 0)
-            return -1;
-        if (ret == 0)
-            return devNum;
-    }
-
-    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                   _("No free veth devices available"));
-    return -1;
-}
/**
   * virNetDevVethCreate:
@@ -102,77 +60,53 @@ static int virNetDevVethGetFreeNum(int startDev)
   */
  int virNetDevVethCreate(char** veth1, char** veth2)
  {
-    int ret = -1;
-    int vethNum = 0;
-    size_t i;
-
-    /*
-     * We might race with other containers, but this is reasonably
-     * unlikely, so don't do too many retries for device creation
-     */
-    virMutexLock(&virNetDevVethCreateMutex);
-#define MAX_VETH_RETRIES 10
-
-    for (i = 0; i < MAX_VETH_RETRIES; i++) {
-        g_autofree char *veth1auto = NULL;
-        g_autofree char *veth2auto = NULL;
-        g_autoptr(virCommand) cmd = NULL;
-
-        int status;
-        if (!*veth1) {
-            int veth1num;
-            if ((veth1num = virNetDevVethGetFreeNum(vethNum)) < 0)
-                goto cleanup;
-
-            veth1auto = g_strdup_printf("vnet%d", veth1num);
-            vethNum = veth1num + 1;
-        }
-        if (!*veth2) {
-            int veth2num;
-            if ((veth2num = virNetDevVethGetFreeNum(vethNum)) < 0)
-                goto cleanup;
+    int status;
+    g_autofree char *veth1auto = NULL;
+    g_autofree char *veth2auto = NULL;
+    g_autoptr(virCommand) cmd = NULL;
- veth2auto = g_strdup_printf("vnet%d", veth2num);
-            vethNum = veth2num + 1;
-        }
+    virNetDevLockGenName(VIR_NET_DEV_GEN_NAME_VETH);
- cmd = virCommandNew("ip");
-        virCommandAddArgList(cmd, "link", "add",
-                             *veth1 ? *veth1 : veth1auto,
-                             "type", "veth", "peer", "name",
-                             *veth2 ? *veth2 : veth2auto,
-                             NULL);
-
-        if (virCommandRun(cmd, &status) < 0)
-            goto cleanup;
-
-        if (status == 0) {
-            if (veth1auto) {
-                *veth1 = veth1auto;
-                veth1auto = NULL;
-            }
-            if (veth2auto) {
-                *veth2 = veth2auto;
-                veth2auto = NULL;
-            }
-            VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2);
-            ret = 0;
-            goto cleanup;
+    if (!*veth1) {
+        if (virNetDevGenerateName(&veth1auto, VIR_NET_DEV_GEN_NAME_VETH) < 0) {
+            virNetDevUnlockGenName(VIR_NET_DEV_GEN_NAME_VETH);
+            return -1;
+        }
+    }
+    if (!*veth2) {
+        if (virNetDevGenerateName(&veth2auto, VIR_NET_DEV_GEN_NAME_VETH) < 0) {
+            virNetDevUnlockGenName(VIR_NET_DEV_GEN_NAME_VETH);
+            return -1;
          }
+    }
+
+    virNetDevUnlockGenName(VIR_NET_DEV_GEN_NAME_VETH);


I can't think of a scenario where it would actually solve any race condition, but in the tap and macvlan uses, the lock is acquired before generating the new name, and not cleared until after the new device is created. I guess really since the libvirtd process will never use the same name twice, and since all the locking we could ever put within libvirtd will not prevent some *other* process from using the name we've just chosen, that it's unnecessary to hold the lock for so long in the other cases - i.e., while typing this I've convinced myself not that we should move this unlock down further, but that we can shorten the section where we hold the lock in the tap and macvlan cases.


- VIR_DEBUG("Failed to create veth host: %s guest: %s: %d",
-                  *veth1 ? *veth1 : veth1auto,
-                  *veth2 ? *veth2 : veth2auto,
-                  status);
+    cmd = virCommandNew("ip");
+    virCommandAddArgList(cmd, "link", "add",
+                         *veth1 ? *veth1 : veth1auto,
+                         "type", "veth", "peer", "name",
+                         *veth2 ? *veth2 : veth2auto,
+                         NULL);
+
+    if (virCommandRun(cmd, &status) < 0 || status) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("Failed to allocate free veth pair"));
+        return -1;
      }
- virReportError(VIR_ERR_INTERNAL_ERROR,
-                   _("Failed to allocate free veth pair after %d attempts"),
-                   MAX_VETH_RETRIES);
+    VIR_DEBUG("create veth host: %s guest: %s: %d",
+              *veth1 ? *veth1 : veth1auto,
+              *veth2 ? *veth2 : veth2auto,
+              status);
+
+    if (veth1auto)
+        *veth1 = g_steal_pointer(&veth1auto);
+    if (veth2auto)
+        *veth2 = g_steal_pointer(&veth2auto);
- cleanup:
-    virMutexUnlock(&virNetDevVethCreateMutex);
-    return ret;
+    VIR_DEBUG("Create Host: %s guest: %s", *veth1, *veth2);
+    return 0;
  }
/**


(Definitely after going through these patches, I think that this series should be applied *before* the "use netlink to create veth devices" series, and that that series should get rid of the "status" arg to VethCreate())




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux