get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2230571,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2230571/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260429210830.594724-9-berrange@redhat.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.1/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": ""
    },
    "msgid": "<20260429210830.594724-9-berrange@redhat.com>",
    "date": "2026-04-29T21:08:29",
    "name": "[8/9] qom: fix ability to create objects without a parent",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "fae6461c10717e62e56b36da5709694a379ea23b",
    "submitter": {
        "id": 2694,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/2694/?format=api",
        "name": "Daniel P. Berrangé",
        "email": "berrange@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260429210830.594724-9-berrange@redhat.com/mbox/",
    "series": [
        {
            "id": 502152,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/502152/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502152",
            "date": "2026-04-29T21:08:21",
            "name": "qom: misc cleanups / fixes",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/502152/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2230571/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2230571/checks/",
    "tags": {},
    "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=fa7e72fX;\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=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists1p.gnu.org (lists1p.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 4g5VLw2T70z1yHZ\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 07:10:16 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wIC9T-0007au-Ok; Wed, 29 Apr 2026 17:08:59 -0400",
            "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <berrange@redhat.com>)\n id 1wIC9P-0007St-I0\n for qemu-devel@nongnu.org; Wed, 29 Apr 2026 17:08:55 -0400",
            "from us-smtp-delivery-124.mimecast.com ([170.10.129.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <berrange@redhat.com>)\n id 1wIC9N-0004EM-Dp\n for qemu-devel@nongnu.org; Wed, 29 Apr 2026 17:08:55 -0400",
            "from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-347-ffo6F9moM9W3jL3RDZPt0Q-1; Wed,\n 29 Apr 2026 17:08:51 -0400",
            "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 28B871956052\n for <qemu-devel@nongnu.org>; Wed, 29 Apr 2026 21:08:50 +0000 (UTC)",
            "from berrange.com (unknown [10.44.48.62])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id C4C5B300019F; Wed, 29 Apr 2026 21:08:48 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777496932;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=qbJSAvaBjg3zPeD1Zo3ltReyHosDEDMPTFArtiE4iJ4=;\n b=fa7e72fXQUX0aphV0uKT0gmASLuR0vXSFFGPpyvVNchwm4WJRksVghWzxGCzSuNkIFOBjH\n vb8nWowpfnE8gxtt0RTODZfXlvnZXjBZc3naotxImt0l0dthajJ5eXnHhHEb7GyswAwKxf\n bOzUPRRihimLdVTY229TthbRJ7luGe8=",
        "X-MC-Unique": "ffo6F9moM9W3jL3RDZPt0Q-1",
        "X-Mimecast-MFC-AGG-ID": "ffo6F9moM9W3jL3RDZPt0Q_1777496930",
        "From": "=?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= <berrange@redhat.com>",
        "To": "qemu-devel@nongnu.org",
        "Cc": "Paolo Bonzini <pbonzini@redhat.com>,\n =?utf-8?q?Daniel_P=2E_Berrang=C3=A9?= <berrange@redhat.com>",
        "Subject": "[PATCH 8/9] qom: fix ability to create objects without a parent",
        "Date": "Wed, 29 Apr 2026 22:08:29 +0100",
        "Message-ID": "<20260429210830.594724-9-berrange@redhat.com>",
        "In-Reply-To": "<20260429210830.594724-1-berrange@redhat.com>",
        "References": "<20260429210830.594724-1-berrange@redhat.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4",
        "Received-SPF": "pass client-ip=170.10.129.124;\n envelope-from=berrange@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com",
        "X-Spam_score_int": "12",
        "X-Spam_score": "1.2",
        "X-Spam_bar": "+",
        "X-Spam_report": "(1.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001,\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_H4=0.001, RCVD_IN_MSPIKE_WL=0.001,\n RCVD_IN_SBL_CSS=3.335, SPF_HELO_PASS=-0.001,\n SPF_PASS=-0.001 autolearn=no 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": "object_new_with_propv allowed id/parent to be optional, in which case\nthe caller was expected to own the returned object. Unfortunately a\ntrailing object_unref() meant that the returned object was already\nfreed.\n\nIt is confusing to have a single method with two different ownership\nscenarios for the returned object.\n\nMake id/parent mandatory in object_new_with_propv once more, and add\na new object_new_with_propv_parentless that does not accept id/parent\nat all and lets the caller own the returned reference.\n\nThe helper method has abstracted the way properties are represented\nand setk in order to facilitate the subsequent commit.\n\nUnit tests are added to address the root cause that allowed the bug\nto slip through in commit 6134d752.\n\nFixes: 6134d7522e570a30d7f0d1e092ee37351c5183ed\nSigned-off-by: Daniel P. Berrangé <berrange@redhat.com>\n---\n include/qom/object.h            | 47 ++++++++++++++++++\n qom/object.c                    | 74 +++++++++++++++++++++++----\n tests/unit/check-qom-proplist.c | 88 ++++++++++++++++++++++++++++-----\n 3 files changed, 187 insertions(+), 22 deletions(-)",
    "diff": "diff --git a/include/qom/object.h b/include/qom/object.h\nindex cd59f1f171..71530dac76 100644\n--- a/include/qom/object.h\n+++ b/include/qom/object.h\n@@ -719,6 +719,53 @@ Object *object_new_with_props_from_qdict(const char *typename,\n                                          Visitor *v,\n                                          Error **errp);\n \n+/**\n+ * object_new_with_props_parentless:\n+ * @typename:  The name of the type of the object to instantiate.\n+ * @errp: pointer to error object\n+ * @...: list of property names and values\n+ *\n+ * Behaviour as object_new_with_props(), except the object\n+ * will not be added to any parent and thus the caller will\n+ * own the returned instance. The caller must call\n+ * object_unref when it is no longer required.\n+ */\n+Object *object_new_with_props_parentless(const char *typename,\n+                                         Error **errp,\n+                                         ...) G_GNUC_NULL_TERMINATED;\n+\n+/**\n+ * object_new_with_propv_parentless:\n+ * @typename:  The name of the type of the object to instantiate.\n+ * @vargs: list of property names and values\n+ * @errp: pointer to error object\n+ *\n+ * Behaviour as object_new_with_propv(), except the object\n+ * will not be added to any parent and thus the caller will\n+ * own the returned instance. The caller must call\n+ * object_unref when it is no longer required.\n+ */\n+Object *object_new_with_propv_parentless(const char *typename,\n+                                         va_list vargs,\n+                                         Error **errp);\n+\n+/**\n+ * object_new_with_props_from_qdict_parentless:\n+ * @typename:  The name of the type of the object to instantiate.\n+ * @props: dictionary of property names and values\n+ * @v: visitor to iterate over @props\n+ * @errp: pointer to error object\n+ *\n+ * Behaviour as object_new_with_props_from_qdict(), except the\n+ * object will not be added to any parent and thus the caller\n+ * will own the returned instance. The caller must call\n+ * object_unref when it is no longer required.\n+ */\n+Object *object_new_with_props_from_qdict_parentless(const char *typename,\n+                                                    QDict *props,\n+                                                    Visitor *v,\n+                                                    Error **errp);\n+\n /**\n  * object_set_props:\n  * @obj: the object instance to set properties on\ndiff --git a/qom/object.c b/qom/object.c\nindex b35a3dff06..9dc2bdb603 100644\n--- a/qom/object.c\n+++ b/qom/object.c\n@@ -750,6 +750,8 @@ Object *object_new_with_props(const char *typename,\n     va_list vargs;\n     Object *obj;\n \n+    assert(parent != NULL);\n+    assert(id != NULL);\n     va_start(vargs, errp);\n     obj = object_new_with_propv(typename, parent, id, vargs, errp);\n     va_end(vargs);\n@@ -767,10 +769,14 @@ object_new_with_props_helper(const char *typename,\n                                               Error **errp),\n                              Error **errp)\n {\n+    ERRP_GUARD();\n     Object *obj;\n     ObjectClass *klass;\n     UserCreatable *uc;\n \n+    assert((id != NULL && parent != NULL) ||\n+           (id == NULL && parent == NULL));\n+\n     if (id != NULL && !id_wellformed(id)) {\n         error_setg(errp, QERR_INVALID_PARAMETER_VALUE, \"id\", \"an identifier\");\n         error_append_hint(errp, \"Identifiers consist of letters, digits, \"\n@@ -795,7 +801,10 @@ object_new_with_props_helper(const char *typename,\n     }\n \n     if (id != NULL) {\n-        object_property_add_child(parent, id, obj);\n+        object_property_try_add_child(parent, id, obj, errp);\n+        if (*errp) {\n+            goto error;\n+        }\n     }\n \n     uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);\n@@ -808,7 +817,6 @@ object_new_with_props_helper(const char *typename,\n         }\n     }\n \n-    object_unref(obj);\n     return obj;\n \n  error:\n@@ -836,7 +844,8 @@ Object *object_new_with_propv(const char *typename,\n {\n     Object *obj;\n     struct ObjectNewVargsData data;\n-\n+    assert(parent != NULL);\n+    assert(id != NULL);\n     va_copy(data.vargs, vargs);\n     obj = object_new_with_props_helper(typename,\n                                        parent,\n@@ -845,6 +854,9 @@ Object *object_new_with_propv(const char *typename,\n                                        object_new_with_propv_setter,\n                                        errp);\n     va_end(data.vargs);\n+    if (obj) {\n+        object_unref(obj);\n+    }\n     return obj;\n }\n \n@@ -869,12 +881,56 @@ Object *object_new_with_props_from_qdict(const char *typename,\n                                          Error **errp)\n {\n     struct ObjectNewQDictData data = { props, v };\n-    return object_new_with_props_helper(typename,\n-                                        parent,\n-                                        id,\n-                                        &data,\n-                                        object_new_with_qdict_setter,\n-                                        errp);\n+    Object *obj;\n+    assert(parent != NULL);\n+    assert(id != NULL);\n+    obj = object_new_with_props_helper(typename,\n+                                       parent,\n+                                       id,\n+                                       &data,\n+                                       object_new_with_qdict_setter,\n+                                       errp);\n+    if (obj) {\n+        object_unref(obj);\n+    }\n+    return obj;\n+}\n+\n+Object *object_new_with_props_parentless(const char *typename,\n+                                         Error **errp,\n+                                         ...)\n+{\n+    va_list vargs;\n+    Object *obj;\n+\n+    va_start(vargs, errp);\n+    obj = object_new_with_propv_parentless(typename, vargs, errp);\n+    va_end(vargs);\n+\n+    return obj;\n+}\n+\n+Object *object_new_with_propv_parentless(const char *typename,\n+                                         va_list vargs,\n+                                         Error **errp)\n+{\n+    Object *ret;\n+    struct ObjectNewVargsData data;\n+    va_copy(data.vargs, vargs);\n+    ret = object_new_with_props_helper(typename, NULL, NULL, &data,\n+                                       object_new_with_propv_setter, errp);\n+    va_end(vargs);\n+    return ret;\n+}\n+\n+Object *object_new_with_props_from_qdict_parentless(const char *typename,\n+                                                    QDict *props,\n+                                                    Visitor *v,\n+                                                    Error **errp)\n+{\n+    struct ObjectNewQDictData data = { props, v };\n+    return object_new_with_props_helper(typename, NULL, NULL, &data,\n+                                        object_new_with_qdict_setter, errp);\n }\n \n bool object_set_props(Object *obj,\ndiff --git a/tests/unit/check-qom-proplist.c b/tests/unit/check-qom-proplist.c\nindex 7f31735459..954c898ce1 100644\n--- a/tests/unit/check-qom-proplist.c\n+++ b/tests/unit/check-qom-proplist.c\n@@ -336,7 +336,7 @@ static QemuOptsList qemu_object_opts = {\n };\n \n \n-static void test_dummy_createv(void)\n+static void test_dummy_createv_tree(void)\n {\n     Error *err = NULL;\n     Object *parent = object_get_objects_root();\n@@ -351,6 +351,7 @@ static void test_dummy_createv(void)\n                               NULL));\n \n     g_assert(err == NULL);\n+    g_assert_cmpint(dobj->parent_obj.ref, ==, 1);\n     g_assert_cmpstr(dobj->sv, ==, \"Hiss hiss hiss\");\n     g_assert(dobj->bv == true);\n     g_assert(dobj->av == DUMMY_PLATYPUS);\n@@ -362,9 +363,30 @@ static void test_dummy_createv(void)\n }\n \n \n-static Object *new_helper(Error **errp,\n-                          Object *parent,\n-                          ...)\n+static void test_dummy_createv_parentless(void)\n+{\n+    Error *err = NULL;\n+    DummyObject *dobj = DUMMY_OBJECT(\n+        object_new_with_props_parentless(TYPE_DUMMY,\n+                                         &err,\n+                                         \"bv\", \"yes\",\n+                                         \"sv\", \"Hiss hiss hiss\",\n+                                         \"av\", \"platypus\",\n+                                         NULL));\n+\n+    g_assert(err == NULL);\n+    g_assert_cmpint(dobj->parent_obj.ref, ==, 1);\n+    g_assert_cmpstr(dobj->sv, ==, \"Hiss hiss hiss\");\n+    g_assert(dobj->bv == true);\n+    g_assert(dobj->av == DUMMY_PLATYPUS);\n+\n+    object_unref(OBJECT(dobj));\n+}\n+\n+\n+static Object *new_helper_tree(Error **errp,\n+                               Object *parent,\n+                               ...)\n {\n     va_list vargs;\n     Object *obj;\n@@ -379,19 +401,20 @@ static Object *new_helper(Error **errp,\n     return obj;\n }\n \n-static void test_dummy_createlist(void)\n+static void test_dummy_createlist_tree(void)\n {\n     Error *err = NULL;\n     Object *parent = object_get_objects_root();\n     DummyObject *dobj = DUMMY_OBJECT(\n-        new_helper(&err,\n-                   parent,\n-                   \"bv\", \"yes\",\n-                   \"sv\", \"Hiss hiss hiss\",\n-                   \"av\", \"platypus\",\n-                   NULL));\n+        new_helper_tree(&err,\n+                        parent,\n+                        \"bv\", \"yes\",\n+                        \"sv\", \"Hiss hiss hiss\",\n+                        \"av\", \"platypus\",\n+                        NULL));\n \n     g_assert(err == NULL);\n+    g_assert_cmpint(dobj->parent_obj.ref, ==, 1);\n     g_assert_cmpstr(dobj->sv, ==, \"Hiss hiss hiss\");\n     g_assert(dobj->bv == true);\n     g_assert(dobj->av == DUMMY_PLATYPUS);\n@@ -402,6 +425,39 @@ static void test_dummy_createlist(void)\n     object_unparent(OBJECT(dobj));\n }\n \n+static Object *new_helper_parentless(Error **errp,\n+                                     ...)\n+{\n+    va_list vargs;\n+    Object *obj;\n+\n+    va_start(vargs, errp);\n+    obj = object_new_with_propv_parentless(TYPE_DUMMY,\n+                                           vargs,\n+                                           errp);\n+    va_end(vargs);\n+    return obj;\n+}\n+\n+static void test_dummy_createlist_parentless(void)\n+{\n+    Error *err = NULL;\n+    DummyObject *dobj = DUMMY_OBJECT(\n+        new_helper_parentless(&err,\n+                              \"bv\", \"yes\",\n+                              \"sv\", \"Hiss hiss hiss\",\n+                              \"av\", \"platypus\",\n+                              NULL));\n+\n+    g_assert(err == NULL);\n+    g_assert_cmpint(dobj->parent_obj.ref, ==, 1);\n+    g_assert_cmpstr(dobj->sv, ==, \"Hiss hiss hiss\");\n+    g_assert(dobj->bv == true);\n+    g_assert(dobj->av == DUMMY_PLATYPUS);\n+\n+    object_unref(OBJECT(dobj));\n+}\n+\n static bool test_create_obj(QDict *qdict, Error **errp)\n {\n     Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(qdict));\n@@ -658,8 +714,14 @@ int main(int argc, char **argv)\n     type_register_static(&dummy_bus_info);\n     type_register_static(&dummy_backend_info);\n \n-    g_test_add_func(\"/qom/proplist/createlist\", test_dummy_createlist);\n-    g_test_add_func(\"/qom/proplist/createv\", test_dummy_createv);\n+    g_test_add_func(\"/qom/proplist/createlist/tree\",\n+                    test_dummy_createlist_tree);\n+    g_test_add_func(\"/qom/proplist/createlist/parentless\",\n+                    test_dummy_createlist_parentless);\n+    g_test_add_func(\"/qom/proplist/createv/tree\",\n+                    test_dummy_createv_tree);\n+    g_test_add_func(\"/qom/proplist/createv/parentless\",\n+                    test_dummy_createv_parentless);\n     g_test_add_func(\"/qom/proplist/createcmdline\", test_dummy_createcmdl);\n     g_test_add_func(\"/qom/proplist/badenum\", test_dummy_badenum);\n     g_test_add_func(\"/qom/proplist/getenum\", test_dummy_getenum);\n",
    "prefixes": [
        "8/9"
    ]
}