get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2194214/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2194214,
    "url": "http://patchwork.ozlabs.org/api/patches/2194214/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260207120901.17222-6-hibriansong@gmail.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260207120901.17222-6-hibriansong@gmail.com>",
    "list_archive_url": null,
    "date": "2026-02-07T12:08:59",
    "name": "[v4,5/6] fuse: safe termination for io_uring",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "cb43eb27d6f9121a7be77996e7cc6c6601624472",
    "submitter": {
        "id": 90672,
        "url": "http://patchwork.ozlabs.org/api/people/90672/?format=api",
        "name": "Brian Song",
        "email": "hibriansong@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260207120901.17222-6-hibriansong@gmail.com/mbox/",
    "series": [
        {
            "id": 491376,
            "url": "http://patchwork.ozlabs.org/api/series/491376/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=491376",
            "date": "2026-02-07T12:08:56",
            "name": "add fuse-over-io_uring support",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/491376/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2194214/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2194214/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20230601 header.b=fKn5MkuZ;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4f7VFH6wHbz1xvj\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 07 Feb 2026 23:12:03 +1100 (AEDT)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1voh8h-0007FR-76; Sat, 07 Feb 2026 07:10:15 -0500",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <hibriansong@gmail.com>)\n id 1voh8d-0007DV-GK\n for qemu-devel@nongnu.org; Sat, 07 Feb 2026 07:10:12 -0500",
            "from mail-pj1-x1034.google.com ([2607:f8b0:4864:20::1034])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <hibriansong@gmail.com>)\n id 1voh8a-00036L-TH\n for qemu-devel@nongnu.org; Sat, 07 Feb 2026 07:10:10 -0500",
            "by mail-pj1-x1034.google.com with SMTP id\n 98e67ed59e1d1-3530e7b3dc2so2570090a91.3\n for <qemu-devel@nongnu.org>; Sat, 07 Feb 2026 04:10:08 -0800 (PST)",
            "from brian.. (n058152022104.netvigator.com. [58.152.22.104])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-354b30f899csm2178530a91.3.2026.02.07.04.10.03\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sat, 07 Feb 2026 04:10:06 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20230601; t=1770466207; x=1771071007; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=H78Df0v0meU3GDrKU4J2lfRzsB4Ror34DjemRoX9SzM=;\n b=fKn5MkuZlDjaeZwMGaXkYQl+JYdNYMv0Ljh8y+pwyqAW42XUroEEpyOQb+rXR2SC0L\n rTveQBD8nZvh8sX/C9Xe06by/uuN4PEIPeINxdNj7HPcF+KI28iBXSDl/w83CaL7exbB\n CwxMJ/ha0lypORF3mW+DSAzVcf41i661BChEcx0718/J3he6Q6s7lnIgA/WB/MdjAk4H\n A9S8biGAhMitiiQSWQue1x47ErzL4czESS5mZsc0nB4ylItrUQdZ5atOHibrFLU6wVBZ\n Qtxzy2myHK32MWxgLZNxmGpKucPGDuKQL6MJRsbTEvNz5HYnCQcj5LEJWh3TxFBMVY8C\n uNyg==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1770466207; x=1771071007;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=H78Df0v0meU3GDrKU4J2lfRzsB4Ror34DjemRoX9SzM=;\n b=ngQyok/NClFUyJYi4BXkwy2efA9nqh0SZye/KNTeHXtSA7c2QmG8712irl8u6bEbde\n 4Oni6dCs+uL8+jfhz0Wd9Z6D5/dMhM63MOJFQu5nto0FUWi9rv2MBTw3skXV4CNIKGDn\n imjHAWi3uUUPe5oddmtdfDLxu9CEWbr0dCwaCYqSqa5JLH4OU9FJyE/TBuQJ/XUCJ+0v\n QUbZvyCod14s9G6x+9wiRFykm36fHn2Oy0sQnz/uvejQY9GpoePo39fKDSbTGpt6hVbB\n Ux37OL/UHLl3SRJedWjL0D/2slh7SHTRD1meir68C5IG3bBOqZrcAVqOOIJOdWVy+uSv\n FNAQ==",
        "X-Gm-Message-State": "AOJu0YwraELw4cgNbsLGhTYtARwsDoA+/Tn5kSeyQpl6U9A8tLCW3dDb\n NlHsBbpWu18ulAdUZPc+BiHtIyQl7ZRCsIUlyDHLXbQORD/+ZQYsHizf",
        "X-Gm-Gg": "AZuq6aKIyl/8aJm2RAm+kB3fxrVkMBfHO4qPxXcCnPDJejs3bUfBGb+N7uOmzGSSH0k\n NcNcafnvXWsXvRL2zq8UE1N06jaj2QhZiseJV315r1ujRxqQCrSSgOTuB8EZ3vcyyXBifYYM8XH\n 2RqFpCNhDtmqYdAK7L229t4R3xCz1zOSlki7OVP0wYK4dZzq1ljYSydsTxeCDWwt1NuEeCLUpYW\n ZVvCm71JSexaKsjQmmf/KGqpzhi02+HAMoV2fUIlhL2ufxIgBdSo6qfGthVctY1g5WVnhIwMW8D\n BJvtgBzB7d9j36sT4J7XEuSnoLLKFJsq+OsEjLueBlWUnfEH5xIMUh7CTeLxizOUciDzykJK/+N\n dEx4b+34+59wsEW+WU+6TEyz0l0wQ6drW+LG9p6ezlbW+M9WOIFvC7K/wHDIcjWcgNe7xSmKBlU\n ZUxtxcJHrOim6Lh3WdmX4F13XLsiqIbDenh2V2UHEnwqBK5W6Q",
        "X-Received": "by 2002:a17:90b:35cc:b0:353:5595:3247 with SMTP id\n 98e67ed59e1d1-354b3c74a3fmr6051387a91.12.1770466207514;\n Sat, 07 Feb 2026 04:10:07 -0800 (PST)",
        "From": "Brian Song <hibriansong@gmail.com>",
        "To": "qemu-block@nongnu.org",
        "Cc": "qemu-devel@nongnu.org, hibriansong@gmail.com, hreitz@redhat.com,\n kwolf@redhat.com, eblake@redhat.com, armbru@redhat.com,\n stefanha@redhat.com, fam@euphon.net, bernd@bsbernd.com",
        "Subject": "[Patch v4 5/6] fuse: safe termination for io_uring",
        "Date": "Sat,  7 Feb 2026 20:08:59 +0800",
        "Message-ID": "<20260207120901.17222-6-hibriansong@gmail.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260207120901.17222-1-hibriansong@gmail.com>",
        "References": "<20260207120901.17222-1-hibriansong@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=2607:f8b0:4864:20::1034;\n envelope-from=hibriansong@gmail.com; helo=mail-pj1-x1034.google.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, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n 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": "qemu development <qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"
    },
    "content": "When a termination signal is received, the storage-export-daemon stops\nthe export, exits the main loop (main_loop_wait), and begins resource\ncleanup. However, some FUSE_IO_URING_CMD_COMMIT_AND_FETCH SQEs may\nremain pending in the kernel, waiting for incoming FUSE requests.\n\nCurrently, there is no way to manually cancel these pending CQEs in the\nkernel. As a result, after export termination, the related data\nstructures might be deleted before the pending CQEs return, causing the\nCQE handler to be invoked after it has been freed, which may lead to a\nsegfault.\n\nAs a workaround, when submitting an SQE to the kernel, we increment the\nblock reference (blk_exp_ref) to prevent the CQE handler from being\ndeleted during export termination. Once the CQE is received, we\ndecrement the reference (blk_exp_unref).\n\nHowever, this introduces a new issue: if no new FUSE requests arrive,\nthe pending SQEs held by the kernel will never complete. Consequently,\nthe export reference count never drops to zero, preventing the export\nfrom shutting down cleanly.\n\nTo resolve this, we schedule a Bottom Half (BH) for each FUSE queue\nduring the export shutdown phase. The BH closes the fuse_fd to prevent\nrace conditions, while the session is unmounted during the remainder of\nthe shutdown sequence. This explicitly aborts all pending SQEs in the\nkernel, forcing the corresponding CQEs to return. This triggers the\nrelease of held references, allowing the export to be freed safely.\n\nSuggested-by: Kevin Wolf <kwolf@redhat.com>\nSuggested-by: Stefan Hajnoczi <stefanha@redhat.com>\nSigned-off-by: Brian Song <hibriansong@gmail.com>\n---\n block/export/fuse.c | 100 +++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 90 insertions(+), 10 deletions(-)\n\n--\n2.43.0",
    "diff": "diff --git a/block/export/fuse.c b/block/export/fuse.c\nindex c117e081cd..abae83041b 100644\n--- a/block/export/fuse.c\n+++ b/block/export/fuse.c\n@@ -934,6 +934,57 @@ static void read_from_fuse_fd(void *opaque)\n     qemu_coroutine_enter(co);\n }\n\n+#ifdef CONFIG_LINUX_IO_URING\n+static void fuse_export_delete_uring(FuseExport *exp)\n+{\n+    exp->is_uring = false;\n+    exp->uring_started = false;\n+\n+    for (int i = 0; i < exp->num_uring_queues; i++) {\n+        FuseUringQueue *rq = &exp->uring_queues[i];\n+\n+        for (int j = 0; j < FUSE_DEFAULT_URING_QUEUE_DEPTH; j++) {\n+            g_free(rq->ent[j].req_payload);\n+        }\n+        g_free(rq->ent);\n+    }\n+\n+    g_free(exp->uring_queues);\n+}\n+#endif\n+\n+/**\n+ * The Linux kernel currently lacks support for asynchronous cancellation\n+ * of FUSE-over-io_uring SQEs. This can lead to a race where an IOThread may\n+ * access fuse_fd after it is closed but before pending SQEs are canceled,\n+ * potentially operating on a newly reused file descriptor.\n+ *\n+ * Therefore, schedule a BH in the IOThread to close and invalidate fuse_fd,\n+ * to avoid races on fuse_fd.\n+ */\n+#ifdef CONFIG_LINUX_IO_URING\n+static void close_fuse_fd(void *opaque)\n+{\n+    FuseQueue *q = opaque;\n+\n+    if (q->fuse_fd >= 0) {\n+        close(q->fuse_fd);\n+        q->fuse_fd = -1;\n+    }\n+}\n+#endif\n+\n+/**\n+ * During exit in FUSE-over-io_uring mode, qemu-storage-daemon requests\n+ * shutdown in main() and then immediately tears down the block export.\n+ * However, SQEs already submitted under FUSE-over-io_uring may still complete\n+ * and generate CQEs that continue to hold references to the block export,\n+ * preventing it from being freed cleanly.\n+ *\n+ * Since the Linux kernel currently lacks support for asynchronous cancellation\n+ * of FUSE-over-io_uring SQEs, this function aborts the connection and cancels\n+ * all pending SQEs to ensure a safe teardown.\n+ */\n static void fuse_export_shutdown(BlockExport *blk_exp)\n {\n     FuseExport *exp = container_of(blk_exp, FuseExport, common);\n@@ -949,18 +1000,42 @@ static void fuse_export_shutdown(BlockExport *blk_exp)\n          */\n         g_hash_table_remove(exports, exp->mountpoint);\n     }\n+\n+#ifdef CONFIG_LINUX_IO_URING\n+    if (exp->uring_started) {\n+        for (size_t i = 0; i < exp->num_fuse_queues; i++) {\n+            FuseQueue *q = &exp->queues[i];\n+\n+            /* Queue 0's FD belongs to the FUSE session */\n+            if (i > 0) {\n+                aio_bh_schedule_oneshot(q->ctx, close_fuse_fd, q);\n+            }\n+        }\n+\n+        /* To cancel all pending SQEs */\n+        if (exp->fuse_session) {\n+            if (exp->mounted) {\n+                fuse_session_unmount(exp->fuse_session);\n+            }\n+            fuse_session_destroy(exp->fuse_session);\n+        }\n+        g_free(exp->mountpoint);\n+    }\n+#endif\n }\n\n static void fuse_export_delete(BlockExport *blk_exp)\n {\n     FuseExport *exp = container_of(blk_exp, FuseExport, common);\n\n-    for (int i = 0; i < exp->num_fuse_queues; i++) {\n+    for (size_t i = 0; i < exp->num_fuse_queues; i++) {\n         FuseQueue *q = &exp->queues[i];\n\n-        /* Queue 0's FD belongs to the FUSE session */\n-        if (i > 0 && q->fuse_fd >= 0) {\n-            close(q->fuse_fd);\n+        if (!exp->uring_started) {\n+            /* Queue 0's FD belongs to the FUSE session */\n+            if (i > 0 && q->fuse_fd >= 0) {\n+                close(q->fuse_fd);\n+            }\n         }\n         if (q->spillover_buf) {\n             qemu_vfree(q->spillover_buf);\n@@ -968,15 +1043,20 @@ static void fuse_export_delete(BlockExport *blk_exp)\n     }\n     g_free(exp->queues);\n\n-    if (exp->fuse_session) {\n-        if (exp->mounted) {\n-            fuse_session_unmount(exp->fuse_session);\n+    if (exp->uring_started) {\n+#ifdef CONFIG_LINUX_IO_URING\n+        fuse_export_delete_uring(exp);\n+#endif\n+    } else {\n+        if (exp->fuse_session) {\n+            if (exp->mounted) {\n+                fuse_session_unmount(exp->fuse_session);\n+            }\n+            fuse_session_destroy(exp->fuse_session);\n         }\n\n-        fuse_session_destroy(exp->fuse_session);\n+        g_free(exp->mountpoint);\n     }\n-\n-    g_free(exp->mountpoint);\n }\n\n /**\n",
    "prefixes": [
        "v4",
        "5/6"
    ]
}