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. --- 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 3314f80..acae5d0 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -3976,12 +3976,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, @@ -3989,9 +3991,9 @@ remoteStreamSend(virStreamPtr st, data, nbytes); -cleanup: + remoteDriverLock(priv); + priv->localUses--; remoteDriverUnlock(priv); - return rv; } @@ -4004,12 +4006,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, @@ -4019,9 +4023,9 @@ remoteStreamRecv(virStreamPtr st, VIR_DEBUG("Done %d", rv); -cleanup: + remoteDriverLock(priv); + priv->localUses--; remoteDriverUnlock(priv); - return rv; } @@ -4138,12 +4142,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); @@ -4167,12 +4177,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); -- 1.7.11.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list