[libvirt] [PATCH 07/10] qemu: agent: simplify io loop
Nikolay Shirokovskiy
nshirokovskiy at virtuozzo.com
Thu Oct 27 12:46:50 UTC 2016
On 26.10.2016 23:48, John Ferlan wrote:
>
>
> On 10/04/2016 02:56 AM, Nikolay Shirokovskiy wrote:
>> Now we don't need to differentiate error and eof cases in the loop function.
>> So let's simplify it radically using goto instead of flags.
>> ---
>> src/qemu/qemu_agent.c | 185 ++++++++++++++++++-------------------------
>> src/qemu/qemu_agent.h | 2 -
>> src/qemu/qemu_process.c | 22 +----
>> tests/qemumonitortestutils.c | 1 -
>> 4 files changed, 83 insertions(+), 127 deletions(-)
>>
>
> I would think it's understood the genesis of this comes from
> qemuMonitorIO (tripped me up in my patch 1 review too, but still the
> same result)...
>
> Part of me believes whatever happens here could be considered for
> qemuMonitorIO too, but that's perhaps a bigger hurdle to jump.
>
> I'm not sure why we want to make Error and EOF be the same thing.
I would not put the change this way. It is just doesn't matter for
us - EOF or error. The cause is different, the result is same.
Then why keep this overwhelming logic in event loop? Just compare
qemuAgentIO before and after the patch...
Nikolay
>
>> diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
>> index ec8d47e..43d78c9 100644
>> --- a/src/qemu/qemu_agent.c
>> +++ b/src/qemu/qemu_agent.c
>> @@ -595,8 +595,8 @@ static void
>> qemuAgentIO(int watch, int fd, int events, void *opaque)
>> {
>> qemuAgentPtr mon = opaque;
>> - bool error = false;
>> - bool eof = false;
>> + void (*errorNotify)(qemuAgentPtr, virDomainObjPtr);
>> + virDomainObjPtr vm;
>>
>> virObjectRef(mon);
>> /* lock access to the monitor and protect fd */
>> @@ -606,122 +606,95 @@ qemuAgentIO(int watch, int fd, int events, void *opaque)
>> #endif
>>
>> if (mon->fd != fd || mon->watch != watch) {
>> - if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
>> - eof = true;
>> virReportError(VIR_ERR_INTERNAL_ERROR,
>> _("event from unexpected fd %d!=%d / watch %d!=%d"),
>> mon->fd, fd, mon->watch, watch);
>> - error = true;
>> - } else if (mon->lastError.code != VIR_ERR_OK) {
>> - if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
>> - eof = true;
>> - error = true;
>> - } else {
>> - if (events & VIR_EVENT_HANDLE_WRITABLE) {
>> - if (mon->connectPending) {
>> - if (qemuAgentIOConnect(mon) < 0)
>> - error = true;
>> - } else {
>> - if (qemuAgentIOWrite(mon) < 0)
>> - error = true;
>> - }
>> - events &= ~VIR_EVENT_HANDLE_WRITABLE;
>> - }
>> -
>> - if (!error &&
>> - events & VIR_EVENT_HANDLE_READABLE) {
>> - int got = qemuAgentIORead(mon);
>> - events &= ~VIR_EVENT_HANDLE_READABLE;
>> - if (got < 0) {
>> - error = true;
>> - } else if (got == 0) {
>> - eof = true;
>> - } else {
>> - /* Ignore hangup/error events if we read some data, to
>> - * give time for that data to be consumed */
>> - events = 0;
>> -
>> - if (qemuAgentIOProcess(mon) < 0)
>> - error = true;
>> - }
>> - }
>> -
>> - if (!error &&
>> - events & VIR_EVENT_HANDLE_HANGUP) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("End of file from agent monitor"));
>> - eof = true;
>> - events &= ~VIR_EVENT_HANDLE_HANGUP;
>> - }
>> -
>> - if (!error && !eof &&
>> - events & VIR_EVENT_HANDLE_ERROR) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("Invalid file descriptor while waiting for monitor"));
>> - eof = true;
>> - events &= ~VIR_EVENT_HANDLE_ERROR;
>> - }
>> - if (!error && events) {
>> - virReportError(VIR_ERR_INTERNAL_ERROR,
>> - _("Unhandled event %d for monitor fd %d"),
>> - events, mon->fd);
>> - error = true;
>> - }
>> + goto error;
>> }
>>
>> - if (error || eof) {
>> - if (mon->lastError.code != VIR_ERR_OK) {
>> - /* Already have an error, so clear any new error */
>> - virResetLastError();
>> + if (mon->lastError.code != VIR_ERR_OK)
>> + goto error;
>> +
>> + if (events & VIR_EVENT_HANDLE_WRITABLE) {
>> + if (mon->connectPending) {
>> + if (qemuAgentIOConnect(mon) < 0)
>> + goto error;
>> } else {
>> - virErrorPtr err = virGetLastError();
>> - if (!err)
>> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("Error while processing monitor IO"));
>> - virCopyLastError(&mon->lastError);
>> - virResetLastError();
>> + if (qemuAgentIOWrite(mon) < 0)
>> + goto error;
>> }
>> + events &= ~VIR_EVENT_HANDLE_WRITABLE;
>> + }
>>
>> - VIR_DEBUG("Error on monitor %s", NULLSTR(mon->lastError.message));
>> - /* If IO process resulted in an error & we have a message,
>> - * then wakeup that waiter */
>> - if (mon->msg && !mon->msg->finished) {
>> - mon->msg->finished = 1;
>> - virCondSignal(&mon->notify);
>> - }
>> + if (events & VIR_EVENT_HANDLE_READABLE) {
>> + int got = qemuAgentIORead(mon);
>> +
>> + if (got <= 0)
>> + goto error;
>> +
>> + if (qemuAgentIOProcess(mon) < 0)
>> + goto error;
>> +
>> + /* Ignore hangup/error events if we read some data, to
>> + * give time for that data to be consumed */
>> + events = 0;
>> + }
>> +
>> + if (events & VIR_EVENT_HANDLE_HANGUP) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("End of file from agent monitor"));
>> + goto error;
>> + }
>> +
>> + if (events & VIR_EVENT_HANDLE_ERROR) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("Invalid file descriptor while waiting for monitor"));
>> + goto error;
>> + }
>> +
>> + if (events) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR,
>> + _("Unhandled event %d for monitor fd %d"),
>> + events, mon->fd);
>> + goto error;
>> }
>>
>> qemuAgentUpdateWatch(mon);
>> + virObjectUnlock(mon);
>> + virObjectUnref(mon);
>> + return;
>>
>> - /* We have to unlock to avoid deadlock against command thread,
>> - * but is this safe ? I think it is, because the callback
>> - * will try to acquire the virDomainObjPtr mutex next */
>> - if (eof) {
>> - void (*eofNotify)(qemuAgentPtr, virDomainObjPtr)
>> - = mon->cb->eofNotify;
>> - virDomainObjPtr vm = mon->vm;
>> -
>> - /* Make sure anyone waiting wakes up now */
>> - virCondSignal(&mon->notify);
>> - virObjectUnlock(mon);
>> - virObjectUnref(mon);
>> - VIR_DEBUG("Triggering EOF callback");
>> - (eofNotify)(mon, vm);
>> - } else if (error) {
>> - void (*errorNotify)(qemuAgentPtr, virDomainObjPtr)
>> - = mon->cb->errorNotify;
>> - virDomainObjPtr vm = mon->vm;
>> -
>> - /* Make sure anyone waiting wakes up now */
>> - virCondSignal(&mon->notify);
>> - virObjectUnlock(mon);
>> - virObjectUnref(mon);
>> - VIR_DEBUG("Triggering error callback");
>> - (errorNotify)(mon, vm);
>> + error:
>> + if (mon->lastError.code != VIR_ERR_OK) {
>> + /* Already have an error, so clear any new error */
>> + virResetLastError();
>> } else {
>> - virObjectUnlock(mon);
>> - virObjectUnref(mon);
>> + virErrorPtr err = virGetLastError();
>> + if (!err)
>> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> + _("Error while processing monitor IO"));
>> + virCopyLastError(&mon->lastError);
>> + virResetLastError();
>> }
>> +
>> + VIR_DEBUG("Error on monitor %s", NULLSTR(mon->lastError.message));
>> + /* If IO process resulted in an error & we have a message,
>> + * then wakeup that waiter */
>> + if (mon->msg && !mon->msg->finished) {
>> + mon->msg->finished = 1;
>> + virCondSignal(&mon->notify);
>> + }
>> +
>> + qemuAgentUpdateWatch(mon);
>> +
>> + errorNotify = mon->cb->errorNotify;
>> + vm = mon->vm;
>> +
>> + /* Make sure anyone waiting wakes up now */
>> + virCondSignal(&mon->notify);
>> + virObjectUnlock(mon);
>> + virObjectUnref(mon);
>> + (errorNotify)(mon, vm);
>> }
>>
>>
>> @@ -732,9 +705,9 @@ qemuAgentOpen(virDomainObjPtr vm,
>> {
>> qemuAgentPtr mon;
>>
>> - if (!cb || !cb->eofNotify) {
>> + if (!cb || !cb->errorNotify) {
>> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
>> - _("EOF notify callback must be supplied"));
>> + _("error notify callback must be supplied"));
>> return NULL;
>> }
>>
>> diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
>> index 6dd9c70..76e8772 100644
>> --- a/src/qemu/qemu_agent.h
>> +++ b/src/qemu/qemu_agent.h
>> @@ -36,8 +36,6 @@ typedef qemuAgentCallbacks *qemuAgentCallbacksPtr;
>> struct _qemuAgentCallbacks {
>> void (*destroy)(qemuAgentPtr mon,
>> virDomainObjPtr vm);
>> - void (*eofNotify)(qemuAgentPtr mon,
>> - virDomainObjPtr vm);
>> void (*errorNotify)(qemuAgentPtr mon,
>> virDomainObjPtr vm);
>> };
>> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
>> index 3da1bd5..fe7682e 100644
>> --- a/src/qemu/qemu_process.c
>> +++ b/src/qemu/qemu_process.c
>> @@ -128,12 +128,12 @@ extern virQEMUDriverPtr qemu_driver;
>> * performed
>> */
>> static void
>> -qemuProcessHandleAgentEOF(qemuAgentPtr agent,
>> - virDomainObjPtr vm)
>> +qemuProcessHandleAgentError(qemuAgentPtr agent,
>> + virDomainObjPtr vm)
>> {
>> qemuDomainObjPrivatePtr priv;
>>
>> - VIR_DEBUG("Received EOF from agent on %p '%s'", vm, vm->def->name);
>> + VIR_DEBUG("Received error from agent on %p '%s'", vm, vm->def->name);
>>
>> virObjectLock(vm);
>>
>> @@ -145,7 +145,7 @@ qemuProcessHandleAgentEOF(qemuAgentPtr agent,
>> }
>>
>> if (priv->beingDestroyed) {
>> - VIR_DEBUG("Domain is being destroyed, agent EOF is expected");
>> + VIR_DEBUG("Domain is being destroyed, agent error is expected");
>> goto unlock;
>> }
>>
>> @@ -161,19 +161,6 @@ qemuProcessHandleAgentEOF(qemuAgentPtr agent,
>> }
>>
>>
>> -/*
>> - * This is invoked when there is some kind of error
>> - * parsing data to/from the agent. The VM can continue
>> - * to run, but no further agent commands will be
>> - * allowed
>> - */
>> -static void
>> -qemuProcessHandleAgentError(qemuAgentPtr agent,
>> - virDomainObjPtr vm)
>> -{
>> - qemuProcessHandleAgentEOF(agent, vm);
>> -}
>> -
>> static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent,
>> virDomainObjPtr vm)
>> {
>> @@ -185,7 +172,6 @@ static void qemuProcessHandleAgentDestroy(qemuAgentPtr agent,
>>
>> static qemuAgentCallbacks agentCallbacks = {
>> .destroy = qemuProcessHandleAgentDestroy,
>> - .eofNotify = qemuProcessHandleAgentEOF,
>> .errorNotify = qemuProcessHandleAgentError,
>> };
>>
>> diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c
>> index c86a27a..d9b2726 100644
>> --- a/tests/qemumonitortestutils.c
>> +++ b/tests/qemumonitortestutils.c
>> @@ -752,7 +752,6 @@ qemuMonitorTestAgentNotify(qemuAgentPtr agent ATTRIBUTE_UNUSED,
>>
>>
>> static qemuAgentCallbacks qemuMonitorTestAgentCallbacks = {
>> - .eofNotify = qemuMonitorTestAgentNotify,
>> .errorNotify = qemuMonitorTestAgentNotify,
>> };
>>
>>
More information about the libvir-list
mailing list