]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
remote: Fix locking in stream APIs
authorJiri Denemark <jdenemar@redhat.com>
Tue, 17 Jul 2012 14:36:23 +0000 (16:36 +0200)
committerCole Robinson <crobinso@redhat.com>
Sun, 12 Aug 2012 23:23:51 +0000 (19:23 -0400)
Remote driver needs to make sure the driver lock is released before
entering client IO loop as that may block indefinitely in poll(). As a
direct consequence of not following this in stream APIs, tunneled
migration to a destination host which becomes non-responding may block
qemu driver. Luckily, if keepalive is turned for p2p migrations, both
remote and qemu drivers will get automagically unblocked after keepalive
timeout.
(cherry picked from commit 17f3be079c3c421eff203fcd311b0357ec42d801)

src/remote/remote_driver.c

index af463844418c06154e562cdef8a5d6ab5482e85e..0f8d6071f342d80d7c10aa9ef48bcb725f6ecb47 100644 (file)
@@ -3882,12 +3882,14 @@ remoteStreamSend(virStreamPtr st,
     VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
     struct private_data *priv = st->conn->privateData;
     virNetClientStreamPtr privst = st->privateData;
-    int rv = -1;
-
-    remoteDriverLock(priv);
+    int rv;
 
     if (virNetClientStreamRaiseError(privst))
-        goto cleanup;
+        return -1;
+
+    remoteDriverLock(priv);
+    priv->localUses++;
+    remoteDriverUnlock(priv);
 
     rv = virNetClientStreamSendPacket(privst,
                                       priv->client,
@@ -3895,9 +3897,9 @@ remoteStreamSend(virStreamPtr st,
                                       data,
                                       nbytes);
 
-cleanup:
+    remoteDriverLock(priv);
+    priv->localUses--;
     remoteDriverUnlock(priv);
-
     return rv;
 }
 
@@ -3910,12 +3912,14 @@ remoteStreamRecv(virStreamPtr st,
     VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
     struct private_data *priv = st->conn->privateData;
     virNetClientStreamPtr privst = st->privateData;
-    int rv = -1;
-
-    remoteDriverLock(priv);
+    int rv;
 
     if (virNetClientStreamRaiseError(privst))
-        goto cleanup;
+        return -1;
+
+    remoteDriverLock(priv);
+    priv->localUses++;
+    remoteDriverUnlock(priv);
 
     rv = virNetClientStreamRecvPacket(privst,
                                       priv->client,
@@ -3925,9 +3929,9 @@ remoteStreamRecv(virStreamPtr st,
 
     VIR_DEBUG("Done %d", rv);
 
-cleanup:
+    remoteDriverLock(priv);
+    priv->localUses--;
     remoteDriverUnlock(priv);
-
     return rv;
 }
 
@@ -4044,12 +4048,18 @@ remoteStreamFinish(virStreamPtr st)
     if (virNetClientStreamRaiseError(privst))
         goto cleanup;
 
+    priv->localUses++;
+    remoteDriverUnlock(priv);
+
     ret = virNetClientStreamSendPacket(privst,
                                        priv->client,
                                        VIR_NET_OK,
                                        NULL,
                                        0);
 
+    remoteDriverLock(priv);
+    priv->localUses--;
+
 cleanup:
     virNetClientRemoveStream(priv->client, privst);
     virNetClientStreamFree(privst);
@@ -4073,12 +4083,18 @@ remoteStreamAbort(virStreamPtr st)
     if (virNetClientStreamRaiseError(privst))
         goto cleanup;
 
+    priv->localUses++;
+    remoteDriverUnlock(priv);
+
     ret = virNetClientStreamSendPacket(privst,
                                        priv->client,
                                        VIR_NET_ERROR,
                                        NULL,
                                        0);
 
+    remoteDriverLock(priv);
+    priv->localUses--;
+
 cleanup:
     virNetClientRemoveStream(priv->client, privst);
     virNetClientStreamFree(privst);