[libvirt] [PATCH 2/6] use virObject to manage reference-count of qemud_client

Hu Tao hutao at cn.fujitsu.com
Wed Apr 6 07:19:46 UTC 2011


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




More information about the libvir-list mailing list