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