get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2197749,
    "url": "http://patchwork.ozlabs.org/api/patches/2197749/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260218132633.29748-19-hreitz@redhat.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": "<20260218132633.29748-19-hreitz@redhat.com>",
    "list_archive_url": null,
    "date": "2026-02-18T13:26:27",
    "name": "[v4,18/24] fuse: Process requests in coroutines",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "a487105ae382003a6c442b133c65aa810ed977c4",
    "submitter": {
        "id": 82279,
        "url": "http://patchwork.ozlabs.org/api/people/82279/?format=api",
        "name": "Hanna Czenczek",
        "email": "hreitz@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260218132633.29748-19-hreitz@redhat.com/mbox/",
    "series": [
        {
            "id": 492547,
            "url": "http://patchwork.ozlabs.org/api/series/492547/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=492547",
            "date": "2026-02-18T13:26:09",
            "name": "export/fuse: Use coroutines and multi-threading",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/492547/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2197749/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2197749/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 (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KddgW/6A;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=google header.b=mkjzVpXL;\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 4fGHYw6Lzcz1xwr\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 19 Feb 2026 00:35:00 +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 1vshfh-0004IF-M2; Wed, 18 Feb 2026 08:32:53 -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 <hreitz@redhat.com>) id 1vshfe-0004Ev-Tk\n for qemu-devel@nongnu.org; Wed, 18 Feb 2026 08:32:50 -0500",
            "from us-smtp-delivery-124.mimecast.com ([170.10.133.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <hreitz@redhat.com>) id 1vshfT-0005pY-8W\n for qemu-devel@nongnu.org; Wed, 18 Feb 2026 08:32:50 -0500",
            "from mail-wr1-f69.google.com (mail-wr1-f69.google.com\n [209.85.221.69]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-544-5hH5UpFdOxymyHA70RAEEQ-1; Wed, 18 Feb 2026 08:27:30 -0500",
            "by mail-wr1-f69.google.com with SMTP id\n ffacd0b85a97d-437681ecd32so4394591f8f.1\n for <qemu-devel@nongnu.org>; Wed, 18 Feb 2026 05:27:30 -0800 (PST)",
            "from localhost\n (p200300cfd737d029edef7b8da7441ac2.dip0.t-ipconnect.de.\n [2003:cf:d737:d029:edef:7b8d:a744:1ac2])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-43796a74918sm41909165f8f.17.2026.02.18.05.27.26\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 18 Feb 2026 05:27:27 -0800 (PST)"
        ],
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1771421557;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:\n content-type:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=hC0XQ436Lp4KW+507FjuStJRdl+9Hpi0tG50/F5Xsmg=;\n b=KddgW/6Av0EVYYNdORWdgeNZTRDkBCWt0/4l7CWuuuyF9gPOPybIs+sj4xso0RWELFonDq\n ZP9DWlxHcLxuEU8xeCBWJ64/Etby2nFCVOau/nP1my/R/4Kzb/PEb+YfVD5PDfRINAWckM\n tlxxe4/9XCqUMnNrt8A7THu+hi5biOQ=",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com; s=google; t=1771421249; x=1772026049; 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=hC0XQ436Lp4KW+507FjuStJRdl+9Hpi0tG50/F5Xsmg=;\n b=mkjzVpXLLrmsUtYIC1saRf7lYO76GNhqNixeamT1ktFA2VrO61xfZ5c4Ap9uH/beOj\n jss514UoNGBRRsiR4aOxRBTC+85hPOG3x6rwf5O4VaDl0gCS/xVOyzFxXBH/tjcyaqXg\n OBefCqis+jtWoN2dcvdEzBRoPZoVfP3cXtM88A+CHV1aQO/SZoTmoyxN4Jhbr47xwx/g\n l97QUlOq2APegnu+2iDlojax0lRjBrMMkGqPzY11N23rFqaHBeJneguP8dnbxiJKaX92\n N1e1S7eXL//eO+MHQaZBz/uCb9wiqeDnIRmRJuALPFbAV7I8TbRzXJp8Ew0XPNjQfUF5\n E+JQ=="
        ],
        "X-MC-Unique": "5hH5UpFdOxymyHA70RAEEQ-1",
        "X-Mimecast-MFC-AGG-ID": "5hH5UpFdOxymyHA70RAEEQ_1771421250",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1771421249; x=1772026049;\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=hC0XQ436Lp4KW+507FjuStJRdl+9Hpi0tG50/F5Xsmg=;\n b=MeQ6QUQl6e9cFTXb5Yp7i1dfy4NokAxobuBp5L3NEcK4zqNRvqCsk1753/Qsb7FuqO\n fzmno4eFmYZIfqZvnmPRO4HDnG9YDnCDMxfHqJ2vyGXG6cJL1cD3N0EpmtCV9ONhBkVo\n 0q4kS8MwwglV+Js64RxVLCjrDJ283WJS7FzEQ53ZLzigApTeOxKG3svP+3Yod9s94rBj\n 5LC/HCDCANe0mJQbxFBRELjYrZe8RlXVILvI5Fzag/NGfkOrrv4T73g/fyssH9Yb9msj\n j6bWW+FYCHSTAIK/dqkIPlzkCvJZwX7tw2e7VLGToQeBoQPzLNyTKnUAf5iPZoqmigXH\n eVYQ==",
        "X-Gm-Message-State": "AOJu0Yxl/EPT57QCWZr2URFQ5kJNnAZpdiqttNHHYNwSSGCMEyUtHfMI\n ODDbpwt9gWbS2whibTcf9nqdg0fHVAXmo+Nrt+/n369U0lsxhSDCUhRTDy/1rMKRV3EoiRmn1sD\n zKi1ifRDm8s/NCRYATuVWvUacOXT1+Q63WJIMkW9Uhy4TIvK5qqSuM+zf",
        "X-Gm-Gg": "AZuq6aIedWPFO7oVVxnZYxJyKbnyZ3M8yp06j/kiZ18BWb80FNEx56zI/PZfgFwjH1x\n ggJoGvAvSaKrkKiIYWCTiKwFniXp3HruPfEb73XerVDEZDAUnpsj1zZdm+aAq/xzOZaQRqQhAXa\n 1JFjwyvrPcZFUTaFEg5zBlbGysFpkR8RfJuHbr98duln3ajfQ7z0BHMc+d7rkdi/Y0qW1w4AwEg\n 6CvurhuRd/VjxqDYw11tLAwGfDgSDwOBYhC9eQI+5KjHESgGSOTSRYHe4n0nCefZug2aap37V5p\n Pgo3N7cFJWXA2dUio79eUwsPLm6M62iYGFyrOK5ro1p2wSWVQWnRVfs8tBMcxjWf4yPuu84a3v5\n N6xWavQz5v6Hk1oko3iez2Uo9o6dxCzG21w7okvKXaoPB1LgiwFpfuSZR2bX22+lQaDCgtzwfUt\n JiAk6a",
        "X-Received": [
            "by 2002:a05:6000:2c01:b0:437:6d8c:c07f with SMTP id\n ffacd0b85a97d-4379dba4416mr24878176f8f.52.1771421249092;\n Wed, 18 Feb 2026 05:27:29 -0800 (PST)",
            "by 2002:a05:6000:2c01:b0:437:6d8c:c07f with SMTP id\n ffacd0b85a97d-4379dba4416mr24878113f8f.52.1771421248407;\n Wed, 18 Feb 2026 05:27:28 -0800 (PST)"
        ],
        "From": "Hanna Czenczek <hreitz@redhat.com>",
        "To": "qemu-block@nongnu.org",
        "Cc": "qemu-devel@nongnu.org, Hanna Czenczek <hreitz@redhat.com>,\n Kevin Wolf <kwolf@redhat.com>, Brian Song <hibriansong@gmail.com>",
        "Subject": "[PATCH v4 18/24] fuse: Process requests in coroutines",
        "Date": "Wed, 18 Feb 2026 14:26:27 +0100",
        "Message-ID": "<20260218132633.29748-19-hreitz@redhat.com>",
        "X-Mailer": "git-send-email 2.53.0",
        "In-Reply-To": "<20260218132633.29748-1-hreitz@redhat.com>",
        "References": "<20260218132633.29748-1-hreitz@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Type": [
            "text/plain; charset=UTF-8",
            "text/plain; charset=UTF-8"
        ],
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=170.10.133.124; envelope-from=hreitz@redhat.com;\n 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.043,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001,\n SPF_HELO_PASS=-0.001,\n 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": "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": "Make fuse_process_request() a coroutine_fn (fuse_co_process_request())\nand have read_from_fuse_fd() launch it inside of a newly created\ncoroutine instead of running it synchronously.  This way, we can process\nrequests in parallel.\n\nThese are the benchmark results, compared to (a) the original results\nwith libfuse, and (b) the results after switching away from libfuse\n(i.e. before this patch):\n\nfile:                (vs. libfuse / vs. no libfuse)\n  read:\n    seq aio:    97.8k ±1.5k (-2%  / -8%)\n    rand aio:   95.8k ±3.4k (+90% / +98%)\n    seq sync:   34.5k ±1.0k (-4%  / -3%)\n    rand sync:   9.9k ±0.1k (-1%  / -1%)\n  write:\n    seq aio:    68.7k ±1.3k (-5%  / -10%)\n    rand aio:   68.9k ±1.1k (-2%  / -10%)\n    seq sync:   30.6k ±0.9k (±0%  / -3%)\n    rand sync:  30.6k ±0.6k (+1%  / -1%)\nnull:\n  read:\n    seq aio:   174.5k ±6.8k (+11% / +8%)\n    rand aio:  170.9k ±5.7k (+8%  / +3%)\n    seq sync:   82.0k ±3.3k (+2%  / +2%)\n    rand sync:  78.0k ±4.0k (+1%  / -1%)\n  write:\n    seq aio:   196.0k ±2.8k (+27% / +6%)\n    rand aio:  191.2k ±7.9k (+24% / +2%)\n    seq sync:   83.3k ±4.4k (+9%  / +1%)\n    rand sync:  79.5k ±4.4k (+9%  / +1%)\n\nSo there is not much difference, especially when compared to how it was\nwith libfuse, except for the randread AIO case with an actual file.\nThat improves greatly.\n\nSigned-off-by: Hanna Czenczek <hreitz@redhat.com>\n---\n block/export/fuse.c | 174 ++++++++++++++++++++++++++------------------\n 1 file changed, 102 insertions(+), 72 deletions(-)",
    "diff": "diff --git a/block/export/fuse.c b/block/export/fuse.c\nindex 8c5a1d397d..b60affe86b 100644\n--- a/block/export/fuse.c\n+++ b/block/export/fuse.c\n@@ -27,6 +27,7 @@\n #include \"block/qapi.h\"\n #include \"qapi/error.h\"\n #include \"qapi/qapi-commands-block.h\"\n+#include \"qemu/coroutine.h\"\n #include \"qemu/error-report.h\"\n #include \"qemu/main-loop.h\"\n #include \"system/block-backend.h\"\n@@ -182,9 +183,9 @@ static int mount_fuse_export(FuseExport *exp, Error **errp);\n static bool is_regular_file(const char *path, Error **errp);\n \n static void read_from_fuse_fd(void *opaque);\n-static void fuse_process_request(FuseExport *exp,\n-                                 const FuseRequestInHeader *in_hdr,\n-                                 const void *data_buffer);\n+static void coroutine_fn\n+fuse_co_process_request(FuseExport *exp, const FuseRequestInHeader *in_hdr,\n+                        const void *data_buffer);\n static int fuse_write_err(int fd, const struct fuse_in_header *in_hdr, int err);\n \n static void fuse_inc_in_flight(FuseExport *exp)\n@@ -519,9 +520,14 @@ static ssize_t req_op_hdr_len(const FuseRequestInHeader *in_hdr)\n }\n \n /**\n- * Try to read and process a single request from the FUSE FD.\n+ * Try to read a single request from the FUSE FD.\n+ * Takes a FuseExport pointer in `opaque`.\n+ *\n+ * Assumes the export's in-flight counter has already been incremented.\n+ *\n+ * If a request is available, process it.\n  */\n-static void read_from_fuse_fd(void *opaque)\n+static void coroutine_fn co_read_from_fuse_fd(void *opaque)\n {\n     FuseExport *exp = opaque;\n     int fuse_fd = exp->fuse_fd;\n@@ -532,8 +538,6 @@ static void read_from_fuse_fd(void *opaque)\n     struct iovec iov[2];\n     ssize_t op_hdr_len;\n \n-    fuse_inc_in_flight(exp);\n-\n     if (unlikely(qatomic_read(&exp->halted))) {\n         goto no_request;\n     }\n@@ -602,13 +606,29 @@ static void read_from_fuse_fd(void *opaque)\n         release_write_data_buffer(exp, &data_buffer);\n     }\n \n-    fuse_process_request(exp, in_hdr, data_buffer);\n+    fuse_co_process_request(exp, in_hdr, data_buffer);\n \n no_request:\n     release_write_data_buffer(exp, &data_buffer);\n     fuse_dec_in_flight(exp);\n }\n \n+/**\n+ * Try to read and process a single request from the FUSE FD.\n+ * (To be used as a handler for when the FUSE FD becomes readable.)\n+ * Takes a FuseExport pointer in `opaque`.\n+ */\n+static void read_from_fuse_fd(void *opaque)\n+{\n+    FuseExport *exp = opaque;\n+    Coroutine *co;\n+\n+    co = qemu_coroutine_create(co_read_from_fuse_fd, exp);\n+    /* Decremented by co_read_from_fuse_fd() */\n+    fuse_inc_in_flight(exp);\n+    qemu_coroutine_enter(co);\n+}\n+\n static void fuse_export_shutdown(BlockExport *blk_exp)\n {\n     FuseExport *exp = container_of(blk_exp, FuseExport, common);\n@@ -683,8 +703,9 @@ static bool is_regular_file(const char *path, Error **errp)\n  * Process FUSE INIT.\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_init(FuseExport *exp, struct fuse_init_out *out,\n-                         const struct fuse_init_in_compat *in)\n+static ssize_t coroutine_fn\n+fuse_co_init(FuseExport *exp, struct fuse_init_out *out,\n+             const struct fuse_init_in_compat *in)\n {\n     const uint32_t supported_flags = FUSE_ASYNC_READ | FUSE_ASYNC_DIO;\n \n@@ -739,7 +760,8 @@ static ssize_t fuse_init(FuseExport *exp, struct fuse_init_out *out,\n /**\n  * Return some filesystem information, just to not break e.g. `df`.\n  */\n-static ssize_t fuse_statfs(FuseExport *exp, struct fuse_statfs_out *out)\n+static ssize_t coroutine_fn\n+fuse_co_statfs(FuseExport *exp, struct fuse_statfs_out *out)\n {\n     BlockDriverState *root_bs;\n     uint32_t opt_transfer = 512;\n@@ -767,17 +789,18 @@ static ssize_t fuse_statfs(FuseExport *exp, struct fuse_statfs_out *out)\n  * Let clients get file attributes (i.e., stat() the file).\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_getattr(FuseExport *exp, struct fuse_attr_out *out)\n+static ssize_t coroutine_fn\n+fuse_co_getattr(FuseExport *exp, struct fuse_attr_out *out)\n {\n     int64_t length, allocated_blocks;\n     time_t now = time(NULL);\n \n-    length = blk_getlength(exp->common.blk);\n+    length = blk_co_getlength(exp->common.blk);\n     if (length < 0) {\n         return length;\n     }\n \n-    allocated_blocks = bdrv_get_allocated_file_size(blk_bs(exp->common.blk));\n+    allocated_blocks = bdrv_co_get_allocated_file_size(blk_bs(exp->common.blk));\n     if (allocated_blocks <= 0) {\n         allocated_blocks = DIV_ROUND_UP(length, 512);\n     } else {\n@@ -804,8 +827,9 @@ static ssize_t fuse_getattr(FuseExport *exp, struct fuse_attr_out *out)\n     return sizeof(*out);\n }\n \n-static int fuse_do_truncate(const FuseExport *exp, int64_t size,\n-                            bool req_zero_write, PreallocMode prealloc)\n+static int coroutine_fn\n+fuse_co_do_truncate(const FuseExport *exp, int64_t size, bool req_zero_write,\n+                    PreallocMode prealloc)\n {\n     uint64_t blk_perm, blk_shared_perm;\n     BdrvRequestFlags truncate_flags = 0;\n@@ -834,8 +858,8 @@ static int fuse_do_truncate(const FuseExport *exp, int64_t size,\n         }\n     }\n \n-    ret = blk_truncate(exp->common.blk, size, true, prealloc,\n-                       truncate_flags, NULL);\n+    ret = blk_co_truncate(exp->common.blk, size, true, prealloc,\n+                          truncate_flags, NULL);\n \n     if (add_resize_perm) {\n         /* Must succeed, because we are only giving up the RESIZE permission */\n@@ -856,9 +880,9 @@ static int fuse_do_truncate(const FuseExport *exp, int64_t size,\n  * they cannot be given non-owner access.\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out,\n-                            uint32_t to_set, uint64_t size, uint32_t mode,\n-                            uint32_t uid, uint32_t gid)\n+static ssize_t coroutine_fn\n+fuse_co_setattr(FuseExport *exp, struct fuse_attr_out *out, uint32_t to_set,\n+                uint64_t size, uint32_t mode, uint32_t uid, uint32_t gid)\n {\n     int supported_attrs;\n     int ret;\n@@ -895,7 +919,7 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out,\n             return -EACCES;\n         }\n \n-        ret = fuse_do_truncate(exp, size, true, PREALLOC_MODE_OFF);\n+        ret = fuse_co_do_truncate(exp, size, true, PREALLOC_MODE_OFF);\n         if (ret < 0) {\n             return ret;\n         }\n@@ -914,7 +938,7 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out,\n         exp->st_gid = gid;\n     }\n \n-    return fuse_getattr(exp, out);\n+    return fuse_co_getattr(exp, out);\n }\n \n /**\n@@ -922,7 +946,8 @@ static ssize_t fuse_setattr(FuseExport *exp, struct fuse_attr_out *out,\n  * just acknowledge the request.\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_open(FuseExport *exp, struct fuse_open_out *out)\n+static ssize_t coroutine_fn\n+fuse_co_open(FuseExport *exp, struct fuse_open_out *out)\n {\n     *out = (struct fuse_open_out) {\n         .open_flags = FOPEN_DIRECT_IO | FOPEN_PARALLEL_DIRECT_WRITES,\n@@ -936,8 +961,8 @@ static ssize_t fuse_open(FuseExport *exp, struct fuse_open_out *out)\n  * Returns the buffer (read) size on success, and -errno on error.\n  * After use, *bufptr must be freed via qemu_vfree().\n  */\n-static ssize_t fuse_read(FuseExport *exp, void **bufptr,\n-                         uint64_t offset, uint32_t size)\n+static ssize_t coroutine_fn\n+fuse_co_read(FuseExport *exp, void **bufptr, uint64_t offset, uint32_t size)\n {\n     int64_t blk_len;\n     void *buf;\n@@ -952,7 +977,7 @@ static ssize_t fuse_read(FuseExport *exp, void **bufptr,\n      * Clients will expect short reads at EOF, so we have to limit\n      * offset+size to the image length.\n      */\n-    blk_len = blk_getlength(exp->common.blk);\n+    blk_len = blk_co_getlength(exp->common.blk);\n     if (blk_len < 0) {\n         return blk_len;\n     }\n@@ -971,7 +996,7 @@ static ssize_t fuse_read(FuseExport *exp, void **bufptr,\n         return -ENOMEM;\n     }\n \n-    ret = blk_pread(exp->common.blk, offset, size, buf, 0);\n+    ret = blk_co_pread(exp->common.blk, offset, size, buf, 0);\n     if (ret < 0) {\n         qemu_vfree(buf);\n         return ret;\n@@ -985,8 +1010,9 @@ static ssize_t fuse_read(FuseExport *exp, void **bufptr,\n  * Handle client writes to the exported image.  @buf has the data to be written.\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out,\n-                          uint64_t offset, uint32_t size, const void *buf)\n+static ssize_t coroutine_fn\n+fuse_co_write(FuseExport *exp, struct fuse_write_out *out,\n+              uint64_t offset, uint32_t size, const void *buf)\n {\n     int64_t blk_len;\n     int ret;\n@@ -1005,7 +1031,7 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out,\n      * Clients will expect short writes at EOF, so we have to limit\n      * offset+size to the image length.\n      */\n-    blk_len = blk_getlength(exp->common.blk);\n+    blk_len = blk_co_getlength(exp->common.blk);\n     if (blk_len < 0) {\n         return blk_len;\n     }\n@@ -1021,7 +1047,8 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out,\n         return -EINVAL;\n     } else if (offset + size > blk_len) {\n         if (exp->growable) {\n-            ret = fuse_do_truncate(exp, offset + size, true, PREALLOC_MODE_OFF);\n+            ret = fuse_co_do_truncate(exp, offset + size, true,\n+                                      PREALLOC_MODE_OFF);\n             if (ret < 0) {\n                 return ret;\n             }\n@@ -1030,7 +1057,7 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out,\n         }\n     }\n \n-    ret = blk_pwrite(exp->common.blk, offset, size, buf, 0);\n+    ret = blk_co_pwrite(exp->common.blk, offset, size, buf, 0);\n     if (ret < 0) {\n         return ret;\n     }\n@@ -1045,8 +1072,9 @@ static ssize_t fuse_write(FuseExport *exp, struct fuse_write_out *out,\n  * Let clients perform various fallocate() operations.\n  * Return 0 on success (no 'out' object), and -errno on error.\n  */\n-static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n-                              uint32_t mode)\n+static ssize_t coroutine_fn\n+fuse_co_fallocate(FuseExport *exp,\n+                  uint64_t offset, uint64_t length, uint32_t mode)\n {\n     int64_t blk_len;\n     int ret;\n@@ -1055,7 +1083,7 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n         return -EACCES;\n     }\n \n-    blk_len = blk_getlength(exp->common.blk);\n+    blk_len = blk_co_getlength(exp->common.blk);\n     if (blk_len < 0) {\n         return blk_len;\n     }\n@@ -1074,14 +1102,14 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n \n         if (offset > blk_len) {\n             /* No preallocation needed here */\n-            ret = fuse_do_truncate(exp, offset, true, PREALLOC_MODE_OFF);\n+            ret = fuse_co_do_truncate(exp, offset, true, PREALLOC_MODE_OFF);\n             if (ret < 0) {\n                 return ret;\n             }\n         }\n \n-        ret = fuse_do_truncate(exp, offset + length, true,\n-                               PREALLOC_MODE_FALLOC);\n+        ret = fuse_co_do_truncate(exp, offset + length, true,\n+                                  PREALLOC_MODE_FALLOC);\n     }\n #ifdef CONFIG_FALLOCATE_PUNCH_HOLE\n     else if (mode & FALLOC_FL_PUNCH_HOLE) {\n@@ -1092,8 +1120,9 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n         do {\n             int size = MIN(length, BDRV_REQUEST_MAX_BYTES);\n \n-            ret = blk_pwrite_zeroes(exp->common.blk, offset, size,\n-                                    BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK);\n+            ret = blk_co_pwrite_zeroes(exp->common.blk, offset, size,\n+                                       BDRV_REQ_MAY_UNMAP |\n+                                       BDRV_REQ_NO_FALLBACK);\n             if (ret == -ENOTSUP) {\n                 /*\n                  * fallocate() specifies to return EOPNOTSUPP for unsupported\n@@ -1111,8 +1140,8 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n     else if (mode & FALLOC_FL_ZERO_RANGE) {\n         if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + length > blk_len) {\n             /* No need for zeroes, we are going to write them ourselves */\n-            ret = fuse_do_truncate(exp, offset + length, false,\n-                                   PREALLOC_MODE_OFF);\n+            ret = fuse_co_do_truncate(exp, offset + length, false,\n+                                      PREALLOC_MODE_OFF);\n             if (ret < 0) {\n                 return ret;\n             }\n@@ -1121,8 +1150,8 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n         do {\n             int size = MIN(length, BDRV_REQUEST_MAX_BYTES);\n \n-            ret = blk_pwrite_zeroes(exp->common.blk,\n-                                    offset, size, 0);\n+            ret = blk_co_pwrite_zeroes(exp->common.blk,\n+                                       offset, size, 0);\n             offset += size;\n             length -= size;\n         } while (ret == 0 && length > 0);\n@@ -1139,9 +1168,9 @@ static ssize_t fuse_fallocate(FuseExport *exp, uint64_t offset, uint64_t length,\n  * Let clients fsync the exported image.\n  * Return 0 on success (no 'out' object), and -errno on error.\n  */\n-static ssize_t fuse_fsync(FuseExport *exp)\n+static ssize_t coroutine_fn fuse_co_fsync(FuseExport *exp)\n {\n-    return blk_flush(exp->common.blk);\n+    return blk_co_flush(exp->common.blk);\n }\n \n /**\n@@ -1149,9 +1178,9 @@ static ssize_t fuse_fsync(FuseExport *exp)\n  * notes this to be a way to return last-minute errors.)\n  * Return 0 on success (no 'out' object), and -errno on error.\n  */\n-static ssize_t fuse_flush(FuseExport *exp)\n+static ssize_t coroutine_fn fuse_co_flush(FuseExport *exp)\n {\n-    return blk_flush(exp->common.blk);\n+    return blk_co_flush(exp->common.blk);\n }\n \n #ifdef CONFIG_FUSE_LSEEK\n@@ -1159,8 +1188,9 @@ static ssize_t fuse_flush(FuseExport *exp)\n  * Let clients inquire allocation status.\n  * Return the number of bytes written to *out on success, and -errno on error.\n  */\n-static ssize_t fuse_lseek(FuseExport *exp, struct fuse_lseek_out *out,\n-                          uint64_t offset, uint32_t whence)\n+static ssize_t coroutine_fn\n+fuse_co_lseek(FuseExport *exp, struct fuse_lseek_out *out,\n+              uint64_t offset, uint32_t whence)\n {\n     if (whence != SEEK_HOLE && whence != SEEK_DATA) {\n         return -EINVAL;\n@@ -1170,8 +1200,8 @@ static ssize_t fuse_lseek(FuseExport *exp, struct fuse_lseek_out *out,\n         int64_t pnum;\n         int ret;\n \n-        ret = bdrv_block_status_above(blk_bs(exp->common.blk), NULL,\n-                                      offset, INT64_MAX, &pnum, NULL, NULL);\n+        ret = bdrv_co_block_status_above(blk_bs(exp->common.blk), NULL,\n+                                         offset, INT64_MAX, &pnum, NULL, NULL);\n         if (ret < 0) {\n             return ret;\n         }\n@@ -1188,7 +1218,7 @@ static ssize_t fuse_lseek(FuseExport *exp, struct fuse_lseek_out *out,\n              * and @blk_len (the client-visible EOF).\n              */\n \n-            blk_len = blk_getlength(exp->common.blk);\n+            blk_len = blk_co_getlength(exp->common.blk);\n             if (blk_len < 0) {\n                 return blk_len;\n             }\n@@ -1332,9 +1362,9 @@ static int fuse_write_buf_response(int fd,\n /**\n  * Process a FUSE request, incl. writing the response.\n  */\n-static void fuse_process_request(FuseExport *exp,\n-                                 const FuseRequestInHeader *in_hdr,\n-                                 const void *data_buffer)\n+static void coroutine_fn\n+fuse_co_process_request(FuseExport *exp, const FuseRequestInHeader *in_hdr,\n+                        const void *data_buffer)\n {\n     FuseRequestOutHeader out_hdr;\n     /* For read requests: Data to be returned */\n@@ -1343,7 +1373,7 @@ static void fuse_process_request(FuseExport *exp,\n \n     switch (in_hdr->common.opcode) {\n     case FUSE_INIT:\n-        ret = fuse_init(exp, &out_hdr.init, &in_hdr->init);\n+        ret = fuse_co_init(exp, &out_hdr.init, &in_hdr->init);\n         break;\n \n     case FUSE_DESTROY:\n@@ -1351,11 +1381,11 @@ static void fuse_process_request(FuseExport *exp,\n         break;\n \n     case FUSE_STATFS:\n-        ret = fuse_statfs(exp, &out_hdr.statfs);\n+        ret = fuse_co_statfs(exp, &out_hdr.statfs);\n         break;\n \n     case FUSE_OPEN:\n-        ret = fuse_open(exp, &out_hdr.open);\n+        ret = fuse_co_open(exp, &out_hdr.open);\n         break;\n \n     case FUSE_RELEASE:\n@@ -1372,19 +1402,19 @@ static void fuse_process_request(FuseExport *exp,\n         return;\n \n     case FUSE_GETATTR:\n-        ret = fuse_getattr(exp, &out_hdr.attr);\n+        ret = fuse_co_getattr(exp, &out_hdr.attr);\n         break;\n \n     case FUSE_SETATTR: {\n         const struct fuse_setattr_in *in = &in_hdr->setattr;\n-        ret = fuse_setattr(exp, &out_hdr.attr,\n-                           in->valid, in->size, in->mode, in->uid, in->gid);\n+        ret = fuse_co_setattr(exp, &out_hdr.attr,\n+                              in->valid, in->size, in->mode, in->uid, in->gid);\n         break;\n     }\n \n     case FUSE_READ: {\n         const struct fuse_read_in *in = &in_hdr->read;\n-        ret = fuse_read(exp, &out_data_buffer, in->offset, in->size);\n+        ret = fuse_co_read(exp, &out_data_buffer, in->offset, in->size);\n         break;\n     }\n \n@@ -1402,36 +1432,36 @@ static void fuse_process_request(FuseExport *exp,\n         }\n \n         /*\n-         * read_from_fuse_fd() has checked that in_hdr->len matches the number\n-         * of bytes read, which cannot exceed the max_write value we set\n+         * co_read_from_fuse_fd() has checked that in_hdr->len matches the\n+         * number of bytes read, which cannot exceed the max_write value we set\n          * (FUSE_MAX_WRITE_BYTES).  So we know that FUSE_MAX_WRITE_BYTES >=\n          * in_hdr->len >= in->size + X, so this assertion must hold.\n          */\n         assert(in->size <= FUSE_MAX_WRITE_BYTES);\n \n-        ret = fuse_write(exp, &out_hdr.write,\n-                         in->offset, in->size, data_buffer);\n+        ret = fuse_co_write(exp, &out_hdr.write,\n+                            in->offset, in->size, data_buffer);\n         break;\n     }\n \n     case FUSE_FALLOCATE: {\n         const struct fuse_fallocate_in *in = &in_hdr->fallocate;\n-        ret = fuse_fallocate(exp, in->offset, in->length, in->mode);\n+        ret = fuse_co_fallocate(exp, in->offset, in->length, in->mode);\n         break;\n     }\n \n     case FUSE_FSYNC:\n-        ret = fuse_fsync(exp);\n+        ret = fuse_co_fsync(exp);\n         break;\n \n     case FUSE_FLUSH:\n-        ret = fuse_flush(exp);\n+        ret = fuse_co_flush(exp);\n         break;\n \n #ifdef CONFIG_FUSE_LSEEK\n     case FUSE_LSEEK: {\n         const struct fuse_lseek_in *in = &in_hdr->lseek;\n-        ret = fuse_lseek(exp, &out_hdr.lseek, in->offset, in->whence);\n+        ret = fuse_co_lseek(exp, &out_hdr.lseek, in->offset, in->whence);\n         break;\n     }\n #endif\n",
    "prefixes": [
        "v4",
        "18/24"
    ]
}