--- daemon/dispatch.c | 2 - daemon/libvirtd.c | 62 +++++++++++++++++++++++++++++++++++++++------------- daemon/libvirtd.h | 5 ++- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/daemon/dispatch.c b/daemon/dispatch.c index 4814017..b2d6927 100644 --- a/daemon/dispatch.c +++ b/daemon/dispatch.c @@ -524,9 +524,7 @@ remoteDispatchClientCall (struct qemud_server *server, */ rv = (data->fn)(server, client, conn, &msg->hdr, &rerr, &args, &ret); - virMutexLock(&server->lock); virMutexLock(&client->lock); - virMutexUnlock(&server->lock); xdr_free (data->args_filter, (char*)&args); diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 42cbe5d..d3ba97b 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -270,6 +270,8 @@ static void sig_fatal(int sig, siginfo_t * siginfo ATTRIBUTE_UNUSED, static void qemudDispatchClientEvent(int watch, int fd, int events, void *opaque); static void qemudDispatchServerEvent(int watch, int fd, int events, void *opaque); static int qemudStartWorker(struct qemud_server *server, struct qemud_worker *worker); +static void qemudClientRef(struct qemud_client *client); +static void qemudClientUnref(struct qemud_client *client); void qemudClientMessageQueuePush(struct qemud_client_message **queue, @@ -1338,6 +1340,8 @@ int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid) { #endif +static void qemudFreeClient(virObjectPtr obj); + static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket *sock) { int fd; virSocketAddr addr; @@ -1411,6 +1415,10 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket VIR_ERROR0(_("cannot initialize mutex")); goto error; } + if (virObjectInit(&client->obj, qemudFreeClient)) { + VIR_ERROR0(_("cannot initialize virobject")); + goto error; + } client->magic = QEMUD_CLIENT_MAGIC; client->fd = fd; @@ -1576,12 +1584,10 @@ static struct qemud_client *qemudPendingJob(struct qemud_server *server) { int i; for (i = 0 ; i < server->nclients ; i++) { - virMutexLock(&server->clients[i]->lock); if (server->clients[i]->dx) { - /* Delibrately don't unlock client - caller wants the lock */ + qemudClientRef(server->clients[i]); return server->clients[i]; } - virMutexUnlock(&server->clients[i]->lock); } return NULL; } @@ -1604,31 +1610,36 @@ static void *qemudWorker(void *data) } } if (worker->quitRequest) { - virMutexUnlock(&client->lock); virMutexUnlock(&server->lock); + qemudClientUnref(client); return NULL; } worker->processingCall = 1; virMutexUnlock(&server->lock); - /* We own a locked client now... */ - client->refs++; + virMutexLock(&client->lock); /* Remove our message from dispatch queue while we use it */ msg = qemudClientMessageQueueServe(&client->dx); + if (!msg) { + virMutexUnlock(&client->lock); + qemudClientUnref(client); + continue; + } + /* This function drops the lock during dispatch, * and re-acquires it before returning */ if (remoteDispatchClientRequest (server, client, msg) < 0) { VIR_FREE(msg); qemudDispatchClientFailure(client); - client->refs--; virMutexUnlock(&client->lock); + qemudClientUnref(client); continue; } - client->refs--; virMutexUnlock(&client->lock); + qemudClientUnref(client); virMutexLock(&server->lock); worker->processingCall = 0; @@ -2155,6 +2166,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { virMutexLock(&server->clients[i]->lock); if (server->clients[i]->watch == watch) { client = server->clients[i]; + qemudClientRef(client); break; } virMutexUnlock(&server->clients[i]->lock); @@ -2168,6 +2180,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { if (client->fd != fd) { virMutexUnlock(&client->lock); + qemudClientUnref(client); return; } @@ -2190,6 +2203,7 @@ qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) { qemudDispatchClientFailure(client); virMutexUnlock(&client->lock); + qemudClientUnref(client); } @@ -2306,7 +2320,9 @@ static void qemudInactiveTimer(int timerid, void *data) { } } -static void qemudFreeClient(struct qemud_client *client) { +static void qemudFreeClient(virObjectPtr obj) { + struct qemud_client *client = (struct qemud_client *)obj; + while (client->rx) { struct qemud_client_message *msg = qemudClientMessageQueueServe(&client->rx); @@ -2333,6 +2349,16 @@ static void qemudFreeClient(struct qemud_client *client) { VIR_FREE(client); } +static void qemudClientRef(struct qemud_client *client) +{ + virObjectRef(&client->obj); +} + +static void qemudClientUnref(struct qemud_client *client) +{ + virObjectUnref(&client->obj); +} + static void *qemudRunLoop(void *opaque) { struct qemud_server *server = opaque; int timerid = -1; @@ -2396,13 +2422,17 @@ static void *qemudRunLoop(void *opaque) { reprocess: for (i = 0 ; i < server->nclients ; i++) { - int inactive; + struct qemud_client *client = NULL; virMutexLock(&server->clients[i]->lock); - inactive = server->clients[i]->fd == -1 - && server->clients[i]->refs == 0; - virMutexUnlock(&server->clients[i]->lock); - if (inactive) { - qemudFreeClient(server->clients[i]); + if (server->clients[i]->fd == -1) { + client = server->clients[i]; + server->clients[i] = NULL; + } + if (!client) { + virMutexUnlock(&server->clients[i]->lock); + } else { + virMutexUnlock(&client->lock); + qemudClientUnref(client); server->nclients--; if (i < server->nclients) memmove(server->clients + i, @@ -2451,7 +2481,7 @@ cleanup: } VIR_FREE(server->workers); for (i = 0; i < server->nclients; i++) - qemudFreeClient(server->clients[i]); + qemudClientUnref(server->clients[i]); server->nclients = 0; VIR_SHRINK_N(server->clients, server->nclients_max, server->nclients_max); diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index d37c3fd..5ac4eb3 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -49,6 +49,7 @@ # include "logging.h" # include "threads.h" # include "network.h" +# include "virobject.h" # if WITH_DTRACE # ifndef LIBVIRTD_PROBES_H @@ -186,6 +187,8 @@ struct qemud_client_stream { /* Stores the per-client connection state */ struct qemud_client { + virObject obj; /* should be the first member */ + virMutex lock; int magic; @@ -243,8 +246,6 @@ struct qemud_client { * called, it will be set back to NULL if that succeeds. */ virConnectPtr conn; - int refs; - }; # define QEMUD_CLIENT_MAGIC 0x7788aaee -- 1.7.3.1 -- Thanks, Hu Tao -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list