From nobody Wed Apr 2 13:30:23 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1743014126; cv=none; d=zohomail.com; s=zohoarc; b=CpWkQPxDMQhzftNH22ssJY3jkb5UhcWP8JJmNo/QuLsn77EfYfKRi1V8bZquTP1mQMxoIWTWNE12Ls7AzuMWebm8EDU/iHkspZbPxj8V36hr52Uhnqh1DZEE/nm/0jLIqd+BLMVgcynBlWNm8bwYUu7DV6tR1mxX6tCLeuYfA5A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743014126; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=D2LwDGoefYs4dtuMbGxSdhyMxKOv3aYPw7i40OKBxVw=; b=JsOtvbRA56iRQx1ZXFXeCD/qrE/gY9Ut0GVIaOL6ELFepJDYLRmoGcAiAISaSk8nUd9OxOHRDD/875u9/wOxZuMjsByxBmIDWs+CAQOwaPQZBXCaCSSKfEWHxS37PPp8SrXQkMX49KRRYGdrTwgEGW+W63WExg6uXJWS7DDs5vo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17430141260005.639873816789645; Wed, 26 Mar 2025 11:35:26 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1txVZj-0001zI-Mb; Wed, 26 Mar 2025 14:34:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZg-0001xx-RB for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:01 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZc-0003Uh-St for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:00 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-45-rQCIxpsaOh6_4okITr1sfw-1; Wed, 26 Mar 2025 14:33:48 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 720E7180035C; Wed, 26 Mar 2025 18:33:46 +0000 (UTC) Received: from localhost (unknown [10.2.16.113]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A522619541A5; Wed, 26 Mar 2025 18:33:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1743014033; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=D2LwDGoefYs4dtuMbGxSdhyMxKOv3aYPw7i40OKBxVw=; b=She9SF7HOQtN7USM/zNG+BV4surlssMLj0IcRrDknmrVmEpbwwDrveOYDDcaEKltmjQYJC 3NodPP8tKM/P66wFnZCX7wFxTNOWLEJqRIjQmUhw530/ICiObfNX6wNY7gzlkXKOd2EkGT diEoaQw/DhrCAHPi2m4/jlZ7EPjk0Ss= X-MC-Unique: rQCIxpsaOh6_4okITr1sfw-1 X-Mimecast-MFC-AGG-ID: rQCIxpsaOh6_4okITr1sfw_1743014027 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, Kevin Wolf , Stefan Hajnoczi , Stefan Weil , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Hanna Reitz , Paolo Bonzini , Fam Zheng Subject: [PATCH 1/4] aio-posix: fix polling mode with fdmon-io_uring Date: Wed, 26 Mar 2025 14:33:37 -0400 Message-ID: <20250326183340.1010531-2-stefanha@redhat.com> In-Reply-To: <20250326183340.1010531-1-stefanha@redhat.com> References: <20250326183340.1010531-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1743014126961019000 Content-Type: text/plain; charset="utf-8" The io_uring(7) file descriptor monitor cannot enter polling mode because it needs to submit a POLL_ADD SQE every time a file descriptor becomes active. Submitting SQEs only happens in FDMonOps->wait() outside of polling mode. Fix this using the multi-shot mechanism introduced in Linux 5.13 and liburing 2.1. Stable and enterprise Linux distros ship 5.14+ as of March 2025, so it is safe to require this. Note that fdmon-io_uring is currently not enabled at runtime and is not essential, so QEMU can still be built without it on older hosts. In multi-shot mode, a POLL_ADD SQE remains active until canceled with POLL_REMOVE. This avoids the need to submit a new SQE every time a file descriptor becomes active. When POLL_REMOVE is processed by the host kernel, the multi-shot POLL_ADD operation completes with -ECANCELED. Adjust the code slightly to take this into account. Signed-off-by: Stefan Hajnoczi --- meson.build | 2 +- util/fdmon-io_uring.c | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/meson.build b/meson.build index 41f68d3806..9f5f31ac46 100644 --- a/meson.build +++ b/meson.build @@ -1144,7 +1144,7 @@ linux_io_uring_test =3D ''' =20 linux_io_uring =3D not_found if not get_option('linux_io_uring').auto() or have_block - linux_io_uring =3D dependency('liburing', version: '>=3D0.3', + linux_io_uring =3D dependency('liburing', version: '>=3D2.1', required: get_option('linux_io_uring'), method: 'pkg-config') if not cc.links(linux_io_uring_test) diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c index b0d68bdc44..6cd665e565 100644 --- a/util/fdmon-io_uring.c +++ b/util/fdmon-io_uring.c @@ -124,8 +124,7 @@ static AioHandler *dequeue(AioHandlerSList *head, unsig= ned *flags) /* * Don't clear FDMON_IO_URING_REMOVE. It's sticky so it can serve two * purposes: telling fill_sq_ring() to submit IORING_OP_POLL_REMOVE and - * telling process_cqe() to delete the AioHandler when its - * IORING_OP_POLL_ADD completes. + * telling process_cqe() to ignore IORING_OP_POLL_ADD completions. */ *flags =3D qatomic_fetch_and(&node->flags, ~(FDMON_IO_URING_PENDING | FDMON_IO_URING_ADD)); @@ -166,12 +165,12 @@ static void fdmon_io_uring_update(AioContext *ctx, } } =20 -static void add_poll_add_sqe(AioContext *ctx, AioHandler *node) +static void add_poll_multishot_sqe(AioContext *ctx, AioHandler *node) { struct io_uring_sqe *sqe =3D get_sqe(ctx); int events =3D poll_events_from_pfd(node->pfd.events); =20 - io_uring_prep_poll_add(sqe, node->pfd.fd, events); + io_uring_prep_poll_multishot(sqe, node->pfd.fd, events); io_uring_sqe_set_data(sqe, node); } =20 @@ -213,7 +212,7 @@ static void fill_sq_ring(AioContext *ctx) while ((node =3D dequeue(&submit_list, &flags))) { /* Order matters, just in case both flags were set */ if (flags & FDMON_IO_URING_ADD) { - add_poll_add_sqe(ctx, node); + add_poll_multishot_sqe(ctx, node); } if (flags & FDMON_IO_URING_REMOVE) { add_poll_remove_sqe(ctx, node); @@ -234,21 +233,30 @@ static bool process_cqe(AioContext *ctx, return false; } =20 + flags =3D qatomic_read(&node->flags); + /* - * Deletion can only happen when IORING_OP_POLL_ADD completes. If we = race - * with enqueue() here then we can safely clear the FDMON_IO_URING_REM= OVE - * bit before IORING_OP_POLL_REMOVE is submitted. + * poll_multishot cancelled by poll_remove? Or completed early because= fd + * was closed before poll_remove finished? */ - flags =3D qatomic_fetch_and(&node->flags, ~FDMON_IO_URING_REMOVE); - if (flags & FDMON_IO_URING_REMOVE) { + if (cqe->res =3D=3D -ECANCELED || cqe->res =3D=3D -EBADF) { + assert(!(cqe->flags & IORING_CQE_F_MORE)); + assert(flags & FDMON_IO_URING_REMOVE); QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_delet= ed); return false; } =20 - aio_add_ready_handler(ready_list, node, pfd_events_from_poll(cqe->res)= ); + /* Ignore if it becomes ready during removal */ + if (flags & FDMON_IO_URING_REMOVE) { + return false; + } =20 - /* IORING_OP_POLL_ADD is one-shot so we must re-arm it */ - add_poll_add_sqe(ctx, node); + /* Multi-shot can stop at any time, so re-arm if necessary */ + if (!(cqe->flags & IORING_CQE_F_MORE)) { + add_poll_multishot_sqe(ctx, node); + } + + aio_add_ready_handler(ready_list, node, pfd_events_from_poll(cqe->res)= ); return true; } =20 --=20 2.49.0 From nobody Wed Apr 2 13:30:23 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1743014137; cv=none; d=zohomail.com; s=zohoarc; b=V5RzGgKrXxIiTQzOW2zt2R18pnd/b/68gutOkHhzXY+f5v23g04MItN0trmoivQmCwXDvIC7ABb7+fAQ4lm+nKGW5ZQyZc1Y06R/koNchaUz0kd/HuUHWseuK5x3cVJGQzPyXP6vL3JLF49vPyTfe34MbBmiWsiD5itXUU5xvI4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743014137; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=q9h1zX98YS130jYQiPMScS8WZnfv2PtTKZLY6/1Rdik=; b=jjKNDZImBVP/EAj3PG21ir5cXUh+MfZ+LvWFxl60O3sPLXRswo0eNoVIwS2Ah4p+Imcg9HKG++A5ehH5q7S47ybhhgrfTWKygmZt/292OHB4EcYz6MSDvTQPiBs1IszIxXKrK6tYUqgBIFgpafcKSYnO0+kONVbjDET4HNCJlTg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1743014137046138.4333345518021; Wed, 26 Mar 2025 11:35:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1txVZl-00020A-7e; Wed, 26 Mar 2025 14:34:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZi-0001z1-VG for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:03 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZe-0003VL-73 for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:01 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-307-gi90J0f2O0KvtyQCQbFA-g-1; Wed, 26 Mar 2025 14:33:51 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 08A311800260; Wed, 26 Mar 2025 18:33:50 +0000 (UTC) Received: from localhost (unknown [10.2.16.113]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 08CDC1801751; Wed, 26 Mar 2025 18:33:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1743014036; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q9h1zX98YS130jYQiPMScS8WZnfv2PtTKZLY6/1Rdik=; b=NGbGz4THjac1bGR8pIik0uJ07JdL5WSTmpjr2wNieMDiWl1kc6nqO3L9Cv/IJDWVYnQlTm wXOFl+3hGM5IUfjaYszSMyPQmOauChet44+X/yp3mQ+Kx3+VE6GIfP6a0wMSXfNNdpC/64 iR2uWl0RWU/346CE9EhzJdxyMZf8P40= X-MC-Unique: gi90J0f2O0KvtyQCQbFA-g-1 X-Mimecast-MFC-AGG-ID: gi90J0f2O0KvtyQCQbFA-g_1743014030 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, Kevin Wolf , Stefan Hajnoczi , Stefan Weil , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Hanna Reitz , Paolo Bonzini , Fam Zheng Subject: [PATCH 2/4] tests/unit: skip test-nested-aio-poll with io_uring Date: Wed, 26 Mar 2025 14:33:38 -0400 Message-ID: <20250326183340.1010531-3-stefanha@redhat.com> In-Reply-To: <20250326183340.1010531-1-stefanha@redhat.com> References: <20250326183340.1010531-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1743014139264019000 Content-Type: text/plain; charset="utf-8" test-nested-aio-poll relies on internal details of how fdmon-poll.c handles AioContext polling. Skip it when other fdmon implementations are in use. Note that this test is only built on POSIX systems so it is safe to include "util/aio-posix.h". Signed-off-by: Stefan Hajnoczi --- tests/unit/test-nested-aio-poll.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/unit/test-nested-aio-poll.c b/tests/unit/test-nested-aio= -poll.c index d8fd92c43b..45484e745b 100644 --- a/tests/unit/test-nested-aio-poll.c +++ b/tests/unit/test-nested-aio-poll.c @@ -15,6 +15,7 @@ #include "qemu/osdep.h" #include "block/aio.h" #include "qapi/error.h" +#include "util/aio-posix.h" =20 typedef struct { AioContext *ctx; @@ -71,6 +72,12 @@ static void test(void) .ctx =3D aio_context_new(&error_abort), }; =20 + if (td.ctx->fdmon_ops !=3D &fdmon_poll_ops) { + /* This test is tied to fdmon-poll.c */ + g_test_skip("fdmon_poll_ops not in use"); + return; + } + qemu_set_current_aio_context(td.ctx); =20 /* Enable polling */ --=20 2.49.0 From nobody Wed Apr 2 13:30:23 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1743014077; cv=none; d=zohomail.com; s=zohoarc; b=DxR8lqj1zr8FiPiTXgkeTL3W4W9K7a79E//7bSjpso9hiYAHyKD4VTrdIyMLNV76oVxuMd10BNEtnNKHFl1W4a/2CvV/Tkf4D6bM/FThgcBcxVgOBZR5NpDFTG5E/bHoxsW6fb0G5VqTl1hSwqpA0Lh3APh3mhB7hYev3tQGQew= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743014077; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=8P8D83t9mOZAXQGYDPUNsY0BVPpt0+1cG+6xwaizz1M=; b=JwREJAsVwhF4t3m/naWSc8xBbd11Wlm56WYlNzUXmF/NFEAgVZAGD++QnJpge3Hs88wc5PUjAkjwRe5omdap2U28pcq/AdU2h5y0y5jyjQYIMMI841O9VBqeoH6dt418eSvXu8z1MXSbeUPTAER+mBQZ6tMRCFQ7NEB735ExF2Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1743014077579608.4232771679215; Wed, 26 Mar 2025 11:34:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1txVZk-000203-QX; Wed, 26 Mar 2025 14:34:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZh-0001yZ-TX for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:02 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZd-0003VP-IW for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:01 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-447-f_ZhHQqwPTmCZ9QnzPw5Cg-1; Wed, 26 Mar 2025 14:33:53 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1541E196B36E; Wed, 26 Mar 2025 18:33:52 +0000 (UTC) Received: from localhost (unknown [10.2.16.113]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 388B119541A5; Wed, 26 Mar 2025 18:33:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1743014036; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8P8D83t9mOZAXQGYDPUNsY0BVPpt0+1cG+6xwaizz1M=; b=VhAfFW6f43gHq5/nqB5WsSKUZ0vQ37TVzbDVn8V0f0iDZexPpyduJ6SY1MEKG+rW2MkJPd lVopIW7KaKeulD8Nszcgdg2LrSrbSAp+rrBQ4kXGyj1rqeOamcrvnC+Hq1UQCBojPXUDxL hX5SnpR0+3w/+VhsckLxdyRh5MChn0g= X-MC-Unique: f_ZhHQqwPTmCZ9QnzPw5Cg-1 X-Mimecast-MFC-AGG-ID: f_ZhHQqwPTmCZ9QnzPw5Cg_1743014032 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, Kevin Wolf , Stefan Hajnoczi , Stefan Weil , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Hanna Reitz , Paolo Bonzini , Fam Zheng Subject: [PATCH 3/4] aio-posix: integrate fdmon into glib event loop Date: Wed, 26 Mar 2025 14:33:39 -0400 Message-ID: <20250326183340.1010531-4-stefanha@redhat.com> In-Reply-To: <20250326183340.1010531-1-stefanha@redhat.com> References: <20250326183340.1010531-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1743014078975019100 Content-Type: text/plain; charset="utf-8" AioContext's glib integration only supports ppoll(2) file descriptor monitoring. epoll(7) and io_uring(7) disable themselves and switch back to ppoll(2) when the glib event loop is used. The main loop thread cannot use epoll(7) or io_uring(7) because it always uses the glib event loop. Future QEMU features may require io_uring(7). One example is uring_cmd support in FUSE exports. Each feature could create its own io_uring(7) context and integrate it into the event loop, but this is inefficient due to extra syscalls. It would be more efficient to reuse the AioContext's existing fdmon-io_uring.c io_uring(7) context because fdmon-io_uring.c will already be active on systems where Linux io_uring is available. In order to keep fdmon-io_uring.c's AioContext operational even when the glib event loop is used, extend FDMonOps with an API similar to GSourceFuncs so that file descriptor monitoring can integrate into the glib event loop. A quick summary of the GSourceFuncs API: - prepare() is called each event loop iteration before waiting for file descriptors and timers. - check() is called to determine whether events are ready to be dispatched after waiting. - dispatch() is called to process events. More details here: https://docs.gtk.org/glib/struct.SourceFuncs.html Move the ppoll(2)-specific code from aio-posix.c into fdmon-poll.c and also implement epoll(7)- and io_uring(7)-specific file descriptor monitoring code for glib event loops. Note that it's still faster to use aio_poll() rather than the glib event loop since glib waits for file descriptor activity with ppoll(2) and does not support adaptive polling. But at least epoll(7) and io_uring(7) now work in glib event loops. Splitting this into multiple commits without temporarily breaking AioContext proved difficult so this commit makes all the changes. The next commit will remove the aio_context_use_g_source() API because it is no longer needed. Signed-off-by: Stefan Hajnoczi --- include/block/aio.h | 36 ++++++++++++++++++ util/aio-posix.h | 5 +++ tests/unit/test-aio.c | 7 +++- util/aio-posix.c | 69 ++++++++------------------------- util/fdmon-epoll.c | 52 ++++++++++++++++++++++--- util/fdmon-io_uring.c | 44 +++++++++++++++++++++- util/fdmon-poll.c | 88 ++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 239 insertions(+), 62 deletions(-) diff --git a/include/block/aio.h b/include/block/aio.h index 99ff48420b..39ed86d14d 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -106,6 +106,38 @@ typedef struct { * Returns: true if ->wait() should be called, false otherwise. */ bool (*need_wait)(AioContext *ctx); + + /* + * gsource_prepare: + * @ctx: the AioContext + * + * Prepare for the glib event loop to wait for events instead of the u= sual + * ->wait() call. See glib's GSourceFuncs->prepare(). + */ + void (*gsource_prepare)(AioContext *ctx); + + /* + * gsource_check: + * @ctx: the AioContext + * + * Called by the glib event loop from glib's GSourceFuncs->check() aft= er + * waiting for events. + * + * Returns: true when ready to be dispatched. + */ + bool (*gsource_check)(AioContext *ctx); + + /* + * gsource_dispatch: + * @ctx: the AioContext + * @ready_list: list for handlers that become ready + * + * Place ready AioHandlers on ready_list. Called as part of the glib e= vent + * loop from glib's GSourceFuncs->dispatch(). + * + * Called with list_lock incremented. + */ + void (*gsource_dispatch)(AioContext *ctx, AioHandlerList *ready_list); } FDMonOps; =20 /* @@ -222,6 +254,7 @@ struct AioContext { /* State for file descriptor monitoring using Linux io_uring */ struct io_uring fdmon_io_uring; AioHandlerSList submit_list; + gpointer io_uring_fd_tag; #endif =20 /* TimerLists for calling timers - one per clock type. Has its own @@ -254,6 +287,9 @@ struct AioContext { /* epoll(7) state used when built with CONFIG_EPOLL */ int epollfd; =20 + /* The GSource unix fd tag for epollfd */ + gpointer epollfd_tag; + const FDMonOps *fdmon_ops; }; =20 diff --git a/util/aio-posix.h b/util/aio-posix.h index 82a0201ea4..f9994ed79e 100644 --- a/util/aio-posix.h +++ b/util/aio-posix.h @@ -47,9 +47,14 @@ void aio_add_ready_handler(AioHandlerList *ready_list, A= ioHandler *node, =20 extern const FDMonOps fdmon_poll_ops; =20 +/* Switch back to poll(2). list_lock must be held. */ +void fdmon_poll_downgrade(AioContext *ctx); + #ifdef CONFIG_EPOLL_CREATE1 bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd); void fdmon_epoll_setup(AioContext *ctx); + +/* list_lock must be held */ void fdmon_epoll_disable(AioContext *ctx); #else static inline bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigned npfd) diff --git a/tests/unit/test-aio.c b/tests/unit/test-aio.c index e77d86be87..010d65b79a 100644 --- a/tests/unit/test-aio.c +++ b/tests/unit/test-aio.c @@ -527,7 +527,12 @@ static void test_source_bh_delete_from_cb(void) g_assert_cmpint(data1.n, =3D=3D, data1.max); g_assert(data1.bh =3D=3D NULL); =20 - assert(g_main_context_iteration(NULL, false)); + /* + * There may be up to one more iteration due to the aio_notify + * EventNotifier. + */ + g_main_context_iteration(NULL, false); + assert(!g_main_context_iteration(NULL, false)); } =20 diff --git a/util/aio-posix.c b/util/aio-posix.c index 2e0a5dadc4..8ed1c4a405 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -70,15 +70,6 @@ static AioHandler *find_aio_handler(AioContext *ctx, int= fd) =20 static bool aio_remove_fd_handler(AioContext *ctx, AioHandler *node) { - /* If the GSource is in the process of being destroyed then - * g_source_remove_poll() causes an assertion failure. Skip - * removal in that case, because glib cleans up its state during - * destruction anyway. - */ - if (!g_source_is_destroyed(&ctx->source)) { - g_source_remove_poll(&ctx->source, &node->pfd); - } - node->pfd.revents =3D 0; node->poll_ready =3D false; =20 @@ -153,7 +144,6 @@ void aio_set_fd_handler(AioContext *ctx, } else { new_node->pfd =3D node->pfd; } - g_source_add_poll(&ctx->source, &new_node->pfd); =20 new_node->pfd.events =3D (io_read ? G_IO_IN | G_IO_HUP | G_IO_ERR = : 0); new_node->pfd.events |=3D (io_write ? G_IO_OUT | G_IO_ERR : 0); @@ -267,37 +257,13 @@ bool aio_prepare(AioContext *ctx) poll_set_started(ctx, &ready_list, false); /* TODO what to do with this list? */ =20 + ctx->fdmon_ops->gsource_prepare(ctx); return false; } =20 bool aio_pending(AioContext *ctx) { - AioHandler *node; - bool result =3D false; - - /* - * We have to walk very carefully in case aio_set_fd_handler is - * called while we're walking. - */ - qemu_lockcnt_inc(&ctx->list_lock); - - QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { - int revents; - - /* TODO should this check poll ready? */ - revents =3D node->pfd.revents & node->pfd.events; - if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { - result =3D true; - break; - } - if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { - result =3D true; - break; - } - } - qemu_lockcnt_dec(&ctx->list_lock); - - return result; + return ctx->fdmon_ops->gsource_check(ctx); } =20 static void aio_free_deleted_handlers(AioContext *ctx) @@ -390,10 +356,6 @@ static bool aio_dispatch_handler(AioContext *ctx, AioH= andler *node) return progress; } =20 -/* - * If we have a list of ready handlers then this is more efficient than - * scanning all handlers with aio_dispatch_handlers(). - */ static bool aio_dispatch_ready_handlers(AioContext *ctx, AioHandlerList *ready_list, int64_t block_ns) @@ -417,24 +379,18 @@ static bool aio_dispatch_ready_handlers(AioContext *c= tx, return progress; } =20 -/* Slower than aio_dispatch_ready_handlers() but only used via glib */ -static bool aio_dispatch_handlers(AioContext *ctx) -{ - AioHandler *node, *tmp; - bool progress =3D false; - - QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) { - progress =3D aio_dispatch_handler(ctx, node) || progress; - } - - return progress; -} - void aio_dispatch(AioContext *ctx) { + AioHandlerList ready_list =3D QLIST_HEAD_INITIALIZER(ready_list); + qemu_lockcnt_inc(&ctx->list_lock); aio_bh_poll(ctx); - aio_dispatch_handlers(ctx); + + ctx->fdmon_ops->gsource_dispatch(ctx, &ready_list); + + /* block_ns is 0 because polling is disabled in the glib event loop */ + aio_dispatch_ready_handlers(ctx, &ready_list, 0); + aio_free_deleted_handlers(ctx); qemu_lockcnt_dec(&ctx->list_lock); =20 @@ -759,6 +715,7 @@ void aio_context_setup(AioContext *ctx) { ctx->fdmon_ops =3D &fdmon_poll_ops; ctx->epollfd =3D -1; + ctx->epollfd_tag =3D NULL; =20 /* Use the fastest fd monitoring implementation if available */ if (fdmon_io_uring_setup(ctx)) { @@ -771,7 +728,11 @@ void aio_context_setup(AioContext *ctx) void aio_context_destroy(AioContext *ctx) { fdmon_io_uring_destroy(ctx); + + qemu_lockcnt_lock(&ctx->list_lock); fdmon_epoll_disable(ctx); + qemu_lockcnt_unlock(&ctx->list_lock); + aio_free_deleted_handlers(ctx); } =20 diff --git a/util/fdmon-epoll.c b/util/fdmon-epoll.c index 9fb8800dde..0e78baa634 100644 --- a/util/fdmon-epoll.c +++ b/util/fdmon-epoll.c @@ -19,8 +19,12 @@ void fdmon_epoll_disable(AioContext *ctx) ctx->epollfd =3D -1; } =20 - /* Switch back */ - ctx->fdmon_ops =3D &fdmon_poll_ops; + if (ctx->epollfd_tag) { + g_source_remove_unix_fd(&ctx->source, ctx->epollfd_tag); + ctx->epollfd_tag =3D NULL; + } + + fdmon_poll_downgrade(ctx); } =20 static inline int epoll_events_from_pfd(int pfd_events) @@ -93,10 +97,47 @@ out: return ret; } =20 +static void fdmon_epoll_gsource_prepare(AioContext *ctx) +{ + /* Do nothing */ +} + +static bool fdmon_epoll_gsource_check(AioContext *ctx) +{ + return g_source_query_unix_fd(&ctx->source, ctx->epollfd_tag) & G_IO_I= N; +} + +static void fdmon_epoll_gsource_dispatch(AioContext *ctx, + AioHandlerList *ready_list) +{ + AioHandler *node; + int ret; + struct epoll_event events[128]; + + /* Collect events and process them */ + ret =3D epoll_wait(ctx->epollfd, events, ARRAY_SIZE(events), 0); + if (ret <=3D 0) { + return; + } + for (int i =3D 0; i < ret; i++) { + int ev =3D events[i].events; + int revents =3D (ev & EPOLLIN ? G_IO_IN : 0) | + (ev & EPOLLOUT ? G_IO_OUT : 0) | + (ev & EPOLLHUP ? G_IO_HUP : 0) | + (ev & EPOLLERR ? G_IO_ERR : 0); + + node =3D events[i].data.ptr; + aio_add_ready_handler(ready_list, node, revents); + } +} + static const FDMonOps fdmon_epoll_ops =3D { .update =3D fdmon_epoll_update, .wait =3D fdmon_epoll_wait, .need_wait =3D aio_poll_disabled, + .gsource_prepare =3D fdmon_epoll_gsource_prepare, + .gsource_check =3D fdmon_epoll_gsource_check, + .gsource_dispatch =3D fdmon_epoll_gsource_dispatch, }; =20 static bool fdmon_epoll_try_enable(AioContext *ctx) @@ -118,6 +159,8 @@ static bool fdmon_epoll_try_enable(AioContext *ctx) } =20 ctx->fdmon_ops =3D &fdmon_epoll_ops; + ctx->epollfd_tag =3D g_source_add_unix_fd(&ctx->source, ctx->epollfd, + G_IO_IN); return true; } =20 @@ -139,12 +182,11 @@ bool fdmon_epoll_try_upgrade(AioContext *ctx, unsigne= d npfd) } =20 ok =3D fdmon_epoll_try_enable(ctx); - - qemu_lockcnt_inc_and_unlock(&ctx->list_lock); - if (!ok) { fdmon_epoll_disable(ctx); } + + qemu_lockcnt_inc_and_unlock(&ctx->list_lock); return ok; } =20 diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c index 6cd665e565..2092d08d24 100644 --- a/util/fdmon-io_uring.c +++ b/util/fdmon-io_uring.c @@ -268,6 +268,11 @@ static int process_cq_ring(AioContext *ctx, AioHandler= List *ready_list) unsigned num_ready =3D 0; unsigned head; =20 + /* If the CQ overflowed then fetch CQEs with a syscall */ + if (io_uring_cq_has_overflow(ring)) { + io_uring_get_events(ring); + } + io_uring_for_each_cqe(ring, head, cqe) { if (process_cqe(ctx, ready_list, cqe)) { num_ready++; @@ -280,6 +285,30 @@ static int process_cq_ring(AioContext *ctx, AioHandler= List *ready_list) return num_ready; } =20 +/* This is where SQEs are submitted in the glib event loop */ +static void fdmon_io_uring_gsource_prepare(AioContext *ctx) +{ + fill_sq_ring(ctx); + if (io_uring_sq_ready(&ctx->fdmon_io_uring)) { + while (io_uring_submit(&ctx->fdmon_io_uring) =3D=3D -EINTR) { + /* Keep trying if syscall was interrupted */ + } + } +} + +static bool fdmon_io_uring_gsource_check(AioContext *ctx) +{ + gpointer tag =3D ctx->io_uring_fd_tag; + return g_source_query_unix_fd(&ctx->source, tag) & G_IO_IN; +} + +/* This is where CQEs are processed in the glib event loop */ +static void fdmon_io_uring_gsource_dispatch(AioContext *ctx, + AioHandlerList *ready_list) +{ + process_cq_ring(ctx, ready_list); +} + static int fdmon_io_uring_wait(AioContext *ctx, AioHandlerList *ready_list, int64_t timeout) { @@ -327,12 +356,17 @@ static const FDMonOps fdmon_io_uring_ops =3D { .update =3D fdmon_io_uring_update, .wait =3D fdmon_io_uring_wait, .need_wait =3D fdmon_io_uring_need_wait, + .gsource_prepare =3D fdmon_io_uring_gsource_prepare, + .gsource_check =3D fdmon_io_uring_gsource_check, + .gsource_dispatch =3D fdmon_io_uring_gsource_dispatch, }; =20 bool fdmon_io_uring_setup(AioContext *ctx) { int ret; =20 + ctx->io_uring_fd_tag =3D NULL; + ret =3D io_uring_queue_init(FDMON_IO_URING_ENTRIES, &ctx->fdmon_io_uri= ng, 0); if (ret !=3D 0) { return false; @@ -340,6 +374,9 @@ bool fdmon_io_uring_setup(AioContext *ctx) =20 QSLIST_INIT(&ctx->submit_list); ctx->fdmon_ops =3D &fdmon_io_uring_ops; + ctx->io_uring_fd_tag =3D g_source_add_unix_fd(&ctx->source, + ctx->fdmon_io_uring.ring_fd, G_IO_IN); + return true; } =20 @@ -364,6 +401,11 @@ void fdmon_io_uring_destroy(AioContext *ctx) QSLIST_REMOVE_HEAD_RCU(&ctx->submit_list, node_submitted); } =20 - ctx->fdmon_ops =3D &fdmon_poll_ops; + g_source_remove_unix_fd(&ctx->source, ctx->io_uring_fd_tag); + ctx->io_uring_fd_tag =3D NULL; + + qemu_lockcnt_lock(&ctx->list_lock); + fdmon_poll_downgrade(ctx); + qemu_lockcnt_unlock(&ctx->list_lock); } } diff --git a/util/fdmon-poll.c b/util/fdmon-poll.c index 17df917cf9..f91dc54944 100644 --- a/util/fdmon-poll.c +++ b/util/fdmon-poll.c @@ -72,6 +72,11 @@ static int fdmon_poll_wait(AioContext *ctx, AioHandlerLi= st *ready_list, =20 /* epoll(7) is faster above a certain number of fds */ if (fdmon_epoll_try_upgrade(ctx, npfd)) { + QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { + if (!QLIST_IS_INSERTED(node, node_deleted) && node->pfd.events= ) { + g_source_remove_poll(&ctx->source, &node->pfd); + } + } npfd =3D 0; /* we won't need pollfds[], reset npfd */ return ctx->fdmon_ops->wait(ctx, ready_list, timeout); } @@ -97,11 +102,92 @@ static void fdmon_poll_update(AioContext *ctx, AioHandler *old_node, AioHandler *new_node) { - /* Do nothing, AioHandler already contains the state we'll need */ + if (old_node && !new_node) { + /* + * If the GSource is in the process of being destroyed then + * g_source_remove_poll() causes an assertion failure. Skip remov= al in + * that case, because glib cleans up its state during destruction + * anyway. + */ + if (!g_source_is_destroyed(&ctx->source)) { + g_source_remove_poll(&ctx->source, &old_node->pfd); + } + } + + if (!old_node && new_node) { + g_source_add_poll(&ctx->source, &new_node->pfd); + } +} + +static void fdmon_poll_gsource_prepare(AioContext *ctx) +{ + /* Do nothing */ +} + +static bool fdmon_poll_gsource_check(AioContext *ctx) +{ + AioHandler *node; + bool result =3D false; + + /* + * We have to walk very carefully in case aio_set_fd_handler is + * called while we're walking. + */ + qemu_lockcnt_inc(&ctx->list_lock); + + QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { + int revents =3D node->pfd.revents & node->pfd.events; + + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + result =3D true; + break; + } + if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + result =3D true; + break; + } + } + + qemu_lockcnt_dec(&ctx->list_lock); + + return result; +} + +static void fdmon_poll_gsource_dispatch(AioContext *ctx, + AioHandlerList *ready_list) +{ + AioHandler *node; + + QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { + int revents; + + revents =3D node->pfd.revents & node->pfd.events; + if (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR) && node->io_read) { + aio_add_ready_handler(ready_list, node, revents); + } else if (revents & (G_IO_OUT | G_IO_ERR) && node->io_write) { + aio_add_ready_handler(ready_list, node, revents); + } + } } =20 const FDMonOps fdmon_poll_ops =3D { .update =3D fdmon_poll_update, .wait =3D fdmon_poll_wait, .need_wait =3D aio_poll_disabled, + .gsource_prepare =3D fdmon_poll_gsource_prepare, + .gsource_check =3D fdmon_poll_gsource_check, + .gsource_dispatch =3D fdmon_poll_gsource_dispatch, }; + +void fdmon_poll_downgrade(AioContext *ctx) +{ + AioHandler *node; + + ctx->fdmon_ops =3D &fdmon_poll_ops; + + QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { + if (!QLIST_IS_INSERTED(node, node_deleted) && node->pfd.events) { + g_source_add_poll(&ctx->source, &node->pfd); + } + } +} --=20 2.49.0 From nobody Wed Apr 2 13:30:23 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1743014077; cv=none; d=zohomail.com; s=zohoarc; b=JHK7E+WSZOW/YDVckXAQ6ZA6X5mA4pPnDexuC63KSvTGeee8MgWb99kLoIIqT2D9IapxJvhsAyMFpwm40XguKfGwmp2nWhj9ZtUc3QJVc87fo8GIqcjEDT9vkekD1FpSXvkC4Ghhu60mSzgpCDdLMppPqgT8gKJIiJcd8RmU0Z0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1743014077; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=1+TRRRr+GYIAG4VyV+8vgtOLkMCbtBvsUV68bR5izEo=; b=mE60QbWHPkg3tOamU0VCWUv5BlcYQW9lo1VAOWyQyXWP9l+P1UojFXE/6mCGbdCDXKVO5a1QFxOeoQ5OT611GQmUsxdDJTqz2IrjGqiiMZfx46AwKqFeiXOyL5xp+KjPxDDyWH4vntzF5xDM7/kka9kCxmnlwX6K7R5WhaTOO08= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1743014077103155.42631467723174; Wed, 26 Mar 2025 11:34:37 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1txVZn-000223-6t; Wed, 26 Mar 2025 14:34:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZi-0001z3-V4 for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:03 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1txVZf-0003Vl-D7 for qemu-devel@nongnu.org; Wed, 26 Mar 2025 14:34:02 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-125-0Ja3Avh2PJKBaRG9LuOKhg-1; Wed, 26 Mar 2025 14:33:54 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 94DC51800349; Wed, 26 Mar 2025 18:33:53 +0000 (UTC) Received: from localhost (unknown [10.2.16.113]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2CDDD1801747; Wed, 26 Mar 2025 18:33:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1743014038; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1+TRRRr+GYIAG4VyV+8vgtOLkMCbtBvsUV68bR5izEo=; b=KhvA2HxcLHcncnd+y1DewHg3hp7p64+R/B6lH7F/omjSHHg7iN6gK3jagKpELodpn4WyXB vt2kWUtT4g4hFp5c3cL67i7USqg+R2QXBYRqmC4wR0EaA29JzciNZrn4Dhpo4OLRizA8Ay UZ9VQCSOAxXNpJFk8mCvcjunqDGWJz4= X-MC-Unique: 0Ja3Avh2PJKBaRG9LuOKhg-1 X-Mimecast-MFC-AGG-ID: 0Ja3Avh2PJKBaRG9LuOKhg_1743014033 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Cc: qemu-block@nongnu.org, Kevin Wolf , Stefan Hajnoczi , Stefan Weil , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Hanna Reitz , Paolo Bonzini , Fam Zheng Subject: [PATCH 4/4] aio: remove aio_context_use_g_source() Date: Wed, 26 Mar 2025 14:33:40 -0400 Message-ID: <20250326183340.1010531-5-stefanha@redhat.com> In-Reply-To: <20250326183340.1010531-1-stefanha@redhat.com> References: <20250326183340.1010531-1-stefanha@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=stefanha@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1743014078824019100 Content-Type: text/plain; charset="utf-8" There is no need for aio_context_use_g_source() now that epoll(7) and io_uring(7) file descriptor monitoring works with the glib event loop. AioContext doesn't need to be notified that GSource is being used. Signed-off-by: Stefan Hajnoczi --- include/block/aio.h | 3 --- tests/unit/test-nested-aio-poll.c | 6 ------ util/aio-posix.c | 12 ------------ util/aio-win32.c | 4 ---- util/async.c | 1 - 5 files changed, 26 deletions(-) diff --git a/include/block/aio.h b/include/block/aio.h index 39ed86d14d..1657740a0e 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -728,9 +728,6 @@ void aio_context_setup(AioContext *ctx); */ void aio_context_destroy(AioContext *ctx); =20 -/* Used internally, do not call outside AioContext code */ -void aio_context_use_g_source(AioContext *ctx); - /** * aio_context_set_poll_params: * @ctx: the aio context diff --git a/tests/unit/test-nested-aio-poll.c b/tests/unit/test-nested-aio= -poll.c index 45484e745b..d13ecccd8c 100644 --- a/tests/unit/test-nested-aio-poll.c +++ b/tests/unit/test-nested-aio-poll.c @@ -83,12 +83,6 @@ static void test(void) /* Enable polling */ aio_context_set_poll_params(td.ctx, 1000000, 2, 2, &error_abort); =20 - /* - * The GSource is unused but this has the side-effect of changing the = fdmon - * that AioContext uses. - */ - aio_get_g_source(td.ctx); - /* Make the event notifier active (set) right away */ event_notifier_init(&td.poll_notifier, 1); aio_set_event_notifier(td.ctx, &td.poll_notifier, diff --git a/util/aio-posix.c b/util/aio-posix.c index 8ed1c4a405..6c2ee0b0b4 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -736,18 +736,6 @@ void aio_context_destroy(AioContext *ctx) aio_free_deleted_handlers(ctx); } =20 -void aio_context_use_g_source(AioContext *ctx) -{ - /* - * Disable io_uring when the glib main loop is used because it doesn't - * support mixed glib/aio_poll() usage. It relies on aio_poll() being - * called regularly so that changes to the monitored file descriptors = are - * submitted, otherwise a list of pending fd handlers builds up. - */ - fdmon_io_uring_destroy(ctx); - aio_free_deleted_handlers(ctx); -} - void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, int64_t grow, int64_t shrink, Error **err= p) { diff --git a/util/aio-win32.c b/util/aio-win32.c index 6583d5c5f3..34c4074133 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -427,10 +427,6 @@ void aio_context_destroy(AioContext *ctx) { } =20 -void aio_context_use_g_source(AioContext *ctx) -{ -} - void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, int64_t grow, int64_t shrink, Error **err= p) { diff --git a/util/async.c b/util/async.c index 863416dee9..11954f8931 100644 --- a/util/async.c +++ b/util/async.c @@ -430,7 +430,6 @@ static GSourceFuncs aio_source_funcs =3D { =20 GSource *aio_get_g_source(AioContext *ctx) { - aio_context_use_g_source(ctx); g_source_ref(&ctx->source); return &ctx->source; } --=20 2.49.0