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