[PATCH 6/7] Convert QEMU driver over to use virPortAllocator APIs

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

 



From: "Daniel P. Berrange" <berrange@xxxxxxxxxx>

Replace the current QEMU driver code for managing port
reservations with the new virPortAllocator APIs.
---
 src/qemu/qemu_conf.h        |   4 +-
 src/qemu/qemu_driver.c      |   9 ++--
 src/qemu/qemu_process.c     | 100 ++++++++------------------------------------
 src/util/virportallocator.c |   3 +-
 4 files changed, 27 insertions(+), 89 deletions(-)

diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 965eff7..6009118 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -39,7 +39,7 @@
 # include "virusb.h"
 # include "cpu_conf.h"
 # include "driver.h"
-# include "virbitmap.h"
+# include "virportallocator.h"
 # include "vircommand.h"
 # include "virthreadpool.h"
 # include "locking/lock_manager.h"
@@ -150,7 +150,7 @@ struct _virQEMUDriver {
 
     virHashTablePtr sharedDisks;
 
-    virBitmapPtr reservedRemotePorts;
+    virPortAllocatorPtr remotePorts;
 
     virSysinfoDefPtr hostsysinfo;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ab1fd4c..2147983 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -809,9 +809,10 @@ qemuStartup(bool privileged,
     /* Allocate bitmap for remote display port reservations. We cannot
      * do this before the config is loaded properly, since the port
      * numbers are configurable now */
-    if ((qemu_driver->reservedRemotePorts =
-         virBitmapNew(qemu_driver->remotePortMax - qemu_driver->remotePortMin)) == NULL)
-        goto out_of_memory;
+    if ((qemu_driver->remotePorts =
+         virPortAllocatorNew(qemu_driver->remotePortMin,
+                             qemu_driver->remotePortMax)) == NULL)
+        goto error;
 
     /* We should always at least have the 'nop' manager, so
      * NULLs here are a fatal error
@@ -1104,7 +1105,7 @@ qemuShutdown(void) {
     qemuCapsCacheFree(qemu_driver->capsCache);
 
     virDomainObjListDeinit(&qemu_driver->domains);
-    virBitmapFree(qemu_driver->reservedRemotePorts);
+    virObjectUnref(qemu_driver->remotePorts);
 
     virSysinfoDefFree(qemu_driver->hostsysinfo);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c8c898f..84ba53b 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2603,73 +2603,6 @@ qemuProcessInitPCIAddresses(virQEMUDriverPtr driver,
 }
 
 
-static int qemuProcessNextFreePort(virQEMUDriverPtr driver,
-                                   int startPort)
-{
-    int i;
-
-    for (i = startPort ; i < driver->remotePortMax; i++) {
-        int fd;
-        int reuse = 1;
-        struct sockaddr_in addr;
-        bool used = false;
-
-        if (virBitmapGetBit(driver->reservedRemotePorts,
-                            i - driver->remotePortMin, &used) < 0)
-            VIR_DEBUG("virBitmapGetBit failed on bit %d", i - driver->remotePortMin);
-
-        if (used)
-            continue;
-
-        addr.sin_family = AF_INET;
-        addr.sin_port = htons(i);
-        addr.sin_addr.s_addr = htonl(INADDR_ANY);
-        fd = socket(PF_INET, SOCK_STREAM, 0);
-        if (fd < 0)
-            return -1;
-
-        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse, sizeof(reuse)) < 0) {
-            VIR_FORCE_CLOSE(fd);
-            break;
-        }
-
-        if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
-            /* Not in use, lets grab it */
-            VIR_FORCE_CLOSE(fd);
-            /* Add port to bitmap of reserved ports */
-            if (virBitmapSetBit(driver->reservedRemotePorts,
-                                i - driver->remotePortMin) < 0) {
-                VIR_DEBUG("virBitmapSetBit failed on bit %d",
-                          i - driver->remotePortMin);
-            }
-            return i;
-        }
-        VIR_FORCE_CLOSE(fd);
-
-        if (errno == EADDRINUSE) {
-            /* In use, try next */
-            continue;
-        }
-        /* Some other bad failure, get out.. */
-        break;
-    }
-    return -1;
-}
-
-
-static void
-qemuProcessReturnPort(virQEMUDriverPtr driver,
-                      int port)
-{
-    if (port < driver->remotePortMin)
-        return;
-
-    if (virBitmapClearBit(driver->reservedRemotePorts,
-                          port - driver->remotePortMin) < 0)
-        VIR_DEBUG("Could not mark port %d as unused", port);
-}
-
-
 static int
 qemuProcessPrepareChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
                                 virDomainChrDefPtr dev,
