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 17f3be079c)
This commit is contained in:
Jiri Denemark 2012-07-17 16:36:23 +02:00 committed by Cole Robinson
parent cba63bbc22
commit 40b0176129

View 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);