diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0d7c9757b764aec9c103ec6f1eb236d47309bd2f..a859810a2ce0adfb6146086705519a3f1fe2e551 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1322,6 +1322,8 @@ virNetClientNewExternal; virNetClientNewSSH; virNetClientNewTCP; virNetClientNewUNIX; +virNetClientRegisterAsyncIO; +virNetClientRegisterKeepAlive; virNetClientRemoteAddrString; virNetClientRemoveStream; virNetClientSendNoReply; diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index a81d0f7778e04582a364ce011f3902bf99beb506..53ecd6077359e419f10a4add7b073de3c7c252a9 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -129,6 +129,8 @@ virLXCMonitorPtr virLXCMonitorNew(virDomainObjPtr vm, if (!(mon->client = virNetClientNewUNIX(sockpath, false, NULL))) goto error; + if (virNetClientRegisterAsyncIO(mon->client) < 0) + goto error; if (!(mon->program = virNetClientProgramNew(VIR_LXC_PROTOCOL_PROGRAM, VIR_LXC_PROTOCOL_PROGRAM_VERSION, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8153d70da54f430c8da3bf5b4a5bd232701958db..c4941c537882018b6a4a11695694e8650e60c77c 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -686,6 +686,15 @@ doRemoteOpen(virConnectPtr conn, } /* switch (transport) */ + if (virNetClientRegisterAsyncIO(priv->client) < 0) { + VIR_DEBUG("Failed to add event watch, disabling events and support for" + " keepalive messages"); + virResetLastError(); + } else { + if (virNetClientRegisterKeepAlive(priv->client) < 0) + goto failed; + } + virNetClientSetCloseCallback(priv->client, remoteClientCloseFunc, conn, NULL); diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index 42bdc54d45f507b86b130dadde4068c050b7cd8c..cec5efbba6d0cc8920a617a5966733d32eb9b374 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -68,6 +68,7 @@ struct _virNetClient { virMutex lock; virNetSocketPtr sock; + bool asyncIO; virNetTLSSessionPtr tls; char *hostname; @@ -309,7 +310,6 @@ static virNetClientPtr virNetClientNew(virNetSocketPtr sock, { virNetClientPtr client = NULL; int wakeupFD[2] = { -1, -1 }; - virKeepAlivePtr ka = NULL; if (virNetClientInitialize() < 0) return NULL; @@ -337,29 +337,6 @@ static virNetClientPtr virNetClientNew(virNetSocketPtr sock, !(client->hostname = strdup(hostname))) goto no_memory; - /* Set up a callback to listen on the socket data */ - virObjectRef(client); - if (virNetSocketAddIOCallback(client->sock, - VIR_EVENT_HANDLE_READABLE, - virNetClientIncomingEvent, - client, - virObjectFreeCallback) < 0) { - virObjectUnref(client); - VIR_DEBUG("Failed to add event watch, disabling events and support for" - " keepalive messages"); - } else { - /* Keepalive protocol consists of async messages so it can only be used - * if the client supports them */ - if (!(ka = virKeepAliveNew(-1, 0, client, - virNetClientKeepAliveSendCB, - virNetClientKeepAliveDeadCB, - virObjectFreeCallback))) - goto error; - /* keepalive object has a reference to client */ - virObjectRef(client); - } - - client->keepalive = ka; PROBE(RPC_CLIENT_NEW, "client=%p sock=%p", client, client->sock); @@ -370,10 +347,6 @@ no_memory: error: VIR_FORCE_CLOSE(wakeupFD[0]); VIR_FORCE_CLOSE(wakeupFD[1]); - if (ka) { - virKeepAliveStop(ka); - virObjectUnref(ka); - } virObjectUnref(client); return NULL; } @@ -433,6 +406,58 @@ virNetClientPtr virNetClientNewExternal(const char **cmdargv) } +int virNetClientRegisterAsyncIO(virNetClientPtr client) +{ + if (client->asyncIO) + return 0; + + /* Set up a callback to listen on the socket data */ + virObjectRef(client); + if (virNetSocketAddIOCallback(client->sock, + VIR_EVENT_HANDLE_READABLE, + virNetClientIncomingEvent, + client, + virObjectFreeCallback) < 0) { + virObjectUnref(client); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to register async IO callback")); + return -1; + } + + client->asyncIO = true; + return 0; +} + + +int virNetClientRegisterKeepAlive(virNetClientPtr client) +{ + virKeepAlivePtr ka; + + if (client->keepalive) + return 0; + + if (!client->asyncIO) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Unable to enable keepalives without async IO support")); + return -1; + } + + /* Keepalive protocol consists of async messages so it can only be used + * if the client supports them */ + if (!(ka = virKeepAliveNew(-1, 0, client, + virNetClientKeepAliveSendCB, + virNetClientKeepAliveDeadCB, + virObjectFreeCallback))) + return -1; + + /* keepalive object has a reference to client */ + virObjectRef(client); + + client->keepalive = ka; + return 0; +} + + int virNetClientGetFD(virNetClientPtr client) { int fd; diff --git a/src/rpc/virnetclient.h b/src/rpc/virnetclient.h index d6b9b3c1d62a960051c1853be9511a44b2d27638..3d55a74e05e6084de178629b6dc72ff0cd562a42 100644 --- a/src/rpc/virnetclient.h +++ b/src/rpc/virnetclient.h @@ -52,6 +52,9 @@ virNetClientPtr virNetClientNewSSH(const char *nodename, virNetClientPtr virNetClientNewExternal(const char **cmdargv); +int virNetClientRegisterAsyncIO(virNetClientPtr client); +int virNetClientRegisterKeepAlive(virNetClientPtr client); + typedef void (*virNetClientCloseFunc)(virNetClientPtr client, int reason, void *opaque);