@@ -3664,20 +3597,18 @@ int qemuProcessStart(virConnectPtr conn,
         if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
             !graphics->data.vnc.socket &&
             graphics->data.vnc.autoport) {
-            int port = qemuProcessNextFreePort(driver, driver->remotePortMin);
-            if (port < 0) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               "%s", _("Unable to find an unused port for VNC"));
+            unsigned short port;
+            if (virPortAllocatorAcquire(driver->remotePorts, &port) < 0)
                 goto cleanup;
-            }
             graphics->data.vnc.port = port;
         } else if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
-            int port = -1;
+            unsigned short port = 0;
             if (graphics->data.spice.autoport ||
                 graphics->data.spice.port == -1) {
-                port = qemuProcessNextFreePort(driver, driver->remotePortMin);
+                if (virPortAllocatorAcquire(driver->remotePorts, &port) < 0)
+                    goto cleanup;
 
-                if (port < 0) {
+                if (port == 0) {
                     virReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Unable to find an unused port for SPICE"));
                     goto cleanup;
@@ -3688,12 +3619,14 @@ int qemuProcessStart(virConnectPtr conn,
             if (driver->spiceTLS &&
                 (graphics->data.spice.autoport ||
                  graphics->data.spice.tlsPort == -1)) {
-                int tlsPort = qemuProcessNextFreePort(driver,
-                                                      graphics->data.spice.port + 1);
-                if (tlsPort < 0) {
+                unsigned short tlsPort;
+                if (virPortAllocatorAcquire(driver->remotePorts, &tlsPort) < 0)
+                    goto cleanup;
+
+                if (tlsPort == 0) {
                     virReportError(VIR_ERR_INTERNAL_ERROR,
                                    "%s", _("Unable to find an unused port for SPICE TLS"));
-                    qemuProcessReturnPort(driver, port);
+                    virPortAllocatorRelease(driver->remotePorts, port);
                     goto cleanup;
                 }
 
@@ -4362,12 +4295,15 @@ retry:
         virDomainGraphicsDefPtr graphics = vm->def->graphics[i];
         if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
             graphics->data.vnc.autoport) {
-            qemuProcessReturnPort(driver, graphics->data.vnc.port);
+            ignore_value(virPortAllocatorRelease(driver->remotePorts,
+                                                 graphics->data.vnc.port));
         }
         if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
             graphics->data.spice.autoport) {
-            qemuProcessReturnPort(driver, graphics->data.spice.port);
-            qemuProcessReturnPort(driver, graphics->data.spice.tlsPort);
+            ignore_value(virPortAllocatorRelease(driver->remotePorts,
+                                                 graphics->data.spice.port));
+            ignore_value(virPortAllocatorRelease(driver->remotePorts,
+                                                 graphics->data.spice.tlsPort));
         }
     }
 
diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c
index 2c27711..1b45d33 100644
--- a/src/util/virportallocator.c
+++ b/src/util/virportallocator.c
@@ -103,7 +103,7 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa,
     *port = 0;
     virObjectLock(pa);
 
-    for (i = pa->start ; i < pa->end && fd == -1; i++) {
+    for (i = pa->start ; i < pa->end && !*port; i++) {
         int reuse = 1;
         struct sockaddr_in addr;
         bool used = false;
@@ -150,6 +150,7 @@ int virPortAllocatorAcquire(virPortAllocatorPtr pa,
                                _("Failed to reserve port %d"), i);
                 goto cleanup;
             }
+            *port = i;
         }
     }
 
-- 
1.8.0.1

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[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]