From nobody Mon Feb 9 05:52:09 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1583412736; cv=none; d=zohomail.com; s=zohoarc; b=InIsixg++/9mLW7qe7FYU7HxKgHtYG9R/xBf3AkXhtbZNwiOECg8Nv/F8hKQdkyzOedFmAYDGRYzNYLTRn+KSQxd66dnRjr5cGSSYpXAhAfWmV8w+DUxaA9zU8kfK2JCMtUFDUoOcUmxcqelz94Wl4tgx/c+avZJslsCEfGerbo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1583412736; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=5n4SvOuzk65BTk2smKZeYQBNhadX4ZtMLAacXGDE/ig=; b=geZfFk3WsyhA/GpDH6m9IeMrZYknhK32nyK2u6PuB7GcYntFMM9u2Gqo+M4/lgyxj4aQbwpxGJusmR7C8Zbb5FLEMUNGWidBRm8mQ2BcTcF32XRCGYIT06iAKZa2ZTiI0i0tCPWCvNZxaUBmo7kkfG1ngDSWTlmu/5cWT7jejJk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1583412736121651.6871643554753; Thu, 5 Mar 2020 04:52:16 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-133-uGUY6aUPMJKRRtdbd5f0GA-1; Thu, 05 Mar 2020 07:52:12 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 601BE13FF; Thu, 5 Mar 2020 12:52:07 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2CE925C219; Thu, 5 Mar 2020 12:52:07 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id C8B4F180887A; Thu, 5 Mar 2020 12:52:06 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 025CpwsY000923 for ; Thu, 5 Mar 2020 07:51:58 -0500 Received: by smtp.corp.redhat.com (Postfix) id EDB401001DF0; Thu, 5 Mar 2020 12:51:58 +0000 (UTC) Received: from domokun.gsslab.fab.redhat.com (unknown [10.33.8.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5BDFE1001902; Thu, 5 Mar 2020 12:51:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583412735; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=5n4SvOuzk65BTk2smKZeYQBNhadX4ZtMLAacXGDE/ig=; b=gtBw4gnDHB7A8f344V+xcO/EN6wBX2q6ycbZsVOgzV6JERvTptMKFMqo5bcG6ot2BmHMIn ub+pTaFd1KgdeI5oIXVumQyOfsnyDqVMiJIbtlPfOdvTryReKhuXQur2pyOMmrVTJZpTEH MO30m6tKP07A9R14y4VyC33UxGuJDuc= X-MC-Unique: uGUY6aUPMJKRRtdbd5f0GA-1 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH v2 7/7] qemu: convert agent to use the per-VM event loop Date: Thu, 5 Mar 2020 12:51:47 +0000 Message-Id: <20200305125147.2003011-8-berrange@redhat.com> In-Reply-To: <20200305125147.2003011-1-berrange@redhat.com> References: <20200305125147.2003011-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" This converts the QEMU agent APIs to use the per-VM event loop, which involves switching from virEvent APIs to GMainContext / GSource APIs. A GSocket is used as a convenient way to create a GSource for a socket, but is not yet used for actual I/O. Signed-off-by: Daniel P. Berrang=C3=A9 --- src/qemu/qemu_agent.c | 146 +++++++++++++++++++---------------- src/qemu/qemu_agent.h | 1 + src/qemu/qemu_process.c | 1 + tests/qemumonitortestutils.c | 1 + 4 files changed, 84 insertions(+), 65 deletions(-) diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c index 72ea159a9c..1655e26212 100644 --- a/src/qemu/qemu_agent.c +++ b/src/qemu/qemu_agent.c @@ -25,6 +25,7 @@ #include #include #include +#include =20 #include "qemu_agent.h" #include "qemu_domain.h" @@ -101,7 +102,10 @@ struct _qemuAgent { virCond notify; =20 int fd; - int watch; + + GMainContext *context; + GSocket *socket; + GSource *watch; =20 bool running; =20 @@ -172,6 +176,7 @@ static void qemuAgentDispose(void *obj) (agent->cb->destroy)(agent, agent->vm); virCondDestroy(&agent->notify); VIR_FREE(agent->buffer); + g_main_context_unref(agent->context); virResetError(&agent->lastError); } =20 @@ -188,13 +193,6 @@ qemuAgentOpenUnix(const char *socketpath) return -1; } =20 - if (virSetNonBlock(agentfd) < 0) { - virReportSystemError(errno, "%s", - _("Unable to put monitor " - "into non-blocking mode")); - goto error; - } - if (virSetCloseExec(agentfd) < 0) { virReportSystemError(errno, "%s", _("Unable to set agent " @@ -498,28 +496,62 @@ qemuAgentIORead(qemuAgentPtr agent) } =20 =20 -static void qemuAgentUpdateWatch(qemuAgentPtr agent) -{ - int events =3D - VIR_EVENT_HANDLE_HANGUP | - VIR_EVENT_HANDLE_ERROR; +static gboolean +qemuAgentIO(GSocket *socket, + GIOCondition cond, + gpointer opaque); =20 - if (!agent->watch) - return; + +static void +qemuAgentRegister(qemuAgentPtr agent) +{ + GIOCondition cond =3D 0; =20 if (agent->lastError.code =3D=3D VIR_ERR_OK) { - events |=3D VIR_EVENT_HANDLE_READABLE; + cond |=3D G_IO_IN; =20 if (agent->msg && agent->msg->txOffset < agent->msg->txLength) - events |=3D VIR_EVENT_HANDLE_WRITABLE; + cond |=3D G_IO_OUT; } =20 - virEventUpdateHandle(agent->watch, events); + agent->watch =3D g_socket_create_source(agent->socket, + cond, + NULL); + + virObjectRef(agent); + g_source_set_callback(agent->watch, + (GSourceFunc)qemuAgentIO, + agent, + NULL); + + g_source_attach(agent->watch, + agent->context); } =20 =20 static void -qemuAgentIO(int watch, int fd, int events, void *opaque) +qemuAgentUnregister(qemuAgentPtr agent) +{ + if (agent->watch) { + g_source_destroy(agent->watch); + g_source_unref(agent->watch); + agent->watch =3D NULL; + } +} + + +static void qemuAgentUpdateWatch(qemuAgentPtr agent) +{ + qemuAgentUnregister(agent); + if (agent->socket) + qemuAgentRegister(agent); +} + + +static gboolean +qemuAgentIO(GSocket *socket G_GNUC_UNUSED, + GIOCondition cond, + gpointer opaque) { qemuAgentPtr agent =3D opaque; bool error =3D false; @@ -529,45 +561,36 @@ qemuAgentIO(int watch, int fd, int events, void *opaq= ue) /* lock access to the agent and protect fd */ virObjectLock(agent); #if DEBUG_IO - VIR_DEBUG("Agent %p I/O on watch %d fd %d events %d", agent, watch, fd= , events); + VIR_DEBUG("Agent %p I/O on watch %d socket %p cond %d", agent, agent->= socket, cond); #endif =20 - if (agent->fd =3D=3D -1 || agent->watch =3D=3D 0) { + if (agent->fd =3D=3D -1 || !agent->watch) { virObjectUnlock(agent); virObjectUnref(agent); - return; + return G_SOURCE_REMOVE; } =20 - if (agent->fd !=3D fd || agent->watch !=3D watch) { - if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) - eof =3D true; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("event from unexpected fd %d!=3D%d / watch %d!=3D= %d"), - agent->fd, fd, agent->watch, watch); - error =3D true; - } else if (agent->lastError.code !=3D VIR_ERR_OK) { - if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) + if (agent->lastError.code !=3D VIR_ERR_OK) { + if (cond & (G_IO_HUP | G_IO_ERR)) eof =3D true; error =3D true; } else { - if (events & VIR_EVENT_HANDLE_WRITABLE) { + if (cond & G_IO_OUT) { if (qemuAgentIOWrite(agent) < 0) error =3D true; - events &=3D ~VIR_EVENT_HANDLE_WRITABLE; } =20 if (!error && - events & VIR_EVENT_HANDLE_READABLE) { + cond & G_IO_IN) { int got =3D qemuAgentIORead(agent); - events &=3D ~VIR_EVENT_HANDLE_READABLE; if (got < 0) { error =3D true; } else if (got =3D=3D 0) { eof =3D true; } else { - /* Ignore hangup/error events if we read some data, to + /* Ignore hangup/error cond if we read some data, to * give time for that data to be consumed */ - events =3D 0; + cond =3D 0; =20 if (qemuAgentIOProcess(agent) < 0) error =3D true; @@ -575,25 +598,17 @@ qemuAgentIO(int watch, int fd, int events, void *opaq= ue) } =20 if (!error && - events & VIR_EVENT_HANDLE_HANGUP) { + cond & G_IO_HUP) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("End of file from agent socket")); eof =3D true; - events &=3D ~VIR_EVENT_HANDLE_HANGUP; } =20 if (!error && !eof && - events & VIR_EVENT_HANDLE_ERROR) { + cond & G_IO_ERR) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid file descriptor while waiting for ag= ent")); eof =3D true; - events &=3D ~VIR_EVENT_HANDLE_ERROR; - } - if (!error && events) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unhandled event %d for agent fd %d"), - events, agent->fd); - error =3D true; } } =20 @@ -649,15 +664,19 @@ qemuAgentIO(int watch, int fd, int events, void *opaq= ue) virObjectUnlock(agent); virObjectUnref(agent); } + + return G_SOURCE_REMOVE; } =20 =20 qemuAgentPtr qemuAgentOpen(virDomainObjPtr vm, const virDomainChrSourceDef *config, + GMainContext *context, qemuAgentCallbacksPtr cb) { qemuAgentPtr agent; + g_autoptr(GError) gerr =3D NULL; =20 if (!cb || !cb->eofNotify) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -693,22 +712,20 @@ qemuAgentOpen(virDomainObjPtr vm, if (agent->fd =3D=3D -1) goto cleanup; =20 - virObjectRef(agent); - if ((agent->watch =3D virEventAddHandle(agent->fd, - VIR_EVENT_HANDLE_HANGUP | - VIR_EVENT_HANDLE_ERROR | - VIR_EVENT_HANDLE_READABLE, - qemuAgentIO, - agent, - virObjectFreeCallback)) < 0) { - virObjectUnref(agent); - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("unable to register agent events")); + agent->context =3D g_main_context_ref(context); + + agent->socket =3D g_socket_new_from_fd(agent->fd, &gerr); + if (!agent->socket) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to create socket object: %s"), + gerr->message); goto cleanup; } =20 + qemuAgentRegister(agent); + agent->running =3D true; - VIR_DEBUG("New agent %p fd =3D%d watch=3D%d", agent, agent->fd, agent-= >watch); + VIR_DEBUG("New agent %p fd=3D%d", agent, agent->fd); =20 return agent; =20 @@ -763,12 +780,11 @@ void qemuAgentClose(qemuAgentPtr agent) =20 virObjectLock(agent); =20 - if (agent->fd >=3D 0) { - if (agent->watch) { - virEventRemoveHandle(agent->watch); - agent->watch =3D 0; - } - VIR_FORCE_CLOSE(agent->fd); + if (agent->socket) { + qemuAgentUnregister(agent); + g_object_unref(agent->socket); + agent->socket =3D NULL; + agent->fd =3D -1; } =20 qemuAgentNotifyCloseLocked(agent); diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h index 5656fe60ff..d4d8615323 100644 --- a/src/qemu/qemu_agent.h +++ b/src/qemu/qemu_agent.h @@ -41,6 +41,7 @@ struct _qemuAgentCallbacks { =20 qemuAgentPtr qemuAgentOpen(virDomainObjPtr vm, const virDomainChrSourceDef *config, + GMainContext *context, qemuAgentCallbacksPtr cb); =20 void qemuAgentClose(qemuAgentPtr mon); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index ea046bcb14..a235064320 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -237,6 +237,7 @@ qemuConnectAgent(virQEMUDriverPtr driver, virDomainObjP= tr vm) =20 agent =3D qemuAgentOpen(vm, config->source, + virEventThreadGetContext(priv->eventThread), &agentCallbacks); =20 virObjectLock(vm); diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index df93aae758..328bfb8525 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -1406,6 +1406,7 @@ qemuMonitorTestNewAgent(virDomainXMLOptionPtr xmlopt) =20 if (!(test->agent =3D qemuAgentOpen(test->vm, &src, + virEventThreadGetContext(test->event= Thread), &qemuMonitorTestAgentCallbacks))) goto error; =20 --=20 2.24.1