get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2174155,
    "url": "http://patchwork.ozlabs.org/api/patches/2174155/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20251215075902.2428-1-wafer@jaguarmicro.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": "<20251215075902.2428-1-wafer@jaguarmicro.com>",
    "list_archive_url": null,
    "date": "2025-12-15T07:59:02",
    "name": "[v2,4/4] vhost: SVQ add the indirect descriptors to available ring",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "41148a16d665db3e40f50607b93bd3af5a5432b7",
    "submitter": {
        "id": 87629,
        "url": "http://patchwork.ozlabs.org/api/people/87629/?format=api",
        "name": "Wafer",
        "email": "wafer@jaguarmicro.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20251215075902.2428-1-wafer@jaguarmicro.com/mbox/",
    "series": [
        {
            "id": 485358,
            "url": "http://patchwork.ozlabs.org/api/series/485358/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=485358",
            "date": "2025-12-15T07:57:13",
            "name": "[v2,1/4] vhost: add data structure of virtio indirect descriptors in SVQ",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/485358/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2174155/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2174155/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=jaguarmicro.com header.i=@jaguarmicro.com\n header.a=rsa-sha256 header.s=selector2 header.b=KylFaGyf;\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)",
            "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=jaguarmicro.com;"
        ],
        "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 4dVCBs0NXQz1xyL\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 15 Dec 2025 18:59:32 +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 1vV3UI-0008GK-QX; Mon, 15 Dec 2025 02:59:22 -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 <wafer@jaguarmicro.com>)\n id 1vV3UH-0008Fq-6t\n for qemu-devel@nongnu.org; Mon, 15 Dec 2025 02:59:21 -0500",
            "from mail-japanwestazlp170120003.outbound.protection.outlook.com\n ([2a01:111:f403:c406::3] helo=OS8PR02CU002.outbound.protection.outlook.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <wafer@jaguarmicro.com>)\n id 1vV3UF-0004Hr-1x\n for qemu-devel@nongnu.org; Mon, 15 Dec 2025 02:59:20 -0500",
            "from PUZPR06MB4713.apcprd06.prod.outlook.com (2603:1096:301:b4::10)\n by OSNPR06MB8228.apcprd06.prod.outlook.com (2603:1096:604:45e::6)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9412.13; Mon, 15 Dec\n 2025 07:59:13 +0000",
            "from PUZPR06MB4713.apcprd06.prod.outlook.com\n ([fe80::1b36:28b0:4e5:de66]) by PUZPR06MB4713.apcprd06.prod.outlook.com\n ([fe80::1b36:28b0:4e5:de66%6]) with mapi id 15.20.9412.011; Mon, 15 Dec 2025\n 07:59:13 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=MY99IYz6fMZvoO4BuBBO+5U/NN4KGGBDpHPRiY3UmAQ4LDcS93WDX9aDr9dGvMyGR68mViAurXz/d8VKFvdDwD+tB/USghRFI75xcJfUbFQcLznD9UtFPDR58Km9Fr2meOsZMNaiN3rJbFdj45P+zIlISXLvsXwBftBXxEJ9g+kREKRQdbimeIEhObRka/WxQoYfywJLg7iRwg9zQHLvPCh4LZpQGvH/4ceV/ewwzAjiu0XSOtcUr+DqNQUUDNap2iZ1dmdCPNAZIFFL+CLE8b3bulzatk0gbmb5LRlZlf0ZnN1UPtCuptnVmQS7UlsfHM1MApmJ7tDziVBhCrAYtQ==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=K8twKTd3sJEqpcDsBLwJRuzOM52cnv/phGQt4VjSEow=;\n b=RnIHuoNmgqyXkTlvMMyPAKa0uhhvs2ygNR0M2as4pkAPB9jqKKQVK/lN6GoJhjlerXHLESTeUnvhoIokP2viFU98zzBQP9qFTJuyA1/yJnF7qYktmBE7a/Xhrx+0DhohrArybmL5D+D3Z3cOP+72aaB5Vk7iVGLseMhQbdybO/vkh0zLhEZt5v8JabnkEp+Td7Ozyj5bC1Ein55avct2ddAN3HCMh9RGWr94Jsy9FytkdVLxggzMEE5CMZyJzqgaaLzyvxHe2fwhkdNQavPWx7j0KRHrDdLPNpzX9JoXvno3zZOW6C+h64T2DtXoLy2bUB/yRkVd2ShbiWB/mvAQvQ==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=jaguarmicro.com; dmarc=pass action=none\n header.from=jaguarmicro.com; dkim=pass header.d=jaguarmicro.com; arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=jaguarmicro.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=K8twKTd3sJEqpcDsBLwJRuzOM52cnv/phGQt4VjSEow=;\n b=KylFaGyfqe9Z5QRjConEknpVjencqnh0xNRwVxt9loj7qn/QBT+6wLxOsEz/zxRVRety/w8YTDb6dJQRQDSTt0YGOzZrOd5ddFM2q1U8x3+v9+Pr558ct2CTSTre8UgB7jYze3FyR0EAgGlSoYPEE8VCGmQv2GL+pgYmiMGGWpG6+69F6BatgD2kdGl0TOLNjiHSHjIOXnoy9Vy5ZEIE93NsGIxmGP4hw7vMBzYGIEJcJx7DfatvrW+JWf2gcnJFSI5UJ2NbW+jf6S48bYN+XeVRuNU7MXYteuGDjGGrlYvJwfKZdJZM7AKjFWRjqbX5uItxcwA/8sJnxWOGPxM6uw==",
        "From": "Wafer Xie <wafer@jaguarmicro.com>",
        "To": "mst@redhat.com, eperezma@redhat.com, jasowang@redhat.com,\n qemu-devel@nongnu.org",
        "Cc": "leiyang@redhat.com, sgarzare@redhat.com, angus.chen@jaguarmicro.com,\n wafer@jaguarmicro.com",
        "Subject": "[PATCH v2 4/4] vhost: SVQ add the indirect descriptors to available\n ring",
        "Date": "Mon, 15 Dec 2025 15:59:02 +0800",
        "Message-Id": "<20251215075902.2428-1-wafer@jaguarmicro.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-ClientProxiedBy": "KU0P306CA0063.MYSP306.PROD.OUTLOOK.COM\n (2603:1096:d10:23::11) To PUZPR06MB4713.apcprd06.prod.outlook.com\n (2603:1096:301:b4::10)",
        "MIME-Version": "1.0",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-TrafficTypeDiagnostic": "PUZPR06MB4713:EE_|OSNPR06MB8228:EE_",
        "X-MS-Office365-Filtering-Correlation-Id": "5d48c659-627b-4254-17bf-08de3bafd60e",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-MS-Exchange-AntiSpam-Relay": "0",
        "X-Microsoft-Antispam": "BCL:0;\n ARA:13230040|1800799024|376014|52116014|366016|38350700014;",
        "X-Microsoft-Antispam-Message-Info": "=?utf-8?q?mPt4Vxtr1+s0X8FP8CFF1l4Rj6MqiVo?=\n\t=?utf-8?q?uSEs1sGZ7pVpHWHV+OMQr5vQWznOb3fa0RhBAfb7VHYqOBImVtb6xYrNQiV5N5Rth?=\n\t=?utf-8?q?vhKe7Mlorb+TDwzgEzhCm8mbCoImn2Zl+BT4QEqNnQXv1v2fcaV8AWWzjyZqXBLyz?=\n\t=?utf-8?q?u575pIOm1fInHTwriVSQ6rgdp5+WecTOCHMK5+mKztxA0MaI23VfnyWFbXqsXIXJy?=\n\t=?utf-8?q?aYNl8klK/iYyP7yvoLWsKy3MBosNDQsT20nwZoHjS07ikI+mopg6srukLxMpOaYEa?=\n\t=?utf-8?q?mUlL6gKZFpbbgnUcxoXccG/spHwnnUueH6DO7KPlglfVHyiu9yp06CSgg+VN7kA8Y?=\n\t=?utf-8?q?SXmU8toyOXCJElJAFjqs/B10aWJdAs0jPML/QlhBB2hMDqIJvYr5HoEPPestSS7dI?=\n\t=?utf-8?q?WEkeIMFVADNgTsyrw8nv+pYSdu06+Z+gDq+e0Ot7iCzpHB/mDONMKMGvPwnaA7KmJ?=\n\t=?utf-8?q?75VYVBNFbyTbEQQ/ACYsc8f2T8c1lteSOCCov26W9Nwz7BR8uwk855KIUs6sZkrHy?=\n\t=?utf-8?q?1i3qhC0kQwV4pZf2460qvYLh1lCoi2f2xC4uwKWNlLBlFSEEt64GdThG8xByTEF7I?=\n\t=?utf-8?q?+GluFJ3x9YI2rgghEhYO85QMZH9vQk6Hx5in87XNxzir2iTr73+76uvQ1zOZXcAni?=\n\t=?utf-8?q?QvMHmhJ6klJxwABRjeiSZaKIWC7E6rLE/oLxZ7FQmh8ECINaUdWDVVMYuaRf0N3rQ?=\n\t=?utf-8?q?lXFyBmAb5Imn1HD03zFDfTlTIFk2aPOdKjmCeVdL/OGWcS2tNMOujkIxCX/ZoIJGm?=\n\t=?utf-8?q?vSZmZopEKth2wbNzizbPVJPEcTv6un6FSQoF10vbxzk7WFLvuUbv0fUlTVasOVc/z?=\n\t=?utf-8?q?kQIzXgLoNJ0TTY8rEbhsZsrSiwjnG70RRHueFQkzXlcyOyrKJ+bIBwYSw2diJ7VGL?=\n\t=?utf-8?q?069jZ23FecBANNhqw5ZE+4oa14kHcMdavNXtTM+bMslR7KJF/I185hLeWThsJzBrr?=\n\t=?utf-8?q?N2PUpH//EjTbghJyWsoGWNEtecIIN1Xt9OKBrJLVP/trJjOtN423ldb8oYt/qjtUD?=\n\t=?utf-8?q?NK88T2KRJfQyKCGEClI1Asb6lJSv05Ku/aKFWv/lEqzbeLLSkXnW+iT50q6D4kys5?=\n\t=?utf-8?q?Kj4iuJjeyQSedkZoD1EM1iFsArQTaEHlqsr5UMVPRFkGkRwrYAOAyWT5LM52CbjUG?=\n\t=?utf-8?q?aIp4hT4O2w8retTab+DRRJ0kVzkKcdjG3J8fWXkqTaZRwZXgj84Wjx0cmkt9iyeOq?=\n\t=?utf-8?q?QeA9+9Ss0ZWvSqyN1JA5wyimn68Q/HEFYklkfZBkBWlsX2qfQuur0rbMBDJW4IvPE?=\n\t=?utf-8?q?v9BkvN15dzn2OWHqeghkdnf0uzGzAZLK1iuk3ohN4AnwGSeRSyTTZTQpoOjtmLIVS?=\n\t=?utf-8?q?ElkWYmMydTxlPXvmM4xx86W0nmLBQJykiq0KbtbHTeZeFN6McQFuMnQqKWhQwK65a?=\n\t=?utf-8?q?1Zhf54RuX7Ve2QQQC9qqoj68OAHDrwpcF/5eEslj1kJZ/pDJPzmqm6RkyWGXaAqkV?=\n\t=?utf-8?q?Oz64QC/n77?=",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:PUZPR06MB4713.apcprd06.prod.outlook.com; PTR:; CAT:NONE;\n SFS:(13230040)(1800799024)(376014)(52116014)(366016)(38350700014); DIR:OUT;\n SFP:1102;",
        "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1",
        "X-MS-Exchange-AntiSpam-MessageData-0": "=?utf-8?q?cQMYJ4+uIXplaOihAN2OF+jvPGzK?=\n\t=?utf-8?q?WnnInzuA0/bcHaZVWqwp0D7T+/BtlEMyLILLg/No06Wuqg2zCc4qhtwv4sWGuYhAd?=\n\t=?utf-8?q?hu1mPBbirU9RmUktA4fjQJQZpoJQuY0fcjpw61N9XNs2kXE4+ZgqgUT/beB2m+Ufx?=\n\t=?utf-8?q?3GJlowhlKXfjFCO25h0GJaqrGtZe8ArUwhwXXFbV+GzkSBpPQkaUYHWjK4n2t1BnO?=\n\t=?utf-8?q?Ju3Od0JgjTYMHGh9tV6x+k0quBXB2h7TzAain4ikumGtYLfbpFClqAAa5kE6baJkV?=\n\t=?utf-8?q?5AsDfXSbozzRn3NrnLsIeSlXLOy+JVJEGjGBBGrt6w0Weu+0UaO2AleFBDvPNmU1s?=\n\t=?utf-8?q?ODWB3jrna8KiHxhZhhFxs7sqrqJ7SFpFjE2mqqi4xj5C/DaptClbXuAgoiUDJRYq0?=\n\t=?utf-8?q?p6XLvpJpK8O5n5HSIqd93Zvdt2t3o2UpUkYS8W6dFsLoKlEg4WxekyQUF1msMUtmn?=\n\t=?utf-8?q?ikahsYbE52oyYJ3XbMJ8mCSRfv+YLFpPWAnSsZhVfEidGWzZw760b7JXgaUF1sJcX?=\n\t=?utf-8?q?PZpPHEhzn0wsFXopBggKkODgRS3gFx3bkcS2XZEhp+sWdbkCnQZWETK3Gz1ERcZHZ?=\n\t=?utf-8?q?INc13s3+SNS4wNM6FJ1V5WpRis42uojZubv4rQFW6uS/x9UeW3tsJWw61YbCOiQNE?=\n\t=?utf-8?q?kKDVDtyfc5bHM2dRF6YGEWGZFaF6sSgZSK0cv3+fT5JuKWGbOCa7h2tbI+NzDy1m9?=\n\t=?utf-8?q?8Y+BkJQisJLVGWlTEwDaemEJtwwXIUElR+iIoe2DnZ9XxEzDCWHPEarqHWvQKl72u?=\n\t=?utf-8?q?3aFKhyYIaLX/WBk37FUcMxAZJFug0B1Iz9cHy4Y6l3mhAXZBGzBG/TyzEYkrbUITZ?=\n\t=?utf-8?q?YiW3+nl9arBPx3a6ZoDy+JhtDhXv/4zHEcb98N2r9/pA19Cu21pmZYoCXFGYqlCP5?=\n\t=?utf-8?q?Kbe9i6HFMHlyoo+8ey8rRwYC8gH4mN3aFHUBFsfGjsNHBfAaRAYihOmGaXAoWuUt3?=\n\t=?utf-8?q?qk08Q8boK7Iw8NdeENnpACQyvEAtWT6FJa76Vb7jeriuQkENf1KkBQ1oxkXCd3Wcj?=\n\t=?utf-8?q?Yeya4Q6etxcheo5P1B4UX+YUiTHxl3GegsAOZWgeFeuDcnXbNE1z0aIt2hNCYm4mb?=\n\t=?utf-8?q?nlKdpVrtXzpmh/uUbSl76hv0+Ba4WiVJq5ww3t86n+HxMacJcziY69jeidicQ1VGj?=\n\t=?utf-8?q?d8vJ9e18TPm8kts9jxVl2b7E+viOhFH4yntTmMY0uzPzQFHIuGT6TWnykLtfKV+OB?=\n\t=?utf-8?q?FWvkx8buG7NHARiLGsPdu+UC1Z+x9QbMOhc440TUsJn3Kzi5Gs+YjBTQsmBF8qFf2?=\n\t=?utf-8?q?82osc645PyBEClHzxOg8IvDamqU9uhw1/Ac/WsY/p4EzCWHeiyn/tNJbvJA70j2Hh?=\n\t=?utf-8?q?CBl2SrUNbInnF07Nxa7NlrUDsilNBvDYBY3OXC9qhbff8KjbafoBCErVig8Pg0Zn0?=\n\t=?utf-8?q?mUtk7NbtnhX4jHDyDmgF/OWyIFRdVHY3Sw3n2Y0xDMF2BtzVtuQrNQqvQYZN3dllO?=\n\t=?utf-8?q?rioxU7eKrATZ2JhVX1bWPpIq0BQaUiUwrExn69H82X1HyalL96cCKB/r2kKiwzeca?=\n\t=?utf-8?q?ufOPZP7pYWWq?=",
        "X-OriginatorOrg": "jaguarmicro.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 5d48c659-627b-4254-17bf-08de3bafd60e",
        "X-MS-Exchange-CrossTenant-AuthSource": "PUZPR06MB4713.apcprd06.prod.outlook.com",
        "X-MS-Exchange-CrossTenant-AuthAs": "Internal",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "15 Dec 2025 07:59:13.1281 (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "1e45a5c2-d3e1-46b3-a0e6-c5ebf6d8ba7b",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n IPdLkClzpRwjk4bjplxt+oyMY7rM1uUswvnuUgPt9uEX51uFY70wPAr6F4wxIir63ittnUKZloS1cRCAUtLNoA==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "OSNPR06MB8228",
        "Received-SPF": "pass client-ip=2a01:111:f403:c406::3;\n envelope-from=wafer@jaguarmicro.com;\n helo=OS8PR02CU002.outbound.protection.outlook.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, 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-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": "From: wafer Xie <wafer@jaguarmicro.com>\n\nRetrieve the target buffer from the indirect buffers by index,\nadd the elements sent by the guest into the buffer’s indirect descriptors,\nand update freed_head and freed_number. If freed_number is zero,\nor if the current buffer’s freed_number is less than the number of elements,\nupdate the buffer state to SVQ_INDIRECT_BUF_FREEING.\n\nSigned-off-by: wafer Xie <wafer@jaguarmicro.com>\n---\n hw/virtio/vhost-shadow-virtqueue.c | 245 ++++++++++++++++++++++++++---\n 1 file changed, 224 insertions(+), 21 deletions(-)",
    "diff": "diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c\nindex 9d43f13842..ef7a1db5ae 100644\n--- a/hw/virtio/vhost-shadow-virtqueue.c\n+++ b/hw/virtio/vhost-shadow-virtqueue.c\n@@ -189,36 +189,237 @@ static bool vhost_svq_vring_write_descs(VhostShadowVirtqueue *svq, hwaddr *sg,\n     return true;\n }\n \n-static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,\n+/**\n+ * Write descriptors to indirect descriptor table\n+ *\n+ * @svq: The shadow virtqueue\n+ * @sg: Cache for hwaddr\n+ * @iovec: The iovec from the guest\n+ * @num: iovec length\n+ * @addr: Descriptors' GPAs, if backed by guest memory\n+ * @buf: The indirect descriptor buffer\n+ * @offset_idx: Offset for write position and next field (0 for out, out_num for in)\n+ * @more_descs: True if more descriptors come in the chain\n+ * @write: True if they are writeable descriptors\n+ *\n+ * Return true if success, false otherwise and print error.\n+ */\n+static bool vhost_svq_vring_write_indirect_descs(VhostShadowVirtqueue *svq,\n+                                                  hwaddr *sg,\n+                                                  const struct iovec *iovec,\n+                                                  size_t num,\n+                                                  const hwaddr *addr,\n+                                                  SVQIndirectDescBuf *buf,\n+                                                  size_t offset_idx,\n+                                                  bool more_descs,\n+                                                  bool write)\n+{\n+    bool ok;\n+    uint16_t flags = write ? cpu_to_le16(VRING_DESC_F_WRITE) : 0;\n+    vring_desc_t *descs = buf->desc;\n+    uint16_t i = buf->freed_head + offset_idx;\n+\n+    if (num == 0) {\n+        return true;\n+    }\n+\n+    ok = vhost_svq_translate_addr(svq, sg, iovec, num, addr);\n+    if (unlikely(!ok)) {\n+        return false;\n+    }\n+\n+    for (size_t n = 0; n < num; n++) {\n+        descs[i].addr = cpu_to_le64(sg[n]);\n+        descs[i].len = cpu_to_le32(iovec[n].iov_len);\n+        if (more_descs || (n + 1 < num)) {\n+            descs[i].flags = flags | cpu_to_le16(VRING_DESC_F_NEXT);\n+            descs[i].next = cpu_to_le16(offset_idx + n + 1);\n+        } else {\n+            descs[i].flags = flags;\n+        }\n+        i++;\n+    }\n+\n+    return true;\n+}\n+\n+/**\n+ * Add descriptors to SVQ vring using indirect descriptors (dual-buffer)\n+ *\n+ * @svq: The shadow virtqueue\n+ * @out_sg: The out iovec from the guest\n+ * @out_num: The out iovec length\n+ * @out_addr: The out descriptors' GPAs\n+ * @in_sg: The in iovec from the guest\n+ * @in_num: The in iovec length\n+ * @in_addr: The in descriptors' GPAs\n+ * @sgs: Cache for hwaddr\n+ * @buf_idx: Index of the indirect buffer to use\n+ *\n+ * Return true if success, false otherwise and print error.\n+ */\n+static bool vhost_svq_add_split_indirect(VhostShadowVirtqueue *svq,\n+                                         const struct iovec *out_sg, size_t out_num,\n+                                         const hwaddr *out_addr,\n+                                         const struct iovec *in_sg, size_t in_num,\n+                                         const hwaddr *in_addr,\n+                                         hwaddr *sgs, int buf_idx)\n+{\n+    SVQIndirectDescBuf *buf = &svq->indirect_bufs[buf_idx];\n+    uint16_t start_idx = buf->freed_head;\n+    size_t total_descs = out_num + in_num;\n+    hwaddr indirect_iova;\n+    bool ok;\n+\n+    /* Populate indirect descriptor table for out descriptors */\n+    ok = vhost_svq_vring_write_indirect_descs(svq, sgs, out_sg, out_num,\n+                                               out_addr, buf, 0,\n+                                               in_num > 0, false);\n+    if (unlikely(!ok)) {\n+        return false;\n+    }\n+\n+    /* Populate indirect descriptor table for in descriptors */\n+    ok = vhost_svq_vring_write_indirect_descs(svq, sgs, in_sg, in_num,\n+                                               in_addr, buf, out_num,\n+                                               false, true);\n+    if (unlikely(!ok)) {\n+        return false;\n+    }\n+\n+    /* Calculate IOVA for this indirect descriptor range */\n+    indirect_iova = buf->iova + start_idx * sizeof(vring_desc_t);\n+\n+    /* Add a single descriptor pointing to the indirect table */\n+    svq->vring.desc[svq->free_head].addr = cpu_to_le64(indirect_iova);\n+    svq->vring.desc[svq->free_head].len = cpu_to_le32(total_descs * sizeof(vring_desc_t));\n+    svq->vring.desc[svq->free_head].flags = cpu_to_le16(VRING_DESC_F_INDIRECT);\n+\n+    /* Store indirect descriptor info in desc_state */\n+    svq->desc_state[svq->free_head].indirect_buf_idx = buf_idx;\n+\n+    /* Update buffer state */\n+    buf->freed_head = start_idx + total_descs;\n+    buf->freed_descs -= total_descs;\n+\n+    /* Move free_head forward */\n+    svq->free_head = svq->desc_next[svq->free_head];\n+\n+    return true;\n+}\n+\n+/**\n+ * Try to get a freed indirect buffer for use\n+ *\n+ * @svq: The shadow virtqueue\n+ * @total_descs: Number of descriptors needed\n+ *\n+ * Returns buffer index (0 to SVQ_NUM_INDIRECT_BUFS-1) if available, -1 if none available.\n+ */\n+static int vhost_svq_get_indirect_buf(VhostShadowVirtqueue *svq, size_t total_descs)\n+{\n+    int cur = svq->current_indirect_buf;\n+    SVQIndirectDescBuf *buf;\n+\n+    if (!svq->indirect_enabled) {\n+        return -1;\n+    }\n+\n+    /* Try current buffer first if it's in FREED state */\n+    if (cur >= 0) {\n+        buf = &svq->indirect_bufs[cur];\n+        if (buf->state == SVQ_INDIRECT_BUF_FREED) {\n+            /* Check if we have enough free descriptors */\n+            if (buf->freed_descs >= total_descs) {\n+                return cur;\n+            }\n+            /* Not enough space, switch to FREEING and try next buffer */\n+            buf->state = SVQ_INDIRECT_BUF_FREEING;\n+        }\n+    }\n+\n+    /* Try all other buffers */\n+    for (int i = 0; i < SVQ_NUM_INDIRECT_BUFS; i++) {\n+        if (i == cur) {\n+            continue;\n+        }\n+        buf = &svq->indirect_bufs[i];\n+        if (buf->state == SVQ_INDIRECT_BUF_FREED && buf->freed_descs >= total_descs) {\n+            svq->current_indirect_buf = i;\n+            return i;\n+        }\n+    }\n+\n+    /* All buffers unavailable, fallback to chain mode */\n+    return -1;\n+}\n+\n+static int vhost_svq_add_split(VhostShadowVirtqueue *svq,\n                                 const struct iovec *out_sg, size_t out_num,\n                                 const hwaddr *out_addr,\n                                 const struct iovec *in_sg, size_t in_num,\n-                                const hwaddr *in_addr, unsigned *head)\n+                                const hwaddr *in_addr, unsigned *head,\n+                                bool *used_indirect)\n {\n     unsigned avail_idx;\n     vring_avail_t *avail = svq->vring.avail;\n     bool ok;\n     g_autofree hwaddr *sgs = g_new(hwaddr, MAX(out_num, in_num));\n+    size_t total_descs = out_num + in_num;\n+    int indirect_buf_idx = -1;\n \n     *head = svq->free_head;\n+    *used_indirect = false;\n \n     /* We need some descriptors here */\n     if (unlikely(!out_num && !in_num)) {\n         qemu_log_mask(LOG_GUEST_ERROR,\n                       \"Guest provided element with no descriptors\");\n-        return false;\n+        return -EINVAL;\n     }\n \n-    ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, out_addr,\n-                                     in_num > 0, false);\n-    if (unlikely(!ok)) {\n-        return false;\n+    /* Try to use indirect descriptors if feature is negotiated and total > 1 */\n+    if (virtio_vdev_has_feature(svq->vdev, VIRTIO_RING_F_INDIRECT_DESC) &&\n+        total_descs >= 2) {\n+        indirect_buf_idx = vhost_svq_get_indirect_buf(svq, total_descs);\n     }\n \n-    ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, in_addr, false,\n-                                     true);\n-    if (unlikely(!ok)) {\n-        return false;\n+    if (indirect_buf_idx >= 0) {\n+        /* Indirect mode: only need 1 main descriptor slot */\n+        if (unlikely(vhost_svq_available_slots(svq) < 1)) {\n+            return -ENOSPC;\n+        }\n+\n+        /* Use indirect mode */\n+        ok = vhost_svq_add_split_indirect(svq, out_sg, out_num, out_addr,\n+                                          in_sg, in_num, in_addr,\n+                                          sgs, indirect_buf_idx);\n+        if (unlikely(!ok)) {\n+            error_report(\"indirect error, out_num %zu in_num %zu avail index %u head %u\\n\",\n+                            out_num, in_num, svq->shadow_avail_idx, *head);\n+            return -EINVAL;\n+        }\n+        *used_indirect = true;\n+    } else {\n+        /* Chain mode: need total_descs descriptor slots */\n+        if (unlikely(vhost_svq_available_slots(svq) < total_descs)) {\n+            return -ENOSPC;\n+        }\n+\n+        /* Use direct (chain) mode */\n+        svq->desc_state[svq->free_head].indirect_buf_idx = -1;\n+\n+        ok = vhost_svq_vring_write_descs(svq, sgs, out_sg, out_num, out_addr,\n+                                         in_num > 0, false);\n+        if (unlikely(!ok)) {\n+            return -EINVAL;\n+        }\n+\n+        ok = vhost_svq_vring_write_descs(svq, sgs, in_sg, in_num, in_addr, false,\n+                                         true);\n+        if (unlikely(!ok)) {\n+            return -EINVAL;\n+        }\n     }\n \n     /*\n@@ -233,7 +434,7 @@ static bool vhost_svq_add_split(VhostShadowVirtqueue *svq,\n     smp_wmb();\n     avail->idx = cpu_to_le16(svq->shadow_avail_idx);\n \n-    return true;\n+    return 0;\n }\n \n static void vhost_svq_kick(VhostShadowVirtqueue *svq)\n@@ -274,19 +475,21 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,\n {\n     unsigned qemu_head;\n     unsigned ndescs = in_num + out_num;\n-    bool ok;\n+    int r;\n+    bool used_indirect = false;\n \n-    if (unlikely(ndescs > vhost_svq_available_slots(svq))) {\n-        return -ENOSPC;\n+    r = vhost_svq_add_split(svq, out_sg, out_num, out_addr, in_sg, in_num,\n+                             in_addr, &qemu_head, &used_indirect);\n+    if (unlikely(r != 0)) {\n+        return r;\n     }\n \n-    ok = vhost_svq_add_split(svq, out_sg, out_num, out_addr, in_sg, in_num,\n-                             in_addr, &qemu_head);\n-    if (unlikely(!ok)) {\n-        return -EINVAL;\n+    /* If using indirect, only 1 main descriptor is used; otherwise ndescs */\n+    if (used_indirect) {\n+        svq->num_free -= 1;\n+    } else {\n+        svq->num_free -= ndescs;\n     }\n-\n-    svq->num_free -= ndescs;\n     svq->desc_state[qemu_head].elem = elem;\n     svq->desc_state[qemu_head].ndescs = ndescs;\n     vhost_svq_kick(svq);\n",
    "prefixes": [
        "v2",
        "4/4"
    ]
}