From: "Daniel P. Berrange" <berrange(a)redhat.com>
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