From nobody Sat Apr 27 21:50:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1538083640095653.2597308865974; Thu, 27 Sep 2018 14:27:20 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 207CDBCD51; Thu, 27 Sep 2018 21:27:18 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DCC795D6A9; Thu, 27 Sep 2018 21:27:17 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 890344A46D; Thu, 27 Sep 2018 21:27:17 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLQuAm005743 for ; Thu, 27 Sep 2018 17:26:56 -0400 Received: by smtp.corp.redhat.com (Postfix) id A0BA15D777; Thu, 27 Sep 2018 21:26:56 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id D60A25D6A9; Thu, 27 Sep 2018 21:26:55 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:40 -0500 Message-Id: <20180927212645.20758-2-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 1/6] qemu_monitor: Introduce qemuMonitorCPUModelInfoNew X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 27 Sep 2018 21:27:18 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" A helper function allocates an initializes model name in CPU Model Info structs. Signed-off-by: Chris Venteicher --- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_monitor.c | 32 +++++++++++++++++++++++++++----- src/qemu/qemu_monitor.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index e228f52ec0..e60a4b369e 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3022,7 +3022,7 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsPtr qemuCa= ps, goto cleanup; } =20 - if (VIR_ALLOC(hostCPU) < 0) + if (!(hostCPU =3D qemuMonitorCPUModelInfoNew(NULL))) goto cleanup; =20 if (!(hostCPU->name =3D virXMLPropString(hostCPUNode, "model"))) { diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7f7013e115..45a4568fcc 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3670,6 +3670,31 @@ qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon, } =20 =20 +qemuMonitorCPUModelInfoPtr +qemuMonitorCPUModelInfoNew(const char *name) +{ + qemuMonitorCPUModelInfoPtr ret =3D NULL; + qemuMonitorCPUModelInfoPtr model; + + if (VIR_ALLOC(model) < 0) + return NULL; + + model->name =3D NULL; + model->nprops =3D 0; + model->props =3D NULL; + model->migratability =3D false; + + if (VIR_STRDUP(model->name, name) < 0) + goto cleanup; + + VIR_STEAL_PTR(ret, model); + + cleanup: + qemuMonitorCPUModelInfoFree(model); + return ret; +} + + void qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info) { @@ -3693,18 +3718,15 @@ qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfo= Ptr model_info) qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig) { - qemuMonitorCPUModelInfoPtr copy; + qemuMonitorCPUModelInfoPtr copy =3D NULL; size_t i; =20 - if (VIR_ALLOC(copy) < 0) + if (!orig || !(copy =3D qemuMonitorCPUModelInfoNew(orig->name))) goto error; =20 if (VIR_ALLOC_N(copy->props, orig->nprops) < 0) goto error; =20 - if (VIR_STRDUP(copy->name, orig->name) < 0) - goto error; - copy->migratability =3D orig->migratability; copy->nprops =3D orig->nprops; =20 diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 48b142a4f4..d87b5a4ec0 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1042,6 +1042,8 @@ int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mo= n, =20 void qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info); =20 +qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoNew(const char *name); + qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig); =20 --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Apr 27 21:50:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1538083623503106.3647792968045; Thu, 27 Sep 2018 14:27:03 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D3D1D307C941; Thu, 27 Sep 2018 21:27:00 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 44ABD65954; Thu, 27 Sep 2018 21:27:00 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 2E48F4BB7F; Thu, 27 Sep 2018 21:26:59 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLQvKn005752 for ; Thu, 27 Sep 2018 17:26:57 -0400 Received: by smtp.corp.redhat.com (Postfix) id AC74C5D772; Thu, 27 Sep 2018 21:26:57 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id E2C7E5D6A9; Thu, 27 Sep 2018 21:26:56 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:41 -0500 Message-Id: <20180927212645.20758-3-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 2/6] qemu_monitor: Introduce qemuMonitorCPUModelInfo / JSON conversion X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 27 Sep 2018 21:27:02 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Conversion functions are used convert CPUModelInfo structs into QMP JSON and the reverse. QMP JSON is of form: {"model": {"name": "IvyBridge", "props": {}}} qemuMonitorCPUModelInfoBoolPropAdd is used to add boolean properties to CPUModelInfo struct. qemuMonitorJSONGetCPUModelExpansion makes full use of conversions and propAdd in prep to support input of full cpu model in future. Signed-off-by: Chris Venteicher --- src/qemu/qemu_monitor.c | 24 ++++++ src/qemu/qemu_monitor.h | 5 ++ src/qemu/qemu_monitor_json.c | 154 +++++++++++++++++++++++++---------- 3 files changed, 138 insertions(+), 45 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 45a4568fcc..801c072eff 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3764,6 +3764,30 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUMode= lInfo *orig) } =20 =20 +int +qemuMonitorCPUModelInfoBoolPropAdd(qemuMonitorCPUModelInfoPtr model, + const char *prop_name, + bool prop_value) +{ + int ret =3D -1; + qemuMonitorCPUProperty prop; + prop.type =3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN; + prop.value.boolean =3D prop_value; + + if (VIR_STRDUP(prop.name, prop_name) < 0) + goto cleanup; + + if (VIR_APPEND_ELEMENT(model->props, model->nprops, prop) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FREE(prop.name); + return ret; +} + + int qemuMonitorGetCommands(qemuMonitorPtr mon, char ***commands) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d87b5a4ec0..0a09590ed1 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1047,6 +1047,11 @@ qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoNe= w(const char *name); qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig); =20 +int qemuMonitorCPUModelInfoBoolPropAdd(qemuMonitorCPUModelInfoPtr model, + const char *prop_name, + bool prop_value) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int qemuMonitorGetCommands(qemuMonitorPtr mon, char ***commands); int qemuMonitorGetEvents(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 3de298c9e2..f20e9e9379 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5505,6 +5505,101 @@ qemuMonitorJSONParseCPUModelProperty(const char *ke= y, return 0; } =20 + +/* model_json: {"name": "z13-base", "props": {}} + */ +static virJSONValuePtr +qemuMonitorJSONBuildCPUModelInfoToJSON(qemuMonitorCPUModelInfoPtr model) +{ + virJSONValuePtr cpu_props =3D NULL; + virJSONValuePtr model_json =3D NULL; + size_t i; + + if (!model) + goto cleanup; + + if (model->nprops > 0 && !(cpu_props =3D virJSONValueNewObject())) + goto cleanup; + + for (i =3D 0; i < model->nprops; i++) { + qemuMonitorCPUPropertyPtr prop =3D &(model->props[i]); + + switch (prop->type) { + case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: + if (virJSONValueObjectAppendBoolean(cpu_props, prop->name, + prop->value.boolean) < 0) + goto cleanup; + break; + + case QEMU_MONITOR_CPU_PROPERTY_STRING: + if (virJSONValueObjectAppendString(cpu_props, prop->name, + prop->value.string) < 0) + goto cleanup; + break; + + case QEMU_MONITOR_CPU_PROPERTY_NUMBER: + if (virJSONValueObjectAppendNumberLong(cpu_props, prop->name, + prop->value.number) < 0) + goto cleanup; + break; + + case QEMU_MONITOR_CPU_PROPERTY_LAST: + default: + virReportEnumRangeError(qemuMonitorCPUPropertyPtr, prop->type); + goto cleanup; + } + } + + ignore_value(virJSONValueObjectCreate(&model_json, "s:name", model->na= me, + "A:props", &cpu_props, NULL)); + + cleanup: + virJSONValueFree(cpu_props); + return model_json; +} + + +/* model_json: {"name": "IvyBridge", "props": {}} + */ +static qemuMonitorCPUModelInfoPtr +qemuMonitorJSONBuildCPUModelInfoFromJSON(virJSONValuePtr cpu_model) +{ + virJSONValuePtr cpu_props; + qemuMonitorCPUModelInfoPtr model =3D NULL; + qemuMonitorCPUModelInfoPtr ret =3D NULL; + char const *cpu_name; + + if (!(cpu_name =3D virJSONValueObjectGetString(cpu_model, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Parsed JSON reply missing 'name'")); + goto cleanup; + } + + if (VIR_ALLOC(model) < 0) + goto cleanup; + + if (VIR_STRDUP(model->name, cpu_name) < 0) + goto cleanup; + + if ((cpu_props =3D virJSONValueObjectGetObject(cpu_model, "props"))) { + if (VIR_ALLOC_N(model->props, + virJSONValueObjectKeysNumber(cpu_props)) < 0) + goto cleanup; + + if (virJSONValueObjectForeachKeyValue(cpu_props, + qemuMonitorJSONParseCPUModel= Property, + model) < 0) + goto cleanup; + } + + VIR_STEAL_PTR(ret, model); + + cleanup: + qemuMonitorCPUModelInfoFree(model); + + return ret; +} + int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelExpansionType type, @@ -5513,32 +5608,25 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr = mon, qemuMonitorCPUModelInfoPtr *model_info) { int ret =3D -1; - virJSONValuePtr model =3D NULL; - virJSONValuePtr props =3D NULL; + virJSONValuePtr json_model_in =3D NULL; virJSONValuePtr cmd =3D NULL; virJSONValuePtr reply =3D NULL; virJSONValuePtr data; virJSONValuePtr cpu_model; - virJSONValuePtr cpu_props; - qemuMonitorCPUModelInfoPtr machine_model =3D NULL; - char const *cpu_name; + qemuMonitorCPUModelInfoPtr model_in =3D NULL; const char *typeStr =3D ""; =20 *model_info =3D NULL; =20 - if (!(model =3D virJSONValueNewObject())) + if (!(model_in =3D qemuMonitorCPUModelInfoNew(model_name))) goto cleanup; =20 - if (virJSONValueObjectAppendString(model, "name", model_name) < 0) + if (!migratable && + qemuMonitorCPUModelInfoBoolPropAdd(model_in, "migratable", false) = < 0) goto cleanup; =20 - if (!migratable) { - if (!(props =3D virJSONValueNewObject()) || - virJSONValueObjectAppendBoolean(props, "migratable", false) < = 0 || - virJSONValueObjectAppend(model, "props", props) < 0) - goto cleanup; - props =3D NULL; - } + if (!(json_model_in =3D qemuMonitorJSONBuildCPUModelInfoToJSON(model_i= n))) + goto cleanup; =20 retry: switch (type) { @@ -5554,7 +5642,7 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mo= n, =20 if (!(cmd =3D qemuMonitorJSONMakeCommand("query-cpu-model-expansion", "s:type", typeStr, - "a:model", &model, + "a:model", &json_model_in, NULL))) goto cleanup; =20 @@ -5585,7 +5673,9 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mo= n, * on the result of the initial "static" expansion. */ if (type =3D=3D QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL) { - if (!(model =3D virJSONValueCopy(cpu_model))) + virJSONValueFree(json_model_in); + + if (!(json_model_in =3D virJSONValueCopy(cpu_model))) goto cleanup; =20 virJSONValueFree(cmd); @@ -5594,42 +5684,16 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr = mon, goto retry; } =20 - if (!(cpu_name =3D virJSONValueObjectGetString(cpu_model, "name"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("query-cpu-model-expansion reply data was missing= 'name'")); - goto cleanup; - } - - if (!(cpu_props =3D virJSONValueObjectGetObject(cpu_model, "props"))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("query-cpu-model-expansion reply data was missing= 'props'")); - goto cleanup; - } - - if (VIR_ALLOC(machine_model) < 0) - goto cleanup; - - if (VIR_STRDUP(machine_model->name, cpu_name) < 0) - goto cleanup; - - if (VIR_ALLOC_N(machine_model->props, virJSONValueObjectKeysNumber(cpu= _props)) < 0) - goto cleanup; - - if (virJSONValueObjectForeachKeyValue(cpu_props, - qemuMonitorJSONParseCPUModelProp= erty, - machine_model) < 0) + if (!(*model_info =3D qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu_mod= el))) goto cleanup; =20 ret =3D 0; - *model_info =3D machine_model; - machine_model =3D NULL; =20 cleanup: - qemuMonitorCPUModelInfoFree(machine_model); + qemuMonitorCPUModelInfoFree(model_in); virJSONValueFree(cmd); virJSONValueFree(reply); - virJSONValueFree(model); - virJSONValueFree(props); + virJSONValueFree(json_model_in); return ret; } =20 --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Apr 27 21:50:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1538083639782660.3009632634826; Thu, 27 Sep 2018 14:27:19 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D895330E6849; Thu, 27 Sep 2018 21:27:17 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 948FD17BA9; Thu, 27 Sep 2018 21:27:17 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 4694E181A12F; Thu, 27 Sep 2018 21:27:17 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLQwEe005762 for ; Thu, 27 Sep 2018 17:26:58 -0400 Received: by smtp.corp.redhat.com (Postfix) id D33425D772; Thu, 27 Sep 2018 21:26:58 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id E7E4D5D6A9; Thu, 27 Sep 2018 21:26:57 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:42 -0500 Message-Id: <20180927212645.20758-4-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 3/6] qemu_monitor: qemuMonitorGetCPUModelExpansion inputs and outputs CPUModelInfo X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Thu, 27 Sep 2018 21:27:18 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" A Full CPUModelInfo structure with props is sent to QEMU for expansion. virQEMUCapsProbeQMPHostCPU migratability logic partitioned into new function for clarity. Signed-off-by: Chris Venteicher --- src/qemu/qemu_capabilities.c | 125 ++++++++++++++++++++++++----------- src/qemu/qemu_monitor.c | 47 +++++++++++-- src/qemu/qemu_monitor.h | 5 +- src/qemu/qemu_monitor_json.c | 20 ++++-- src/qemu/qemu_monitor_json.h | 6 +- tests/cputest.c | 11 ++- 6 files changed, 156 insertions(+), 58 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index e60a4b369e..d38530ca80 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2352,15 +2352,82 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qe= muCaps, return 0; } =20 +/* virQEMUCapsMigratablePropsDiff + * @migratable: migratable props=3Dtrue, non-migratable & unsupported prop= s=3Dfalse + * @nonMigratable: migratable & non-migratable props =3D true, unsupported= props =3D false + * @augmented: prop->migratable =3D VIR_TRISTATE_BOOL_{YES/NO} base on diff + * + * Use differences in Expanded CPUModelInfo inputs + * to augment with prop->migratable in CPUModelInfo output + */ +static int +virQEMUCapsMigratablePropsDiff(qemuMonitorCPUModelInfoPtr migratable, + qemuMonitorCPUModelInfoPtr nonMigratable, + qemuMonitorCPUModelInfoPtr *augmented) +{ + int ret =3D -1; + qemuMonitorCPUModelInfoPtr tmp; + qemuMonitorCPUPropertyPtr prop; + qemuMonitorCPUPropertyPtr mProp; + qemuMonitorCPUPropertyPtr nmProp; + virHashTablePtr hash =3D NULL; + size_t i; + + *augmented =3D NULL; + + if (!(tmp =3D qemuMonitorCPUModelInfoCopy(migratable))) + goto cleanup; + + if (!nonMigratable) + goto done; + + if (!(hash =3D virHashCreate(0, NULL))) + goto cleanup; + + for (i =3D 0; i < tmp->nprops; i++) { + prop =3D tmp->props + i; + + if (virHashAddEntry(hash, prop->name, prop) < 0) + goto cleanup; + } + + for (i =3D 0; i < nonMigratable->nprops; i++) { + nmProp =3D nonMigratable->props + i; + + if (!(mProp =3D virHashLookup(hash, nmProp->name)) || + mProp->type !=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN || + mProp->type !=3D nmProp->type) + continue; /* In non-migratable list but not in migratable lis= t */ + + if (mProp->value.boolean) { + mProp->migratable =3D VIR_TRISTATE_BOOL_YES; + } else if (nmProp->value.boolean) { + mProp->value.boolean =3D true; + mProp->migratable =3D VIR_TRISTATE_BOOL_NO; + } + } + + tmp->migratability =3D true; + + done: + VIR_STEAL_PTR(*augmented, tmp); + ret =3D 0; + + cleanup: + qemuMonitorCPUModelInfoFree(tmp); + virHashFree(hash); + return ret; +} =20 static int virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, qemuMonitorPtr mon, bool tcg) { - qemuMonitorCPUModelInfoPtr modelInfo =3D NULL; + qemuMonitorCPUModelInfoPtr input; + qemuMonitorCPUModelInfoPtr migratable =3D NULL; qemuMonitorCPUModelInfoPtr nonMigratable =3D NULL; - virHashTablePtr hash =3D NULL; + qemuMonitorCPUModelInfoPtr augmented =3D NULL; const char *model; qemuMonitorCPUModelExpansionType type; virDomainVirtType virtType; @@ -2380,6 +2447,8 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, =20 cpuData =3D virQEMUCapsGetHostCPUData(qemuCaps, virtType); =20 + cpuData->info =3D NULL; + /* Some x86_64 features defined in cpu_map.xml use spelling which diff= er * from the one preferred by QEMU. Static expansion would give us only= the * preferred spelling, thus we need to do a full expansion on the resu= lt of @@ -2390,54 +2459,30 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, else type =3D QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC; =20 - if (qemuMonitorGetCPUModelExpansion(mon, type, model, true, &modelInfo= ) < 0) + if (!(input =3D qemuMonitorCPUModelInfoNew(model)) || + qemuMonitorGetCPUModelExpansion(mon, type, true, input, &migratabl= e) < 0) goto cleanup; =20 - /* Try to check migratability of each feature. */ - if (modelInfo && - qemuMonitorGetCPUModelExpansion(mon, type, model, false, - &nonMigratable) < 0) + if (!migratable) { + ret =3D 0; /* Qemu can't expand the model name, exit without = error */ goto cleanup; + } =20 - if (nonMigratable) { - qemuMonitorCPUPropertyPtr prop; - qemuMonitorCPUPropertyPtr nmProp; - size_t i; - - if (!(hash =3D virHashCreate(0, NULL))) - goto cleanup; - - for (i =3D 0; i < modelInfo->nprops; i++) { - prop =3D modelInfo->props + i; - if (virHashAddEntry(hash, prop->name, prop) < 0) - goto cleanup; - } - - for (i =3D 0; i < nonMigratable->nprops; i++) { - nmProp =3D nonMigratable->props + i; - if (!(prop =3D virHashLookup(hash, nmProp->name)) || - prop->type !=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN || - prop->type !=3D nmProp->type) - continue; - - if (prop->value.boolean) { - prop->migratable =3D VIR_TRISTATE_BOOL_YES; - } else if (nmProp->value.boolean) { - prop->value.boolean =3D true; - prop->migratable =3D VIR_TRISTATE_BOOL_NO; - } - } + /* Try to check migratability of each feature. */ + if (qemuMonitorGetCPUModelExpansion(mon, type, false, input, &nonMigra= table) < 0) + goto cleanup; =20 - modelInfo->migratability =3D true; - } + if (virQEMUCapsMigratablePropsDiff(migratable, nonMigratable, &augment= ed) < 0) + goto cleanup; =20 - VIR_STEAL_PTR(cpuData->info, modelInfo); + VIR_STEAL_PTR(cpuData->info, augmented); ret =3D 0; =20 cleanup: - virHashFree(hash); + qemuMonitorCPUModelInfoFree(input); + qemuMonitorCPUModelInfoFree(migratable); qemuMonitorCPUModelInfoFree(nonMigratable); - qemuMonitorCPUModelInfoFree(modelInfo); + qemuMonitorCPUModelInfoFree(augmented); =20 return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 801c072eff..c64b3ad38a 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3653,20 +3653,57 @@ qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr = cpu) } =20 =20 +/** + * qemuMonitorGetCPUModelExpansion: + * @mon: + * @type: qemuMonitorCPUModelExpansionType + * @migratable: Prompt QEMU to include non-migratable features for X86 mod= els if false. + * @input: Non-expanded input model + * @expansion: Expanded output model (or NULL if QEMU rejects model / requ= est) + * + * CPU property lists are computed from CPUModelInfo structures by 1) conv= erting + * model->name into a property list using a static lookup table and 2) add= ing or + * removing properties in the resulting list from model->props. + * + * This function uses QEMU to identify a base model name that most closely + * matches the migratable CPU properties in the input CPU Model. + * + * This function also uses QEMU to enumerate model->props in various ways = based + * on the qemuMonitorCPUModelExpansionType. + * + * full_input_props =3D LookupProps(input->name) then +/- input->props + * + * migratable_input_props =3D full_input_props - non_migratable_input_props + * + * base_model =3D FindClosestBaseModel(migratable_input_props) + * + * expansion->name =3D base_model->name + * + * @type =3D=3D QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC + * expansion->props =3D props to +/- to base_model to approximate migrat= able_input_props + * + * @type =3D=3D QEMU_MONITOR_CPU_MODEL_EXPANSION_FULL + * expansion->props =3D full_input_props + * + * @type =3D=3D QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL + * expansion->props =3D migratable_input_props + * + * Returns 0 in case of success, -1 in case of failure + */ int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelExpansionType type, - const char *model_name, bool migratable, - qemuMonitorCPUModelInfoPtr *model_info) + qemuMonitorCPUModelInfoPtr input, + qemuMonitorCPUModelInfoPtr *expansion + ) { VIR_DEBUG("type=3D%d model_name=3D%s migratable=3D%d", - type, model_name, migratable); + type, input->name, migratable); =20 QEMU_CHECK_MONITOR(mon); =20 - return qemuMonitorJSONGetCPUModelExpansion(mon, type, model_name, - migratable, model_info); + return qemuMonitorJSONGetCPUModelExpansion(mon, type, migratable, inpu= t, expansion); } =20 =20 diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 0a09590ed1..d3efd37099 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1036,9 +1036,10 @@ typedef enum { =20 int qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelExpansionType type, - const char *model_name, bool migratable, - qemuMonitorCPUModelInfoPtr *model_info= ); + qemuMonitorCPUModelInfoPtr input, + qemuMonitorCPUModelInfoPtr *expansion) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); =20 void qemuMonitorCPUModelInfoFree(qemuMonitorCPUModelInfoPtr model_info); =20 diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index f20e9e9379..4e6e220a8c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5600,12 +5600,17 @@ qemuMonitorJSONBuildCPUModelInfoFromJSON(virJSONVal= uePtr cpu_model) return ret; } =20 + +/* return: + * -1 - Execution Failure + * 0 - Success + */ int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelExpansionType type, - const char *model_name, bool migratable, - qemuMonitorCPUModelInfoPtr *model_info) + qemuMonitorCPUModelInfoPtr input, + qemuMonitorCPUModelInfoPtr *expansion) { int ret =3D -1; virJSONValuePtr json_model_in =3D NULL; @@ -5613,12 +5618,13 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr = mon, virJSONValuePtr reply =3D NULL; virJSONValuePtr data; virJSONValuePtr cpu_model; + qemuMonitorCPUModelInfoPtr expanded_model =3D NULL; qemuMonitorCPUModelInfoPtr model_in =3D NULL; const char *typeStr =3D ""; =20 - *model_info =3D NULL; + *expansion =3D NULL; =20 - if (!(model_in =3D qemuMonitorCPUModelInfoNew(model_name))) + if (!(model_in =3D qemuMonitorCPUModelInfoCopy(input))) goto cleanup; =20 if (!migratable && @@ -5684,13 +5690,17 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr = mon, goto retry; } =20 - if (!(*model_info =3D qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu_mod= el))) + if (!(expanded_model =3D qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu_= model))) goto cleanup; =20 + VIR_STEAL_PTR(*expansion, expanded_model); ret =3D 0; =20 cleanup: + VIR_FREE(expanded_model); /* Free structure but not reused contents */ qemuMonitorCPUModelInfoFree(model_in); + qemuMonitorCPUModelInfoFree(expanded_model); + virJSONValueFree(cmd); virJSONValueFree(reply); virJSONValueFree(json_model_in); diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index da267b15b0..2d5679094e 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -367,10 +367,10 @@ int qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr m= on, =20 int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelExpansionType t= ype, - const char *model_name, bool migratable, - qemuMonitorCPUModelInfoPtr *model_= info) - ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(5); + qemuMonitorCPUModelInfoPtr input, + qemuMonitorCPUModelInfoPtr *expans= ion) + ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); =20 int qemuMonitorJSONGetCommands(qemuMonitorPtr mon, char ***commands) diff --git a/tests/cputest.c b/tests/cputest.c index 339119c63f..c438a8d09e 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -483,6 +483,7 @@ cpuTestMakeQEMUCaps(const struct data *data) virQEMUCapsPtr qemuCaps =3D NULL; qemuMonitorTestPtr testMon =3D NULL; qemuMonitorCPUModelInfoPtr model =3D NULL; + qemuMonitorCPUModelInfoPtr expansion =3D NULL; char *json =3D NULL; =20 if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", @@ -492,9 +493,12 @@ cpuTestMakeQEMUCaps(const struct data *data) if (!(testMon =3D qemuMonitorTestNewFromFile(json, driver.xmlopt, true= ))) goto error; =20 + if (!(model =3D qemuMonitorCPUModelInfoNew("host"))) + goto cleanup; + if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon), QEMU_MONITOR_CPU_MODEL_EXPANSION_S= TATIC, - "host", true, &model) < 0) + true, model, &expansion) < 0) goto error; =20 if (!(qemuCaps =3D virQEMUCapsNew())) @@ -506,8 +510,8 @@ cpuTestMakeQEMUCaps(const struct data *data) virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); =20 virQEMUCapsSetArch(qemuCaps, data->arch); - virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); - model =3D NULL; + virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, expansion); + expansion =3D NULL; =20 if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, qemuMonitorTestGetMonitor(testMo= n), @@ -516,6 +520,7 @@ cpuTestMakeQEMUCaps(const struct data *data) =20 cleanup: qemuMonitorCPUModelInfoFree(model); + qemuMonitorCPUModelInfoFree(expansion); qemuMonitorTestFree(testMon); VIR_FREE(json); =20 --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Apr 27 21:50:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1538083645432956.2093170648719; Thu, 27 Sep 2018 14:27:25 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9B0C480F6C; Thu, 27 Sep 2018 21:27:22 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 62EA830157BE; Thu, 27 Sep 2018 21:27:22 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 197DF181A12F; Thu, 27 Sep 2018 21:27:22 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLR0YI005771 for ; Thu, 27 Sep 2018 17:27:00 -0400 Received: by smtp.corp.redhat.com (Postfix) id 034CC5D772; Thu, 27 Sep 2018 21:27:00 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1BB3E5D6A9; Thu, 27 Sep 2018 21:26:58 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:43 -0500 Message-Id: <20180927212645.20758-5-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 4/6] qemu_process: Use common processes mgmt funcs for all QMP query types X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Thu, 27 Sep 2018 21:27:23 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Generalized QEMU process management functions supporting all forms of QMP queries including but no limited to capabilities queries. QEMU process instances can be maintained and used for multiple different QMP queries, of the same or different types, as required to complete a specific libvirt task. Support concurrent QEMU process instances for QMP queries, using the same or different qemu binaries. All process mgmt functions are removed from qemu_capabilities and re-implemented in qemu_process in a generic, non capabilities specific, manner consistent with existing qemu_process mgmt functions. Concept of qmp_query domain is used to contain process state through the an entire process lifecycle similar to how a VM domains contain process state in existing process functions. Monitor callbacks were not used in original process management code for capabilities and are eliminated in new generalized process code for QMP queries. QMP exchange to exit capabilities negotiation mode and enter command mode is the sole responsibility of the QMP query process code. Signed-off-by: Chris Venteicher --- src/qemu/qemu_capabilities.c | 304 +++++--------------------- src/qemu/qemu_monitor.c | 4 +- src/qemu/qemu_process.c | 398 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_process.h | 35 +++ tests/qemucapabilitiestest.c | 7 + 5 files changed, 489 insertions(+), 259 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d38530ca80..5b1e4f1bbd 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -47,6 +47,7 @@ #define __QEMU_CAPSPRIV_H_ALLOW__ #include "qemu_capspriv.h" #include "qemu_qapi.h" +#include "qemu_process.h" =20 #include #include @@ -3960,18 +3961,6 @@ virQEMUCapsIsValid(void *data, } =20 =20 -static void virQEMUCapsMonitorNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED, - virDomainObjPtr vm ATTRIBUTE_UNUSED, - void *opaque ATTRIBUTE_UNUSED) -{ -} - -static qemuMonitorCallbacks callbacks =3D { - .eofNotify =3D virQEMUCapsMonitorNotify, - .errorNotify =3D virQEMUCapsMonitorNotify, -}; - - /** * virQEMUCapsInitQMPArch: * @qemuCaps: QEMU capabilities @@ -4067,13 +4056,6 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, =20 /* @mon is supposed to be locked by callee */ =20 - if (qemuMonitorSetCapabilities(mon) < 0) { - VIR_DEBUG("Failed to set monitor capabilities %s", - virGetLastErrorMessage()); - ret =3D 0; - goto cleanup; - } - if (qemuMonitorGetVersion(mon, &major, &minor, µ, &package) < 0) { @@ -4247,13 +4229,6 @@ virQEMUCapsInitQMPMonitorTCG(virQEMUCapsPtr qemuCaps= ATTRIBUTE_UNUSED, { int ret =3D -1; =20 - if (qemuMonitorSetCapabilities(mon) < 0) { - VIR_DEBUG("Failed to set monitor capabilities %s", - virGetLastErrorMessage()); - ret =3D 0; - goto cleanup; - } - if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, mon, true) < 0) goto cleanup; =20 @@ -4266,251 +4241,75 @@ virQEMUCapsInitQMPMonitorTCG(virQEMUCapsPtr qemuCa= ps ATTRIBUTE_UNUSED, } =20 =20 -typedef struct _virQEMUCapsInitQMPCommand virQEMUCapsInitQMPCommand; -typedef virQEMUCapsInitQMPCommand *virQEMUCapsInitQMPCommandPtr; -struct _virQEMUCapsInitQMPCommand { - char *binary; - uid_t runUid; - gid_t runGid; - char **qmperr; - char *monarg; - char *monpath; - char *pidfile; - virCommandPtr cmd; - qemuMonitorPtr mon; - virDomainChrSourceDef config; - pid_t pid; - virDomainObjPtr vm; -}; - - -static void -virQEMUCapsInitQMPCommandAbort(virQEMUCapsInitQMPCommandPtr cmd) -{ - if (cmd->mon) - virObjectUnlock(cmd->mon); - qemuMonitorClose(cmd->mon); - cmd->mon =3D NULL; - - virCommandAbort(cmd->cmd); - virCommandFree(cmd->cmd); - cmd->cmd =3D NULL; - - if (cmd->monpath) - unlink(cmd->monpath); - - virDomainObjEndAPI(&cmd->vm); - - if (cmd->pid !=3D 0) { - char ebuf[1024]; - - VIR_DEBUG("Killing QMP caps process %lld", (long long)cmd->pid); - if (virProcessKill(cmd->pid, SIGKILL) < 0 && errno !=3D ESRCH) - VIR_ERROR(_("Failed to kill process %lld: %s"), - (long long)cmd->pid, - virStrerror(errno, ebuf, sizeof(ebuf))); - - VIR_FREE(*cmd->qmperr); - } - if (cmd->pidfile) - unlink(cmd->pidfile); - cmd->pid =3D 0; -} - - -static void -virQEMUCapsInitQMPCommandFree(virQEMUCapsInitQMPCommandPtr cmd) -{ - if (!cmd) - return; - - virQEMUCapsInitQMPCommandAbort(cmd); - VIR_FREE(cmd->binary); - VIR_FREE(cmd->monpath); - VIR_FREE(cmd->monarg); - VIR_FREE(cmd->pidfile); - VIR_FREE(cmd); -} - - -static virQEMUCapsInitQMPCommandPtr -virQEMUCapsInitQMPCommandNew(char *binary, - const char *libDir, - uid_t runUid, - gid_t runGid, - char **qmperr) -{ - virQEMUCapsInitQMPCommandPtr cmd =3D NULL; - - if (VIR_ALLOC(cmd) < 0) - goto error; - - if (VIR_STRDUP(cmd->binary, binary) < 0) - goto error; - - cmd->runUid =3D runUid; - cmd->runGid =3D runGid; - cmd->qmperr =3D qmperr; - - /* the ".sock" sufix is important to avoid a possible clash with a qemu - * domain called "capabilities" - */ - if (virAsprintf(&cmd->monpath, "%s/%s", libDir, - "capabilities.monitor.sock") < 0) - goto error; - if (virAsprintf(&cmd->monarg, "unix:%s,server,nowait", cmd->monpath) <= 0) - goto error; - - /* ".pidfile" suffix is used rather than ".pid" to avoid a possible cl= ash - * with a qemu domain called "capabilities" - * Normally we'd use runDir for pid files, but because we're using - * -daemonize we need QEMU to be allowed to create them, rather - * than libvirtd. So we're using libDir which QEMU can write to - */ - if (virAsprintf(&cmd->pidfile, "%s/%s", libDir, "capabilities.pidfile"= ) < 0) - goto error; - - virPidFileForceCleanupPath(cmd->pidfile); - - cmd->config.type =3D VIR_DOMAIN_CHR_TYPE_UNIX; - cmd->config.data.nix.path =3D cmd->monpath; - cmd->config.data.nix.listen =3D false; - - return cmd; - - error: - virQEMUCapsInitQMPCommandFree(cmd); - return NULL; -} - - -/* Returns -1 on fatal error, - * 0 on success, - * 1 when probing QEMU failed - */ static int -virQEMUCapsInitQMPCommandRun(virQEMUCapsInitQMPCommandPtr cmd, - bool forceTCG) +virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, + const char *libDir, + uid_t runUid, + gid_t runGid) { - virDomainXMLOptionPtr xmlopt =3D NULL; - const char *machine; - int status =3D 0; int ret =3D -1; + virDomainObjPtr dom =3D NULL; + virDomainObjPtr dom_kvm =3D NULL; + qemuMonitorPtr mon =3D NULL; + qemuMonitorPtr mon_kvm =3D NULL; + bool forceTCG =3D false; =20 - if (forceTCG) - machine =3D "none,accel=3Dtcg"; - else - machine =3D "none,accel=3Dkvm:tcg"; - - VIR_DEBUG("Try to probe capabilities of '%s' via QMP, machine %s", - cmd->binary, machine); + VIR_DEBUG("qemuCaps->binary=3D%s, libDir=3D%s, runUid=3D%u, runGid=3D%= u ", + NULLSTR(qemuCaps->binary), NULLSTR(libDir), runUid, runGid); =20 - /* - * We explicitly need to use -daemonize here, rather than - * virCommandDaemonize, because we need to synchronize - * with QEMU creating its monitor socket API. Using - * daemonize guarantees control won't return to libvirt - * until the socket is present. - */ - cmd->cmd =3D virCommandNewArgList(cmd->binary, - "-S", - "-no-user-config", - "-nodefaults", - "-nographic", - "-machine", machine, - "-qmp", cmd->monarg, - "-pidfile", cmd->pidfile, - "-daemonize", - NULL); - virCommandAddEnvPassCommon(cmd->cmd); - virCommandClearCaps(cmd->cmd); - virCommandSetGID(cmd->cmd, cmd->runGid); - virCommandSetUID(cmd->cmd, cmd->runUid); - - virCommandSetErrorBuffer(cmd->cmd, cmd->qmperr); - - /* Log, but otherwise ignore, non-zero status. */ - if (virCommandRun(cmd->cmd, &status) < 0) + if (!(dom =3D qmpDomainObjNew(qemuCaps->binary, forceTCG, libDir, runU= id, runGid))) goto cleanup; =20 - if (status !=3D 0) { - VIR_DEBUG("QEMU %s exited with status %d: %s", - cmd->binary, status, *cmd->qmperr); - goto ignore; - } + if (qemuProcessStartQmp(dom) < 0) + goto cleanup; =20 - if (virPidFileReadPath(cmd->pidfile, &cmd->pid) < 0) { - VIR_DEBUG("Failed to read pidfile %s", cmd->pidfile); - goto ignore; + if (!(mon =3D QMP_DOMAIN_MONITOR(dom))) { + ret =3D 0; /* Failure probing QEMU not considered error case */ + goto cleanup; } =20 - if (!(xmlopt =3D virDomainXMLOptionNew(NULL, NULL, NULL, NULL, NULL)) = || - !(cmd->vm =3D virDomainObjNew(xmlopt))) + /* Pull capabilities from QEMU */ + if (virQEMUCapsInitQMPMonitor(qemuCaps, mon) < 0) goto cleanup; =20 - cmd->vm->pid =3D cmd->pid; - - if (!(cmd->mon =3D qemuMonitorOpen(cmd->vm, &cmd->config, true, true, - 0, &callbacks, NULL))) - goto ignore; - - virObjectLock(cmd->mon); - - ret =3D 0; - - cleanup: - if (!cmd->mon) - virQEMUCapsInitQMPCommandAbort(cmd); - virObjectUnref(xmlopt); - - return ret; - - ignore: - ret =3D 1; - goto cleanup; -} - - -static int -virQEMUCapsInitQMP(virQEMUCapsPtr qemuCaps, - const char *libDir, - uid_t runUid, - gid_t runGid, - char **qmperr) -{ - virQEMUCapsInitQMPCommandPtr cmd =3D NULL; - int ret =3D -1; - int rc; + /* Pull capabilities again if KVM supported */ + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) { =20 - if (!(cmd =3D virQEMUCapsInitQMPCommandNew(qemuCaps->binary, libDir, - runUid, runGid, qmperr))) - goto cleanup; + qemuProcessStopQmp(dom); + virDomainObjEndAPI(&dom); =20 - if ((rc =3D virQEMUCapsInitQMPCommandRun(cmd, false)) !=3D 0) { - if (rc =3D=3D 1) - ret =3D 0; - goto cleanup; - } + forceTCG =3D true; + dom_kvm =3D qmpDomainObjNew(qemuCaps->binary, forceTCG, libDir, ru= nUid, runGid); =20 - if (virQEMUCapsInitQMPMonitor(qemuCaps, cmd->mon) < 0) - goto cleanup; + if (qemuProcessStartQmp(dom_kvm) < 0) + goto cleanup; =20 - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) { - virQEMUCapsInitQMPCommandAbort(cmd); - if ((rc =3D virQEMUCapsInitQMPCommandRun(cmd, true)) !=3D 0) { - if (rc =3D=3D 1) - ret =3D 0; + if (!(mon_kvm =3D QMP_DOMAIN_MONITOR(dom_kvm))) { + ret =3D 0; /* Failure probing QEMU not considered error case */ goto cleanup; } =20 - if (virQEMUCapsInitQMPMonitorTCG(qemuCaps, cmd->mon) < 0) + if (virQEMUCapsInitQMPMonitorTCG(qemuCaps, mon_kvm) < 0) goto cleanup; } =20 ret =3D 0; =20 cleanup: - virQEMUCapsInitQMPCommandFree(cmd); + if (!mon) { + char *err =3D QMP_DOMAIN_ERROR(dom) ? QMP_DOMAIN_ERROR(dom) : _("u= nknown error"); + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to probe QEMU binary with QMP: %s"), err); + } + + qemuProcessStopQmp(dom); + virDomainObjEndAPI(&dom); + qemuProcessStopQmp(dom_kvm); + virDomainObjEndAPI(&dom_kvm); + + VIR_DEBUG("ret=3D%i", ret); + return ret; } =20 @@ -4546,7 +4345,6 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch, { virQEMUCapsPtr qemuCaps; struct stat sb; - char *qmperr =3D NULL; =20 if (!(qemuCaps =3D virQEMUCapsNew())) goto error; @@ -4573,15 +4371,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch, goto error; } =20 - if (virQEMUCapsInitQMP(qemuCaps, libDir, runUid, runGid, &qmperr) < 0)= { - virQEMUCapsLogProbeFailure(binary); - goto error; - } - - if (!qemuCaps->usedQMP) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to probe QEMU binary with QMP: %s"), - qmperr ? qmperr : _("unknown error")); + if (virQEMUCapsInitQMP(qemuCaps, libDir, runUid, runGid) < 0 || + !qemuCaps->usedQMP) { virQEMUCapsLogProbeFailure(binary); goto error; } @@ -4600,7 +4391,6 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch, } =20 cleanup: - VIR_FREE(qmperr); return qemuCaps; =20 error: diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c64b3ad38a..507710d241 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -813,12 +813,12 @@ qemuMonitorOpenInternal(virDomainObjPtr vm, { qemuMonitorPtr mon; =20 - if (!cb->eofNotify) { + if (cb && !cb->eofNotify) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("EOF notify callback must be supplied")); return NULL; } - if (!cb->errorNotify) { + if (cb && !cb->errorNotify) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Error notify callback must be supplied")); return NULL; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 29b0ba1590..c8a34fc37e 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -8068,3 +8068,401 @@ qemuProcessReconnectAll(virQEMUDriverPtr driver) struct qemuProcessReconnectData data =3D {.driver =3D driver}; virDomainObjListForEach(driver->domains, qemuProcessReconnectHelper, &= data); } + + +static void * +qmpDomainObjPrivateAlloc(void *opaque) +{ + qmpDomainObjPrivatePtr priv; + + if (VIR_ALLOC(priv) < 0) + return NULL; + + VIR_DEBUG("priv=3D%p opaque=3D%p", priv, opaque); + + return priv; +} + + +static void +qmpDomainObjPrivateFree(void *data) +{ + qmpDomainObjPrivatePtr priv =3D data; + + VIR_DEBUG("priv=3D%p, priv->mon=3D%p", priv, (priv ? priv->mon : NULL)= ); + + if (!priv) + return; + + /* This should never be non-NULL if we get here, but just in case... */ + if (priv->mon) { + VIR_ERROR(_("Unexpected QEMU monitor still active during domain de= letion")); + qemuMonitorClose(priv->mon); + priv->mon =3D NULL; + } + + VIR_FREE(priv->libDir); + VIR_FREE(priv->monpath); + VIR_FREE(priv->monarg); + VIR_FREE(priv->pidfile); + VIR_FREE(priv->qmperr); + VIR_FREE(priv); +} + +/** + * qmpDomainObjNew: + * @binary: Qemu binary + * @forceTCG: Force TCG mode if true + * @libDir: Directory for process and connection artifacts + * @runUid: UserId for Qemu Process + * @runGid: GroupId for Qemu Process + * + * Allocate and initialize domain structure encapsulating + * QEMU Process state and monitor connection to QEMU + * for completing QMP Queries. + */ +virDomainObjPtr +qmpDomainObjNew(const char *binary, + bool forceTCG, + const char *libDir, + uid_t runUid, gid_t runGid) +{ + virDomainXMLOptionPtr xmlopt =3D NULL; + virDomainObjPtr ret =3D NULL; + virDomainObjPtr dom =3D NULL; + qmpDomainObjPrivatePtr priv =3D NULL; + + virDomainXMLPrivateDataCallbacks callbacks =3D { + .alloc =3D qmpDomainObjPrivateAlloc, + .free =3D qmpDomainObjPrivateFree, + }; + + VIR_DEBUG("exec=3D%s, libDir=3D%s, runUid=3D%u, runGid=3D%u ", + NULLSTR(binary), NULLSTR(libDir), runUid, runGid); + + xmlopt =3D virDomainXMLOptionNew(NULL, + &callbacks, + NULL, NULL, NULL); + + if (!xmlopt || + !(dom =3D virDomainObjNew(xmlopt))) + goto cleanup; + + if (VIR_ALLOC(dom->def) < 0 || + VIR_STRDUP(dom->def->name, "QmpQuery") < 0 || + VIR_STRDUP(dom->def->emulator, binary) < 0) + goto cleanup; + + priv =3D QMP_DOMAIN_PRIVATE(dom); + + priv->forceTCG =3D forceTCG; + + if (VIR_STRDUP(priv->libDir, libDir) < 0) + goto cleanup; + + priv->runUid =3D runUid; + priv->runGid =3D runGid; + + VIR_STEAL_PTR(ret, dom); + + cleanup: + virDomainObjEndAPI(&dom); + return ret; +} + + +/* Initialize configuration and paths prior to starting QEMU + */ +static int +qemuProcessInitQmp(virDomainObjPtr dom) +{ + int ret =3D -1; + qmpDomainObjPrivatePtr priv =3D QMP_DOMAIN_PRIVATE(dom); + + /* Allow multiple QEMU Procs and make clashes very unlikely */ + unsigned int seed =3D time(NULL); + dom->def->id =3D rand_r(&seed) % 1000000; + + VIR_DEBUG("Beginning VM startup process" + "dom=3D%p name=3D%s emulator=3D%s, id=3D%d", + dom, dom->def->name, dom->def->emulator, dom->def->id); + + /* the ".sock" sufix is important to avoid a possible clash with a qemu + * domain called "capabilities" + */ + if (virAsprintf(&priv->monpath, "%s/%s.%d.%s", + priv->libDir, dom->def->name, dom->def->id, + "monitor.sock") < 0) + goto cleanup; + + if (virAsprintf(&priv->monarg, "unix:%s,server,nowait", priv->monpath)= < 0) + goto cleanup; + + /* Normally we'd use runDir for pid files, but because we're using + * -daemonize we need QEMU to be allowed to create them, rather + * than libvirtd. So we're using libDir which QEMU can write to + */ + if (virAsprintf(&priv->pidfile, "%s/%s.%d.%s", + priv->libDir, dom->def->name, dom->def->id, + "pidfile") < 0) + goto cleanup; + + virPidFileForceCleanupPath(priv->pidfile); + + ret =3D 0; + + cleanup: + VIR_DEBUG("ret=3D%i", ret); + return ret; +} + + +/* Launch QEMU Process + * + * Returns -1 on fatal error, + * 0 on success, + * 1 when probing QEMU failed + */ +static int +qemuProcessLaunchQmp(virDomainObjPtr dom) +{ + const char *machine; + int status =3D 0; + int ret =3D -1; + + qmpDomainObjPrivatePtr priv =3D QMP_DOMAIN_PRIVATE(dom); + + VIR_DEBUG("dom=3D%p, emulator=3D%s, id=3D%d", + dom, NULLSTR(dom->def->emulator), dom->def->id); + + if (priv->forceTCG) { + machine =3D "none,accel=3Dtcg"; + } else { + machine =3D "none,accel=3Dkvm:tcg"; + } + + VIR_DEBUG("Try to probe capabilities of '%s' via QMP, machine %s", + NULLSTR(dom->def->emulator), machine); + + /* We explicitly need to use -daemonize here, rather than + * virCommandDaemonize, because we need to synchronize + * with QEMU creating its monitor socket API. Using + * daemonize guarantees control won't return to libvirt + * until the socket is present. + */ + priv->cmd =3D virCommandNewArgList(dom->def->emulator, + "-S", + "-no-user-config", + "-nodefaults", + "-nographic", + "-machine", machine, + "-qmp", priv->monarg, + "-pidfile", priv->pidfile, + "-daemonize", + NULL); + + virCommandAddEnvPassCommon(priv->cmd); + virCommandClearCaps(priv->cmd); + virCommandSetGID(priv->cmd, priv->runGid); + virCommandSetUID(priv->cmd, priv->runUid); + + virCommandSetErrorBuffer(priv->cmd, &(priv->qmperr)); + + if (virCommandRun(priv->cmd, &status) < 0) { + VIR_DEBUG("QEMU %s dom=3D%p name=3D%s failed to spawn", + dom->def->emulator, dom, dom->def->name); + goto cleanup; + } + + /* Log, but otherwise ignore, non-zero status. */ + if (status !=3D 0) { + VIR_DEBUG("QEMU %s exited with status %d: %s", + dom->def->emulator, status, priv->qmperr); + goto ignore; + } + + if (virPidFileReadPath(priv->pidfile, &dom->pid) < 0) { + VIR_DEBUG("Failed to read pidfile %s", priv->pidfile); + goto ignore; + } + + ret =3D 0; + + cleanup: + return ret; + + ignore: + ret =3D 1; + goto cleanup; +} + + +/* Connect Monitor to QEMU Process + * + * Returns -1 on fatal error, + * 0 on success, + * 1 when probing QEMU failed + */ +static int +qemuConnectMonitorQmp(virDomainObjPtr dom) +{ + int ret =3D 0; + + qemuMonitorPtr mon =3D NULL; + virDomainChrSourceDef monConfig; + unsigned long long timeout =3D 0; + bool retry =3D true; + bool enableJson =3D true; + qemuMonitorCallbacksPtr monCallbacks =3D NULL; + + qmpDomainObjPrivatePtr priv =3D QMP_DOMAIN_PRIVATE(dom); + + VIR_DEBUG("emulator=3D%s, dom->pid=3D%lld", + dom->def->emulator, (long long)dom->pid); + + priv->mon =3D NULL; + + if (!dom->pid) + goto ignore; + + monConfig.type =3D VIR_DOMAIN_CHR_TYPE_UNIX; + monConfig.data.nix.path =3D priv->monpath; + monConfig.data.nix.listen =3D false; + + /* Hold an extra reference because we can't allow dom to be + * deleted until the monitor gets its own reference. */ + virObjectRef(dom); + virObjectUnlock(dom); + + mon =3D qemuMonitorOpen(dom, + &monConfig, + enableJson, + retry, + timeout, + monCallbacks, + NULL); + + virObjectLock(dom); + virObjectUnref(dom); + + if (!mon) { + VIR_INFO("Failed to connect monitor for %s", dom->def->name); + goto ignore; + } + + VIR_STEAL_PTR(priv->mon, mon); + + /* Exit capabilities negotiation mode and enter QEMU command mode + * by issuing qmp_capabilities command to QEMU */ + if (qemuMonitorSetCapabilities(priv->mon) < 0) { + VIR_DEBUG("Failed to set monitor capabilities %s", + virGetLastErrorMessage()); + goto ignore; + } + + ret =3D 0; + + cleanup: + VIR_DEBUG("ret=3D%i", ret); + return ret; + + ignore: + ret =3D 1; + goto cleanup; +} + + +/** + * qemuProcessStartQmp: + * @dom: Qmp Specific Domain storing Process and Connection State + * + * Start and connect to QEMU binary so QMP queries can be made. + * + * Usage: + * dom =3D qmpDomainObjNew(binary, forceTCG, libDir, runUid, runGid); + * qemuProcessStartQmp(dom); + * mon =3D QMP_DOMAIN_MONITOR(dom); + * ** Send QMP Queries to QEMU using monitor ** + * qemuProcessStopQmp(dom); + * virDomainObjEndAPI(&dom); + * + * QEMU probing failure is not an error case (negative return value.) + * Check monitor before using. + * + * Resources remain allocated until qemuProcessStopQmp and virDomainObjEnd= API + * are called (even in failure cases.) Error string (dom->priv->qmperr) + * remains valid until virDomainObjEndAPI(&dom) is called. + */ +int +qemuProcessStartQmp(virDomainObjPtr dom) +{ + int ret =3D -1; + + VIR_DEBUG("dom=3D%p name=3D%s emulator=3D%s", + dom, dom->def->name, dom->def->emulator); + + if (qemuProcessInitQmp(dom) < 0) + goto stop; + + if (qemuProcessLaunchQmp(dom) < 0) + goto stop; + + if (qemuConnectMonitorQmp(dom) < 0) + goto stop; + + ret =3D 0; + + cleanup: + VIR_DEBUG("ret=3D%i", ret); + return ret; + + stop: + qemuProcessStopQmp(dom); + goto cleanup; +} + +/** + * qemuProcessStop: + * @dom: Qmp Specific Domain storing Process and Connection State + * + * Stop Monitor Connection and QEMU Process + */ +void qemuProcessStopQmp(virDomainObjPtr dom) +{ + if (!dom) + return; + + qmpDomainObjPrivatePtr priv =3D QMP_DOMAIN_PRIVATE(dom); + + VIR_DEBUG("Shutting down dom=3D%p name=3D%s emulator=3D%s id->%d pid= =3D%lld", + dom, dom->def->name, dom->def->emulator, dom->def->id, + (long long)dom->pid); + + if (priv->mon) { + virObjectUnlock(priv->mon); + qemuMonitorClose(priv->mon); + priv->mon =3D NULL; + } + + virCommandAbort(priv->cmd); + virCommandFree(priv->cmd); + priv->cmd =3D NULL; + + if (priv->monpath) + ignore_value(unlink(priv->monpath)); + + if (dom->pid !=3D 0) { + char ebuf[1024]; + + VIR_DEBUG("Killing QMP caps process %lld", (long long)dom->pid); + if (virProcessKill(dom->pid, SIGKILL) < 0 && errno !=3D ESRCH) + VIR_ERROR(_("Failed to kill process %lld: %s"), + (long long)dom->pid, + virStrerror(errno, ebuf, sizeof(ebuf))); + } + + if (priv->pidfile) + unlink(priv->pidfile); + + dom->pid =3D 0; +} diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index c2f7c2b5d2..7c5fd32538 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -74,6 +74,36 @@ int qemuProcessBeginJob(virQEMUDriverPtr driver, void qemuProcessEndJob(virQEMUDriverPtr driver, virDomainObjPtr vm); =20 +typedef struct _qmpDomainObjPrivate qmpDomainObjPrivate; +typedef qmpDomainObjPrivate *qmpDomainObjPrivatePtr; +struct _qmpDomainObjPrivate { + char *libDir; + uid_t runUid; + gid_t runGid; + char *qmperr; /* qemu proc stderr */ + char *monarg; // "unix:{priv->monpath},server,nowait" + char *monpath; // {libDir}/capabilities.monitor.sock + char *pidfile; + virCommandPtr cmd; + qemuMonitorPtr mon; + bool forceTCG; +}; + +virDomainObjPtr qmpDomainObjNew(const char *binary, + bool forceTCG, + const char *libDir, + uid_t runUid, + gid_t runGid); + +#define QMP_DOMAIN_PRIVATE(dom) \ + ((qmpDomainObjPrivatePtr) (dom)->privateData) + +#define QMP_DOMAIN_MONITOR(dom) \ + ((qemuMonitorPtr) (QMP_DOMAIN_PRIVATE(dom) ? QMP_DOMAIN_PRIVATE(dom)->m= on : NULL)) + +#define QMP_DOMAIN_ERROR(dom) \ + ((char *) (QMP_DOMAIN_PRIVATE(dom) ? QMP_DOMAIN_PRIVATE(dom)->qmperr: N= ULL)) + typedef enum { VIR_QEMU_PROCESS_START_COLD =3D 1 << 0, VIR_QEMU_PROCESS_START_PAUSED =3D 1 << 1, @@ -97,6 +127,9 @@ int qemuProcessStart(virConnectPtr conn, virNetDevVPortProfileOp vmop, unsigned int flags); =20 +int +qemuProcessStartQmp(virDomainObjPtr dom); + virCommandPtr qemuProcessCreatePretendCmd(virQEMUDriverPtr driver, virDomainObjPtr vm, const char *migrateURI, @@ -155,6 +188,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, qemuDomainAsyncJob asyncJob, unsigned int flags); =20 +void qemuProcessStopQmp(virDomainObjPtr dom); + int qemuProcessAttach(virConnectPtr conn, virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c index 8fe5a55e1d..ea4671739b 100644 --- a/tests/qemucapabilitiestest.c +++ b/tests/qemucapabilitiestest.c @@ -58,6 +58,9 @@ testQemuCaps(const void *opaque) if (!(mon =3D qemuMonitorTestNewFromFileFull(repliesFile, &data->drive= r, NULL))) goto cleanup; =20 + if (qemuMonitorSetCapabilities(qemuMonitorTestGetMonitor(mon)) < 0) + goto cleanup; + if (!(capsActual =3D virQEMUCapsNew()) || virQEMUCapsInitQMPMonitor(capsActual, qemuMonitorTestGetMonitor(mon)) < 0) @@ -65,6 +68,10 @@ testQemuCaps(const void *opaque) =20 if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM)) { qemuMonitorResetCommandID(qemuMonitorTestGetMonitor(mon)); + + if (qemuMonitorSetCapabilities(qemuMonitorTestGetMonitor(mon)) < 0) + goto cleanup; + if (virQEMUCapsInitQMPMonitorTCG(capsActual, qemuMonitorTestGetMonitor(mon)) <= 0) goto cleanup; --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Apr 27 21:50:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 153808364426657.29895705401907; Thu, 27 Sep 2018 14:27:24 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5EB7B30832CD; Thu, 27 Sep 2018 21:27:22 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 2BA8C2010D16; Thu, 27 Sep 2018 21:27:22 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id D8004181A130; Thu, 27 Sep 2018 21:27:21 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLR1OO005781 for ; Thu, 27 Sep 2018 17:27:01 -0400 Received: by smtp.corp.redhat.com (Postfix) id 1080D5D776; Thu, 27 Sep 2018 21:27:01 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F9705D6A9; Thu, 27 Sep 2018 21:27:00 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:44 -0500 Message-Id: <20180927212645.20758-6-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 5/6] qemu_driver: BaselineHypervisorCPU support for S390 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.25 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Thu, 27 Sep 2018 21:27:22 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Libvirt can compute baseline hypervisor cpu from list of S390 cpu models by using QEMU QMP messages to compute baseline within QEMU. QEMU only baselines one pair of CPU models per query so a sequence of multiple QMP queries are needed if more than two CPU models are baselined. Full expansion of baseline S390 model supported using QEMU QMP messages to compute expansion within QEMU. Introduces qemuMonitorCPUModelInfoRemovePropByBoolValue to remove props by value as required to convert between cpu model property lists that indicate if property is or isn't include in model with true / false value and the form of cpu model property lists that only enumerate properties that are actually included in the model. Introduces functions for virCPUDef / qemuMonitorCPUModelInfo conversion. Signed-off-by: Chris Venteicher --- src/qemu/qemu_capabilities.c | 128 +++++++++++++++++++++++++------ src/qemu/qemu_capabilities.h | 4 + src/qemu/qemu_driver.c | 143 +++++++++++++++++++++++++++++++++-- src/qemu/qemu_monitor.c | 41 ++++++++++ src/qemu/qemu_monitor.h | 10 +++ src/qemu/qemu_monitor_json.c | 60 +++++++++++++++ src/qemu/qemu_monitor_json.h | 7 ++ 7 files changed, 365 insertions(+), 28 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5b1e4f1bbd..c5bf04993b 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2785,7 +2785,8 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, virCPUDefPtr cpu, bool migratable) { - size_t i; + virCPUDefPtr tmp =3D NULL; + int ret =3D -1; =20 if (!modelInfo) { if (type =3D=3D VIR_DOMAIN_VIRT_KVM) { @@ -2798,32 +2799,18 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, return 2; } =20 - if (VIR_STRDUP(cpu->model, modelInfo->name) < 0 || - VIR_ALLOC_N(cpu->features, modelInfo->nprops) < 0) - return -1; - - cpu->nfeatures_max =3D modelInfo->nprops; - cpu->nfeatures =3D 0; - - for (i =3D 0; i < modelInfo->nprops; i++) { - virCPUFeatureDefPtr feature =3D cpu->features + cpu->nfeatures; - qemuMonitorCPUPropertyPtr prop =3D modelInfo->props + i; + if (!(tmp =3D virQEMUCapsCPUModelInfoToCPUDef(migratable, modelInfo))) + goto cleanup; =20 - if (prop->type !=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) - continue; + /* Free original then copy over model, vendor, vendor_id and features = */ + virCPUDefStealModel(cpu, tmp, true); =20 - if (VIR_STRDUP(feature->name, prop->name) < 0) - return -1; + ret =3D 0; =20 - if (!prop->value.boolean || - (migratable && prop->migratable =3D=3D VIR_TRISTATE_BOOL_NO)) - feature->policy =3D VIR_CPU_FEATURE_DISABLE; - else - feature->policy =3D VIR_CPU_FEATURE_REQUIRE; - cpu->nfeatures++; - } + cleanup: + virCPUDefFree(tmp); =20 - return 0; + return ret; } =20 =20 @@ -3620,6 +3607,101 @@ virQEMUCapsLoadCache(virArch hostArch, return ret; } =20 +/* virCPUDef model =3D> qemuMonitorCPUModelInfo name + * virCPUDef features =3D> qemuMonitorCPUModelInfo boolean properties */ +qemuMonitorCPUModelInfoPtr +virQEMUCapsCPUModelInfoFromCPUDef(const virCPUDef *cpuDef) +{ + size_t i; + qemuMonitorCPUModelInfoPtr cpuModel =3D NULL; + qemuMonitorCPUModelInfoPtr ret =3D NULL; + + if (!cpuDef || (VIR_ALLOC(cpuModel) < 0)) + goto cleanup; + + VIR_DEBUG("cpuDef->model =3D %s", NULLSTR(cpuDef->model)); + + if (VIR_STRDUP(cpuModel->name, cpuDef->model) < 0 || + VIR_ALLOC_N(cpuModel->props, cpuDef->nfeatures) < 0) + goto cleanup; + + cpuModel->nprops =3D 0; + + for (i =3D 0; i < cpuDef->nfeatures; i++) { + qemuMonitorCPUPropertyPtr prop =3D &(cpuModel->props[cpuModel->npr= ops]); + virCPUFeatureDefPtr feature =3D &(cpuDef->features[i]); + + if (!(feature->name) || + VIR_STRDUP(prop->name, feature->name) < 0) + goto cleanup; + + prop->type =3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN; + + prop->value.boolean =3D feature->policy =3D=3D -1 || /* policy und= efined */ + feature->policy =3D=3D VIR_CPU_FEATURE_FORCE= || + feature->policy =3D=3D VIR_CPU_FEATURE_REQUI= RE; + + cpuModel->nprops++; + } + + VIR_STEAL_PTR(ret, cpuModel); + + cleanup: + qemuMonitorCPUModelInfoFree(cpuModel); + return ret; +} + + +/* qemuMonitorCPUModelInfo name =3D> virCPUDef model + * qemuMonitorCPUModelInfo boolean properties =3D> virCPUDef features + * + * migratable true: mark non-migratable features as disabled + * false: allow all features as required + */ +virCPUDefPtr +virQEMUCapsCPUModelInfoToCPUDef(bool migratable, qemuMonitorCPUModelInfoPt= r model) +{ + virCPUDefPtr cpu =3D NULL; + virCPUDefPtr ret =3D NULL; + size_t i; + + if (!model || VIR_ALLOC(cpu) < 0) + goto cleanup; + + VIR_DEBUG("model->name=3D %s", NULLSTR(model->name)); + + if (VIR_STRDUP(cpu->model, model->name) < 0 || + VIR_ALLOC_N(cpu->features, model->nprops) < 0) + goto cleanup; + + cpu->nfeatures_max =3D model->nprops; + cpu->nfeatures =3D 0; + + for (i =3D 0; i < model->nprops; i++) { + virCPUFeatureDefPtr feature =3D cpu->features + cpu->nfeatures; + qemuMonitorCPUPropertyPtr prop =3D model->props + i; + + if (prop->type !=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) + continue; + + if (VIR_STRDUP(feature->name, prop->name) < 0) + goto cleanup; + + if (!prop->value.boolean || + (migratable && prop->migratable =3D=3D VIR_TRISTATE_BOOL_NO)) + feature->policy =3D VIR_CPU_FEATURE_DISABLE; + else + feature->policy =3D VIR_CPU_FEATURE_REQUIRE; + + cpu->nfeatures++; + } + + VIR_STEAL_PTR(ret, cpu); + + cleanup: + virCPUDefFree(cpu); + return ret; +} =20 static void virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps, diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 934620ed31..98ccec154e 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -571,6 +571,10 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemu= Caps, void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps, const char *machineType); =20 +qemuMonitorCPUModelInfoPtr virQEMUCapsCPUModelInfoFromCPUDef(const virCPUD= ef *cpuDef); +virCPUDefPtr virQEMUCapsCPUModelInfoToCPUDef(bool migratable, + qemuMonitorCPUModelInfoPtr mo= del); + virFileCachePtr virQEMUCapsCacheNew(const char *libDir, const char *cacheDir, uid_t uid, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b238309852..8db7d01660 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13406,6 +13406,77 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUT= E_UNUSED, return cpustr; } =20 +/* in: + * cpus[0]->model =3D "z14"; + * cpus[0]->features[0].name =3D "xxx"; + * cpus[0]->features[1].name =3D "yyy"; + * *** + * cpus[n]->model =3D "z13"; + * cpus[n]->features[0].name =3D "xxx"; + * cpus[n]->features[1].name =3D "yyy"; + * + * out: + * *baseline->model =3D "z13-base"; + * *baseline->features[0].name =3D "yyy"; + */ +static int +qemuConnectBaselineHypervisorCPUViaQEMU(qemuMonitorPtr mon, + virCPUDefPtr *cpus, + virCPUDefPtr *baseline) +{ + qemuMonitorCPUModelInfoPtr model_baseline =3D NULL; + qemuMonitorCPUModelInfoPtr new_model_baseline =3D NULL; + qemuMonitorCPUModelInfoPtr next_model =3D NULL; + bool migratable =3D true; + int ret =3D -1; + size_t i; + + *baseline =3D NULL; + + if (!cpus || !cpus[0]) { + virReportError(VIR_ERR_INVALID_ARG, "%s", _("no cpus")); + goto cleanup; + } + + for (i =3D 0; cpus[i]; i++) { /* cpus terminated by NULL element = */ + virCPUDefPtr cpu =3D cpus[i]; + + VIR_DEBUG("cpu[%lu]->model =3D %s", i, NULLSTR(cpu->model)); + + if (!(next_model =3D virQEMUCapsCPUModelInfoFromCPUDef(cpu))) + goto cleanup; + + if (i =3D=3D 0) { + model_baseline =3D next_model; + continue; + } + + if (qemuMonitorGetCPUModelBaseline(mon, model_baseline, + next_model, &new_model_baseline= ) < 0) + goto cleanup; + + qemuMonitorCPUModelInfoFree(model_baseline); + qemuMonitorCPUModelInfoFree(next_model); + + next_model =3D NULL; + + model_baseline =3D new_model_baseline; + } + + if (!(*baseline =3D virQEMUCapsCPUModelInfoToCPUDef(migratable, model_= baseline))) + goto cleanup; + + VIR_DEBUG("baseline->model =3D %s", (*baseline)->model); + + ret =3D 0; + + cleanup: + qemuMonitorCPUModelInfoFree(model_baseline); + qemuMonitorCPUModelInfoFree(next_model); + + return ret; +} + =20 static char * qemuConnectBaselineHypervisorCPU(virConnectPtr conn, @@ -13427,6 +13498,11 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr con= n, virCPUDefPtr cpu =3D NULL; char *cpustr =3D NULL; char **features =3D NULL; + bool forceTCG =3D false; + qemuMonitorCPUModelInfoPtr modelInfo =3D NULL; + qemuMonitorCPUModelInfoPtr expansion =3D NULL; + virDomainObjPtr dom =3D NULL; + qemuMonitorPtr mon =3D NULL; =20 virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES | VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL); @@ -13434,8 +13510,6 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr conn, if (virConnectBaselineHypervisorCPUEnsureACL(conn) < 0) goto cleanup; =20 - migratable =3D !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE); - if (!(cpus =3D virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_AUTO))) goto cleanup; =20 @@ -13448,6 +13522,20 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr con= n, if (!qemuCaps) goto cleanup; =20 + /* QEMU can enumerate non-migratable cpu model features for some archs= like x86 + * migratable =3D=3D true: ask for and include only migratable featur= es + * migratable =3D=3D false: ask for and include all features + */ + migratable =3D !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE); + + if (ARCH_IS_S390(arch)) { + /* QEMU for S390 arch only enumerates migratable features + * No reason to explicitly ask QEMU for or include non-migratable + * features + */ + migratable =3D true; + } + if (!(cpuModels =3D virQEMUCapsGetCPUDefinitions(qemuCaps, virttype)) = || cpuModels->nmodels =3D=3D 0) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, @@ -13472,6 +13560,20 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr con= n, if (!(cpu =3D virCPUBaseline(arch, cpus, ncpus, cpuModels, (const char **)features, migratable))) goto cleanup; + } else if (ARCH_IS_S390(arch)) { + const char *binary =3D virQEMUCapsGetBinary(qemuCaps); + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + + if (!(dom =3D qmpDomainObjNew(binary, forceTCG, cfg->libDir, cfg->= user, cfg->group))) + goto cleanup; + + if (qemuProcessStartQmp(dom) < 0) + goto cleanup; + + mon =3D QMP_DOMAIN_MONITOR(dom); + + if ((qemuConnectBaselineHypervisorCPUViaQEMU(mon, cpus, &cpu) < 0)= || !cpu) + goto cleanup; } else { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("computing baseline hypervisor CPU is not support= ed " @@ -13481,9 +13583,36 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr con= n, =20 cpu->fallback =3D VIR_CPU_FALLBACK_FORBID; =20 - if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) && - virCPUExpandFeatures(arch, cpu) < 0) - goto cleanup; + if (flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) { + if (ARCH_IS_X86(arch)) { + if (virCPUExpandFeatures(arch, cpu) < 0) + goto cleanup; + } else if (ARCH_IS_S390(arch)) { + if (!(modelInfo =3D virQEMUCapsCPUModelInfoFromCPUDef(cpu))) + goto cleanup; + + virCPUDefFree(cpu); + cpu =3D NULL; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANS= ION)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Feature Expansion not supported with thi= s QEMU binary")); + goto cleanup; + } + + if (qemuMonitorGetCPUModelExpansion(mon, + QEMU_MONITOR_CPU_MODEL_EXP= ANSION_FULL, + migratable, modelInfo, &ex= pansion) < 0) + goto cleanup; + + /* Expansion enumerates all features + * Baseline reply enumerates only in-model (true) features */ + qemuMonitorCPUModelInfoRemovePropByBoolValue(expansion, false); + + if (!(cpu =3D virQEMUCapsCPUModelInfoToCPUDef(migratable, expa= nsion))) + goto cleanup; + } + } =20 cpustr =3D virCPUDefFormat(cpu, NULL); =20 @@ -13492,6 +13621,10 @@ qemuConnectBaselineHypervisorCPU(virConnectPtr con= n, virCPUDefFree(cpu); virObjectUnref(qemuCaps); virStringListFree(features); + qemuMonitorCPUModelInfoFree(modelInfo); + qemuMonitorCPUModelInfoFree(expansion); + qemuProcessStopQmp(dom); + virDomainObjEndAPI(&dom); =20 return cpustr; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 507710d241..7045186c4e 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3801,6 +3801,47 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUMode= lInfo *orig) } =20 =20 +/* Squash CPU Model Info property list + * removing props of type boolean matching value */ +void +qemuMonitorCPUModelInfoRemovePropByBoolValue(qemuMonitorCPUModelInfoPtr mo= del, + bool value) +{ + qemuMonitorCPUPropertyPtr src; + qemuMonitorCPUPropertyPtr dst; + size_t i; + size_t dst_nprops =3D 0; + + for (i =3D 0; i < model->nprops; i++) { + src =3D &(model->props[i]); + dst =3D &(model->props[dst_nprops]); + + if (src->type =3D=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN && + src->value.boolean =3D=3D value) + continue; + + *dst =3D *src; + + dst_nprops++; + } + + model->nprops =3D dst_nprops; + + ignore_value(VIR_REALLOC_N_QUIET(model->props, dst_nprops)); +} + + +int +qemuMonitorGetCPUModelBaseline(qemuMonitorPtr mon, + qemuMonitorCPUModelInfoPtr model_a, + qemuMonitorCPUModelInfoPtr model_b, + qemuMonitorCPUModelInfoPtr *model_baseline) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetCPUModelBaseline(mon, model_a, model_b, model= _baseline); +} + int qemuMonitorCPUModelInfoBoolPropAdd(qemuMonitorCPUModelInfoPtr model, const char *prop_name, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d3efd37099..fad39945d3 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1053,6 +1053,16 @@ int qemuMonitorCPUModelInfoBoolPropAdd(qemuMonitorCP= UModelInfoPtr model, bool prop_value) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); =20 +void qemuMonitorCPUModelInfoRemovePropByBoolValue(qemuMonitorCPUModelInfoP= tr model, + bool value) + ATTRIBUTE_NONNULL(1); + +int qemuMonitorGetCPUModelBaseline(qemuMonitorPtr mon, + qemuMonitorCPUModelInfoPtr model_a, + qemuMonitorCPUModelInfoPtr model_b, + qemuMonitorCPUModelInfoPtr *model_basel= ine) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); + int qemuMonitorGetCommands(qemuMonitorPtr mon, char ***commands); int qemuMonitorGetEvents(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 4e6e220a8c..1cac3d2964 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5708,6 +5708,66 @@ qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr m= on, } =20 =20 +int +qemuMonitorJSONGetCPUModelBaseline(qemuMonitorPtr mon, + qemuMonitorCPUModelInfoPtr model_a, + qemuMonitorCPUModelInfoPtr model_b, + qemuMonitorCPUModelInfoPtr *model_basel= ine) +{ + int ret =3D -1; + virJSONValuePtr cmd =3D NULL; + virJSONValuePtr reply =3D NULL; + virJSONValuePtr data =3D NULL; + virJSONValuePtr modela =3D NULL; + virJSONValuePtr modelb =3D NULL; + virJSONValuePtr cpu_model =3D NULL; + + *model_baseline =3D NULL; + + if (!(modela =3D qemuMonitorJSONBuildCPUModelInfoToJSON(model_a)) || + !(modelb =3D qemuMonitorJSONBuildCPUModelInfoToJSON(model_b))) + goto cleanup; + + if (!(cmd =3D qemuMonitorJSONMakeCommand("query-cpu-model-baseline", + "a:modela", &modela, + "a:modelb", &modelb, + NULL))) + goto cleanup; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("QEMU doesn't support baseline or recognize model= %s or %s"), + model_a->name, + model_b->name); + goto cleanup; + } + + data =3D virJSONValueObjectGetObject(reply, "return"); + + if (!(cpu_model =3D virJSONValueObjectGetObject(data, "model"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-cpu-model-baseline reply data was missing = 'model'")); + goto cleanup; + } + + if (!(*model_baseline =3D qemuMonitorJSONBuildCPUModelInfoFromJSON(cpu= _model))) + goto cleanup; + + ret =3D 0; + + cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + virJSONValueFree(modela); + virJSONValueFree(modelb); + + return ret; +} + + int qemuMonitorJSONGetCommands(qemuMonitorPtr mon, char ***commands) { diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2d5679094e..e57f2e3590 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -372,6 +372,13 @@ int qemuMonitorJSONGetCPUModelExpansion(qemuMonitorPtr= mon, qemuMonitorCPUModelInfoPtr *expans= ion) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5); =20 +int qemuMonitorJSONGetCPUModelBaseline(qemuMonitorPtr mon, + qemuMonitorCPUModelInfoPtr model_a, + qemuMonitorCPUModelInfoPtr model_b, + qemuMonitorCPUModelInfoPtr *model_b= aseline) + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); + + int qemuMonitorJSONGetCommands(qemuMonitorPtr mon, char ***commands) ATTRIBUTE_NONNULL(2); --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Apr 27 21:50:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1538083650740503.3049459693726; Thu, 27 Sep 2018 14:27:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 133273097028; Thu, 27 Sep 2018 21:27:27 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id D40D130157BE; Thu, 27 Sep 2018 21:27:26 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 811F34A463; Thu, 27 Sep 2018 21:27:26 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w8RLR2xW005789 for ; Thu, 27 Sep 2018 17:27:02 -0400 Received: by smtp.corp.redhat.com (Postfix) id 16BA45D773; Thu, 27 Sep 2018 21:27:02 +0000 (UTC) Received: from cv1.lan (ovpn-125-53.rdu2.redhat.com [10.10.125.53]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4D9DD5D6A9; Thu, 27 Sep 2018 21:27:01 +0000 (UTC) From: Chris Venteicher To: libvir-list@redhat.com Date: Thu, 27 Sep 2018 16:26:45 -0500 Message-Id: <20180927212645.20758-7-cventeic@redhat.com> In-Reply-To: <20180927212645.20758-1-cventeic@redhat.com> References: <20180927212645.20758-1-cventeic@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Cc: walling@linux.ibm.com, Chris Venteicher , david@redhat.com Subject: [libvirt] [PATCH v3 6/6] qemu_monitor: Default props to migratable when expanding cpu model X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Thu, 27 Sep 2018 21:27:28 +0000 (UTC) X-ZohoMail: RDMRC_0 RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" QEMU only returns migratable props when expanding model unless explicitly told to also include non-migratable props. Props will be marked migratable when we are certain QEMU returned only migratable props resulting in consistent information and expansion output for s390 that is consistent with x86. After this change, immediately default prop->migratable =3D _YES for all props when we know QEMU only included migratable props in CPU Model. Set model->migratability =3D true when we have set prop->migratable. Signed-off-by: Chris Venteicher --- src/qemu/qemu_monitor.c | 53 ++++++++++++++- src/qemu/qemu_monitor.h | 7 +- .../caps_2.10.0.s390x.xml | 60 ++++++++--------- .../caps_2.11.0.s390x.xml | 58 ++++++++--------- .../caps_2.12.0.s390x.xml | 56 ++++++++-------- .../qemucapabilitiesdata/caps_2.8.0.s390x.xml | 32 +++++----- .../qemucapabilitiesdata/caps_2.9.0.s390x.xml | 34 +++++----- .../qemucapabilitiesdata/caps_3.0.0.s390x.xml | 64 +++++++++---------- 8 files changed, 210 insertions(+), 154 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7045186c4e..7a7c175f0a 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3698,12 +3698,31 @@ qemuMonitorGetCPUModelExpansion(qemuMonitorPtr mon, qemuMonitorCPUModelInfoPtr *expansion ) { + int ret =3D -1; + qemuMonitorCPUModelInfoPtr tmp; + VIR_DEBUG("type=3D%d model_name=3D%s migratable=3D%d", type, input->name, migratable); =20 + *expansion =3D NULL; + QEMU_CHECK_MONITOR(mon); =20 - return qemuMonitorJSONGetCPUModelExpansion(mon, type, migratable, inpu= t, expansion); + if ((ret =3D qemuMonitorJSONGetCPUModelExpansion(mon, type, migratable= , input, &tmp)) < 0) + goto cleanup; + + if (migratable) { + /* Only migratable props were included in expanded CPU model */ + *expansion =3D qemuMonitorCPUModelInfoCopyDefaultMigratable(tmp); + } else { + VIR_STEAL_PTR(*expansion, tmp); + } + + ret =3D 0; + + cleanup: + qemuMonitorCPUModelInfoFree(tmp); + return ret; } =20 =20 @@ -3801,6 +3820,38 @@ qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUMode= lInfo *orig) } =20 =20 +qemuMonitorCPUModelInfoPtr +qemuMonitorCPUModelInfoCopyDefaultMigratable(const qemuMonitorCPUModelInfo= *orig) +{ + qemuMonitorCPUModelInfoPtr ret =3D NULL; + qemuMonitorCPUModelInfoPtr tmp =3D NULL; + qemuMonitorCPUPropertyPtr prop =3D NULL; + size_t i; + + if (!(tmp =3D qemuMonitorCPUModelInfoCopy(orig))) + goto cleanup; + + for (i =3D 0; i < tmp->nprops; i++) { + prop =3D tmp->props + i; + + /* Default prop thats in cpu model (true) to migratable (_YES) + * unless prop already explicitly set not migratable (_NO) + */ + if (prop->type =3D=3D QEMU_MONITOR_CPU_PROPERTY_BOOLEAN && + prop->value.boolean && + prop->migratable !=3D VIR_TRISTATE_BOOL_NO) + prop->migratable =3D VIR_TRISTATE_BOOL_YES; + } + + tmp->migratability =3D true; /* prop->migratable =3D YES/NO for all CP= U props */ + + VIR_STEAL_PTR(ret, tmp); + + cleanup: + return ret; +} + + /* Squash CPU Model Info property list * removing props of type boolean matching value */ void diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index fad39945d3..7268bd7977 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1025,7 +1025,7 @@ struct _qemuMonitorCPUModelInfo { char *name; size_t nprops; qemuMonitorCPUPropertyPtr props; - bool migratability; + bool migratability; /* true if prop->migratable is YES/NO for all CPU = props */ }; =20 typedef enum { @@ -1048,6 +1048,11 @@ qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoNe= w(const char *name); qemuMonitorCPUModelInfoPtr qemuMonitorCPUModelInfoCopy(const qemuMonitorCPUModelInfo *orig); =20 +qemuMonitorCPUModelInfoPtr +qemuMonitorCPUModelInfoCopyDefaultMigratable(const qemuMonitorCPUModelInfo= *orig) + ATTRIBUTE_NONNULL(1); + + int qemuMonitorCPUModelInfoBoolPropAdd(qemuMonitorCPUModelInfoPtr model, const char *prop_name, bool prop_value) diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml b/tests/qemuc= apabilitiesdata/caps_2.10.0.s390x.xml index e000aac384..391bee4f06 100644 --- a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml @@ -118,36 +118,36 @@ 306247 s390x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml b/tests/qemuc= apabilitiesdata/caps_2.11.0.s390x.xml index 4eb8a39d94..d63f56be7d 100644 --- a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml @@ -125,35 +125,35 @@ 345099 s390x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml b/tests/qemuc= apabilitiesdata/caps_2.12.0.s390x.xml index 79320d5229..ea3bce232e 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml @@ -133,34 +133,34 @@ 374287 s390x - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemuca= pabilitiesdata/caps_2.8.0.s390x.xml index b010f731a5..858bc49918 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml @@ -108,22 +108,22 @@ 244554 s390x - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemuca= pabilitiesdata/caps_2.9.0.s390x.xml index 5a4371ab83..621036c914 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml @@ -112,23 +112,23 @@ 267973 s390x - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml b/tests/qemuca= pabilitiesdata/caps_3.0.0.s390x.xml index 3b5f9818a5..7bb42d211c 100644 --- a/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml @@ -135,38 +135,38 @@ 387601 s390x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list