From 40b01761291907c024441f8d5bfb349fe3de0069 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Tue, 17 Jul 2012 16:36:23 +0200 Subject: [PATCH] remote: Fix locking in stream APIs 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 | 40 ++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index af46384441..0f8d6071f3 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -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);