get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1954404,
    "url": "http://patchwork.ozlabs.org/api/patches/1954404/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1719776434-435013-3-git-send-email-steven.sistare@oracle.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": "<1719776434-435013-3-git-send-email-steven.sistare@oracle.com>",
    "list_archive_url": null,
    "date": "2024-06-30T19:40:25",
    "name": "[V2,02/11] migration: cpr-state",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d8c520256e4ae4e0c9c93aad6fb16a9ea6f0fa02",
    "submitter": {
        "id": 71906,
        "url": "http://patchwork.ozlabs.org/api/people/71906/?format=api",
        "name": "Steve Sistare",
        "email": "steven.sistare@oracle.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1719776434-435013-3-git-send-email-steven.sistare@oracle.com/mbox/",
    "series": [
        {
            "id": 413181,
            "url": "http://patchwork.ozlabs.org/api/series/413181/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=413181",
            "date": "2024-06-30T19:40:26",
            "name": "Live update: cpr-exec",
            "version": 2,
            "mbox": "http://patchwork.ozlabs.org/series/413181/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/1954404/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/1954404/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=oracle.com header.i=@oracle.com header.a=rsa-sha256\n header.s=corp-2023-11-20 header.b=JMYo2HVd;\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 4WC01h2yF6z1xpN\n\tfor <incoming@patchwork.ozlabs.org>; Mon,  1 Jul 2024 05:42:16 +1000 (AEST)",
            "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 1sO0Q1-000072-5B; Sun, 30 Jun 2024 15:41:03 -0400",
            "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 <steven.sistare@oracle.com>)\n id 1sO0Pu-0008SB-E9\n for qemu-devel@nongnu.org; Sun, 30 Jun 2024 15:40:54 -0400",
            "from mx0a-00069f02.pphosted.com ([205.220.165.32])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <steven.sistare@oracle.com>)\n id 1sO0Pn-0004O2-Jv\n for qemu-devel@nongnu.org; Sun, 30 Jun 2024 15:40:51 -0400",
            "from pps.filterd (m0246627.ppops.net [127.0.0.1])\n by mx0b-00069f02.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id\n 45UJW3BS026542;\n Sun, 30 Jun 2024 19:40:41 GMT",
            "from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com\n (iadpaimrmta02.appoci.oracle.com [147.154.18.20])\n by mx0b-00069f02.pphosted.com (PPS) with ESMTPS id 4028v0hgjs-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);\n Sun, 30 Jun 2024 19:40:40 +0000 (GMT)",
            "from pps.filterd\n (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1])\n by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (8.17.1.19/8.17.1.19)\n with ESMTP id 45UHtoa4019083; Sun, 30 Jun 2024 19:40:39 GMT",
            "from pps.reinject (localhost [127.0.0.1])\n by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with ESMTPS id\n 4028qc16d2-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);\n Sun, 30 Jun 2024 19:40:39 +0000",
            "from iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com\n (iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com [127.0.0.1])\n by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 45UJeaSS014044;\n Sun, 30 Jun 2024 19:40:38 GMT",
            "from ca-dev63.us.oracle.com (ca-dev63.us.oracle.com [10.211.8.221])\n by iadpaimrmta02.imrmtpd1.prodappiadaev1.oraclevcn.com (PPS) with\n ESMTP id 4028qc16cc-3; Sun, 30 Jun 2024 19:40:38 +0000"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=\n from:to:cc:subject:date:message-id:in-reply-to:references; s=\n corp-2023-11-20; bh=7+QL5ZrrpPDnlyBxW0st4Wn/YKyjCdy8c6YwBxJSlJI=; b=\n JMYo2HVd42mWYrnCWpGbMD657/sjXoB8OAlMJmyB+Kh0EczHvef2CpXnFzVqCyse\n Xg7y7CrmHGv4kLaqAKLxAsWJXAq3q+stU2+3fz91cscpGTQj9jTKu6E08Qy3HkQP\n Zuw+qyRZxn/gnEXY2c6Lp2XL6iHiNzpsRVrTuF7Fxk9ZsdysrAlf6EAExrJVH0nx\n yWgxJQYy8hipl7kBs0vQjs71bQZPyvuUNaYeNA4Ox5HNx4UV2q1Gpk4sMk3CDF6I\n KolCOLG18bnNhd+zjwk/KkSx8AY24S9LuMhzA5TmmVV270KQh7TkPhhk6oDxER7c\n mon2K3wE7nq0HnI3TDLaTg==",
        "From": "Steve Sistare <steven.sistare@oracle.com>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>,\n David Hildenbrand <david@redhat.com>,\n Marcel Apfelbaum <marcel.apfelbaum@gmail.com>,\n Eduardo Habkost <eduardo@habkost.net>,\n Philippe Mathieu-Daude <philmd@linaro.org>,\n Paolo Bonzini <pbonzini@redhat.com>,\n \"Daniel P. Berrange\" <berrange@redhat.com>,\n Markus Armbruster <armbru@redhat.com>,\n Steve Sistare <steven.sistare@oracle.com>",
        "Subject": "[PATCH V2 02/11] migration: cpr-state",
        "Date": "Sun, 30 Jun 2024 12:40:25 -0700",
        "Message-Id": "<1719776434-435013-3-git-send-email-steven.sistare@oracle.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1719776434-435013-1-git-send-email-steven.sistare@oracle.com>",
        "References": "<1719776434-435013-1-git-send-email-steven.sistare@oracle.com>",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16\n definitions=2024-06-30_16,2024-06-28_01,2024-05-17_01",
        "X-Proofpoint-Spam-Details": "rule=notspam policy=default score=0 suspectscore=0\n malwarescore=0\n adultscore=0 bulkscore=0 mlxlogscore=999 phishscore=0 spamscore=0\n mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1\n engine=8.12.0-2406180000 definitions=main-2406300157",
        "X-Proofpoint-ORIG-GUID": "zfmTs7vXi1T1LP0RHQR8hE53gHD2ecPu",
        "X-Proofpoint-GUID": "zfmTs7vXi1T1LP0RHQR8hE53gHD2ecPu",
        "Received-SPF": "pass client-ip=205.220.165.32;\n envelope-from=steven.sistare@oracle.com; helo=mx0a-00069f02.pphosted.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_MED=-0.001,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, 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": "CPR must save state that is needed after QEMU is restarted, when devices\nare realized.  Thus the extra state cannot be saved in the migration stream,\nas objects must already exist before that stream can be loaded.  Instead,\ndefine auxilliary state structures and vmstate descriptions, not associated\nwith any registered object, and serialize the aux state to a cpr-specific\nstream in cpr_state_save.  Deserialize in cpr_state_load after QEMU\nrestarts, before devices are realized.\n\nProvide accessors for clients to register file descriptors for saving.\nThe mechanism for passing the fd's to the new process will be specific\nto each migration mode, and added in subsequent patches.\n\nSigned-off-by: Steve Sistare <steven.sistare@oracle.com>\n---\n include/migration/cpr.h |  21 ++++++\n migration/cpr.c         | 188 ++++++++++++++++++++++++++++++++++++++++++++++++\n migration/meson.build   |   1 +\n migration/migration.c   |   6 ++\n migration/trace-events  |   5 ++\n system/vl.c             |   3 +\n 6 files changed, 224 insertions(+)\n create mode 100644 include/migration/cpr.h\n create mode 100644 migration/cpr.c",
    "diff": "diff --git a/include/migration/cpr.h b/include/migration/cpr.h\nnew file mode 100644\nindex 0000000..8e7e705\n--- /dev/null\n+++ b/include/migration/cpr.h\n@@ -0,0 +1,21 @@\n+/*\n+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates.\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#ifndef MIGRATION_CPR_H\n+#define MIGRATION_CPR_H\n+\n+typedef int (*cpr_walk_fd_cb)(int fd);\n+void cpr_save_fd(const char *name, int id, int fd);\n+void cpr_delete_fd(const char *name, int id);\n+int cpr_find_fd(const char *name, int id);\n+int cpr_walk_fd(cpr_walk_fd_cb cb);\n+void cpr_resave_fd(const char *name, int id, int fd);\n+\n+int cpr_state_save(Error **errp);\n+int cpr_state_load(Error **errp);\n+\n+#endif\ndiff --git a/migration/cpr.c b/migration/cpr.c\nnew file mode 100644\nindex 0000000..313e74e\n--- /dev/null\n+++ b/migration/cpr.c\n@@ -0,0 +1,188 @@\n+/*\n+ * Copyright (c) 2021-2024 Oracle and/or its affiliates.\n+ *\n+ * This work is licensed under the terms of the GNU GPL, version 2 or later.\n+ * See the COPYING file in the top-level directory.\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"migration/cpr.h\"\n+#include \"migration/misc.h\"\n+#include \"migration/qemu-file.h\"\n+#include \"migration/savevm.h\"\n+#include \"migration/vmstate.h\"\n+#include \"sysemu/runstate.h\"\n+#include \"trace.h\"\n+\n+/*************************************************************************/\n+/* cpr state container for all information to be saved. */\n+\n+typedef QLIST_HEAD(CprFdList, CprFd) CprFdList;\n+\n+typedef struct CprState {\n+    CprFdList fds;\n+} CprState;\n+\n+static CprState cpr_state;\n+\n+/****************************************************************************/\n+\n+typedef struct CprFd {\n+    char *name;\n+    unsigned int namelen;\n+    int id;\n+    int fd;\n+    QLIST_ENTRY(CprFd) next;\n+} CprFd;\n+\n+static const VMStateDescription vmstate_cpr_fd = {\n+    .name = \"cpr fd\",\n+    .version_id = 1,\n+    .minimum_version_id = 1,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_UINT32(namelen, CprFd),\n+        VMSTATE_VBUFFER_ALLOC_UINT32(name, CprFd, 0, NULL, namelen),\n+        VMSTATE_INT32(id, CprFd),\n+        VMSTATE_INT32(fd, CprFd),\n+        VMSTATE_END_OF_LIST()\n+    }\n+};\n+\n+void cpr_save_fd(const char *name, int id, int fd)\n+{\n+    CprFd *elem = g_new0(CprFd, 1);\n+\n+    trace_cpr_save_fd(name, id, fd);\n+    elem->name = g_strdup(name);\n+    elem->namelen = strlen(name) + 1;\n+    elem->id = id;\n+    elem->fd = fd;\n+    QLIST_INSERT_HEAD(&cpr_state.fds, elem, next);\n+}\n+\n+static CprFd *find_fd(CprFdList *head, const char *name, int id)\n+{\n+    CprFd *elem;\n+\n+    QLIST_FOREACH(elem, head, next) {\n+        if (!strcmp(elem->name, name) && elem->id == id) {\n+            return elem;\n+        }\n+    }\n+    return NULL;\n+}\n+\n+void cpr_delete_fd(const char *name, int id)\n+{\n+    CprFd *elem = find_fd(&cpr_state.fds, name, id);\n+\n+    if (elem) {\n+        QLIST_REMOVE(elem, next);\n+        g_free(elem->name);\n+        g_free(elem);\n+    }\n+\n+    trace_cpr_delete_fd(name, id);\n+}\n+\n+int cpr_find_fd(const char *name, int id)\n+{\n+    CprFd *elem = find_fd(&cpr_state.fds, name, id);\n+    int fd = elem ? elem->fd : -1;\n+\n+    trace_cpr_find_fd(name, id, fd);\n+    return fd;\n+}\n+\n+int cpr_walk_fd(cpr_walk_fd_cb cb)\n+{\n+    CprFd *elem;\n+\n+    QLIST_FOREACH(elem, &cpr_state.fds, next) {\n+        if (elem->fd >= 0 && cb(elem->fd)) {\n+            return 1;\n+        }\n+    }\n+    return 0;\n+}\n+\n+void cpr_resave_fd(const char *name, int id, int fd)\n+{\n+    CprFd *elem = find_fd(&cpr_state.fds, name, id);\n+    int old_fd = elem ? elem->fd : -1;\n+\n+    if (old_fd < 0) {\n+        cpr_save_fd(name, id, fd);\n+    } else if (old_fd != fd) {\n+        error_setg(&error_fatal,\n+                   \"internal error: cpr fd '%s' id %d value %d \"\n+                   \"already saved with a different value %d\",\n+                   name, id, fd, old_fd);\n+    }\n+}\n+/*************************************************************************/\n+#define CPR_STATE \"CprState\"\n+\n+static const VMStateDescription vmstate_cpr_state = {\n+    .name = CPR_STATE,\n+    .version_id = 1,\n+    .minimum_version_id = 1,\n+    .fields = (VMStateField[]) {\n+        VMSTATE_QLIST_V(fds, CprState, 1, vmstate_cpr_fd, CprFd, next),\n+        VMSTATE_END_OF_LIST()\n+    }\n+};\n+/*************************************************************************/\n+\n+int cpr_state_save(Error **errp)\n+{\n+    int ret;\n+    QEMUFile *f;\n+\n+    /* set f based on mode in a later patch in this series */\n+    return 0;\n+\n+    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);\n+    qemu_put_be32(f, QEMU_VM_FILE_VERSION);\n+\n+    ret = vmstate_save_state(f, &vmstate_cpr_state, &cpr_state, 0);\n+    if (ret) {\n+        error_setg(errp, \"vmstate_save_state error %d\", ret);\n+    }\n+\n+    qemu_fclose(f);\n+    return ret;\n+}\n+\n+int cpr_state_load(Error **errp)\n+{\n+    int ret;\n+    uint32_t v;\n+    QEMUFile *f;\n+\n+    /* set f based on mode in a later patch in this series */\n+    return 0;\n+\n+    v = qemu_get_be32(f);\n+    if (v != QEMU_VM_FILE_MAGIC) {\n+        error_setg(errp, \"Not a migration stream (bad magic %x)\", v);\n+        qemu_fclose(f);\n+        return -EINVAL;\n+    }\n+    v = qemu_get_be32(f);\n+    if (v != QEMU_VM_FILE_VERSION) {\n+        error_setg(errp, \"Unsupported migration stream version %d\", v);\n+        qemu_fclose(f);\n+        return -ENOTSUP;\n+    }\n+\n+    ret = vmstate_load_state(f, &vmstate_cpr_state, &cpr_state, 1);\n+    if (ret) {\n+        error_setg(errp, \"vmstate_load_state error %d\", ret);\n+    }\n+\n+    qemu_fclose(f);\n+    return ret;\n+}\n+\ndiff --git a/migration/meson.build b/migration/meson.build\nindex 5ce2acb4..87feb4c 100644\n--- a/migration/meson.build\n+++ b/migration/meson.build\n@@ -13,6 +13,7 @@ system_ss.add(files(\n   'block-dirty-bitmap.c',\n   'channel.c',\n   'channel-block.c',\n+  'cpr.c',\n   'dirtyrate.c',\n   'exec.c',\n   'fd.c',\ndiff --git a/migration/migration.c b/migration/migration.c\nindex 3dea06d..e394ad7 100644\n--- a/migration/migration.c\n+++ b/migration/migration.c\n@@ -27,6 +27,7 @@\n #include \"sysemu/cpu-throttle.h\"\n #include \"rdma.h\"\n #include \"ram.h\"\n+#include \"migration/cpr.h\"\n #include \"migration/global_state.h\"\n #include \"migration/misc.h\"\n #include \"migration.h\"\n@@ -2118,6 +2119,10 @@ void qmp_migrate(const char *uri, bool has_channels,\n         }\n     }\n \n+    if (cpr_state_save(&local_err)) {\n+        goto out;\n+    }\n+\n     if (addr->transport == MIGRATION_ADDRESS_TYPE_SOCKET) {\n         SocketAddress *saddr = &addr->u.socket;\n         if (saddr->type == SOCKET_ADDRESS_TYPE_INET ||\n@@ -2142,6 +2147,7 @@ void qmp_migrate(const char *uri, bool has_channels,\n                           MIGRATION_STATUS_FAILED);\n     }\n \n+out:\n     if (local_err) {\n         if (!resume_requested) {\n             yank_unregister_instance(MIGRATION_YANK_INSTANCE);\ndiff --git a/migration/trace-events b/migration/trace-events\nindex 0b7c332..173f2c0 100644\n--- a/migration/trace-events\n+++ b/migration/trace-events\n@@ -340,6 +340,11 @@ colo_receive_message(const char *msg) \"Receive '%s' message\"\n # colo-failover.c\n colo_failover_set_state(const char *new_state) \"new state %s\"\n \n+# cpr.c\n+cpr_save_fd(const char *name, int id, int fd) \"%s, id %d, fd %d\"\n+cpr_delete_fd(const char *name, int id) \"%s, id %d\"\n+cpr_find_fd(const char *name, int id, int fd) \"%s, id %d returns %d\"\n+\n # block-dirty-bitmap.c\n send_bitmap_header_enter(void) \"\"\n send_bitmap_bits(uint32_t flags, uint64_t start_sector, uint32_t nr_sectors, uint64_t data_size) \"flags: 0x%x, start_sector: %\" PRIu64 \", nr_sectors: %\" PRIu32 \", data_size: %\" PRIu64\ndiff --git a/system/vl.c b/system/vl.c\nindex 03951be..6521ee3 100644\n--- a/system/vl.c\n+++ b/system/vl.c\n@@ -77,6 +77,7 @@\n #include \"hw/block/block.h\"\n #include \"hw/i386/x86.h\"\n #include \"hw/i386/pc.h\"\n+#include \"migration/cpr.h\"\n #include \"migration/misc.h\"\n #include \"migration/snapshot.h\"\n #include \"sysemu/tpm.h\"\n@@ -3713,6 +3714,8 @@ void qemu_init(int argc, char **argv)\n \n     qemu_create_machine(machine_opts_dict);\n \n+    cpr_state_load(&error_fatal);\n+\n     suspend_mux_open();\n \n     qemu_disable_default_devices();\n",
    "prefixes": [
        "V2",
        "02/11"
    ]
}