From nobody Wed Jan 15 12:50:24 2025
Delivered-To: importer@patchew.org
Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied
by domain of lists.libvirt.org) client-ip=8.43.85.245;
envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org;
Authentication-Results: mx.zohomail.com;
spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain
of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org;
dmarc=fail(p=reject dis=none) header.from=linux.ibm.com
Return-Path:
Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by
mx.zohomail.com
with SMTPS id 1708608083187533.4408131019302;
Thu, 22 Feb 2024 05:21:23 -0800 (PST)
Received: by lists.libvirt.org (Postfix, from userid 996)
id 19E811E1C; Thu, 22 Feb 2024 08:21:22 -0500 (EST)
Received: from lists.libvirt.org (localhost [IPv6:::1])
by lists.libvirt.org (Postfix) with ESMTP id F203E1C08;
Thu, 22 Feb 2024 08:03:25 -0500 (EST)
Received: by lists.libvirt.org (Postfix, from userid 996)
id E8B891858; Thu, 22 Feb 2024 08:02:27 -0500 (EST)
Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com
[148.163.156.1])
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
(No client certificate requested)
by lists.libvirt.org (Postfix) with ESMTPS id 8ACFF1987
for ; Thu, 22 Feb 2024 08:02:24 -0500 (EST)
Received: from pps.filterd (m0356517.ppops.net [127.0.0.1])
by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id
41MCu9lm022075
for ; Thu, 22 Feb 2024 13:02:23 GMT
Received: from pps.reinject (localhost [127.0.0.1])
by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3we69h8wxp-1
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT)
for ; Thu, 22 Feb 2024 13:02:23 +0000
Received: from m0356517.ppops.net (m0356517.ppops.net [127.0.0.1])
by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 41MCvj7h027266
for ; Thu, 22 Feb 2024 13:02:22 GMT
Received: from ppma12.dal12v.mail.ibm.com
(dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220])
by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3we69h8ww9-1
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
Thu, 22 Feb 2024 13:02:22 +0000
Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1])
by ppma12.dal12v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id
41MBAQAr003596;
Thu, 22 Feb 2024 13:02:19 GMT
Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226])
by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 3wb74txhmy-1
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
Thu, 22 Feb 2024 13:02:19 +0000
Received: from smtpav01.fra02v.mail.ibm.com (smtpav01.fra02v.mail.ibm.com
[10.20.54.100])
by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id
41MD2Deu51118582
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);
Thu, 22 Feb 2024 13:02:15 GMT
Received: from smtpav01.fra02v.mail.ibm.com (unknown [127.0.0.1])
by IMSVA (Postfix) with ESMTP id CCF4920063;
Thu, 22 Feb 2024 13:02:11 +0000 (GMT)
Received: from smtpav01.fra02v.mail.ibm.com (unknown [127.0.0.1])
by IMSVA (Postfix) with ESMTP id 9564620071;
Thu, 22 Feb 2024 13:02:11 +0000 (GMT)
Received: from fiuczyvm.. (unknown [9.171.135.123])
by smtpav01.fra02v.mail.ibm.com (Postfix) with ESMTP;
Thu, 22 Feb 2024 13:02:11 +0000 (GMT)
X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org
X-Spam-Level:
X-Spam-Status: No,
score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS,
MAILING_LIST_MULTI,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,
T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no
version=3.4.4
From: Boris Fiuczynski
To: devel@lists.libvirt.org
Subject: [PATCH v5 10/12] nodedev: Implement virNodeDeviceUpdate
Date: Thu, 22 Feb 2024 14:02:07 +0100
Message-ID: <20240222130209.8316-11-fiuczy@linux.ibm.com>
X-Mailer: git-send-email 2.43.0
In-Reply-To: <20240222130209.8316-1-fiuczy@linux.ibm.com>
References: <20240222130209.8316-1-fiuczy@linux.ibm.com>
MIME-Version: 1.0
X-TM-AS-GCONF: 00
X-Proofpoint-GUID: piS7t_DbVUjslm3GbEEkPNWgwFT1IG4M
X-Proofpoint-ORIG-GUID: l2mmXaLj2pZY1L0eXXhw1loDSt496clS
X-Proofpoint-Virus-Version: vendor=baseguard
engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26
definitions=2024-02-22_10,2024-02-22_01,2023-05-22_02
X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
phishscore=0 spamscore=0
malwarescore=0 suspectscore=0 clxscore=1015 impostorscore=0 adultscore=0
mlxscore=0 mlxlogscore=999 priorityscore=1501 bulkscore=0
lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1
engine=8.12.0-2311290000 definitions=main-2402220104
Message-ID-Hash: QVO4GBCPR3FZJJLLIORZ2MOMYO4OE3FH
X-Message-ID-Hash: QVO4GBCPR3FZJJLLIORZ2MOMYO4OE3FH
X-MailFrom: fiuczy@linux.ibm.com
X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency;
loop; banned-address; member-moderation; header-match-config-1;
header-match-config-2; header-match-config-3;
header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia;
implicit-dest; max-recipients; max-size; news-moderation; no-subject;
suspicious-header
CC: jjongsma@redhat.com, mhartmay@linux.ibm.com
X-Mailman-Version: 3.2.2
Precedence: list
List-Id: Development discussions about the libvirt library & tools
Archived-At:
List-Archive:
List-Help:
List-Post:
List-Subscribe:
List-Unsubscribe:
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
X-ZM-MESSAGEID: 1708608083535100001
Implement the API functions in the node device driver by using mdevctl
modify with the options defined and live.
Instead of increasing the minimum mdevctl version to 1.3.0 in the spec
file to ensure support exists in mdevctl the support is dynamically
checked before using mdevctl.
Signed-off-by: Boris Fiuczynski
Reviewed-by: Jonathon Jongsma
---
NEWS.rst | 7 +
libvirt.spec.in | 1 +
src/node_device/node_device_driver.c | 224 +++++++++++++++++-
src/node_device/node_device_driver.h | 11 +
src/node_device/node_device_udev.c | 1 +
...60c_c60c_c60c_c60c_c60cc60cc60c_update.xml | 16 ++
tests/nodedevmdevctldata/mdevctl-modify.argv | 25 ++
tests/nodedevmdevctldata/mdevctl-modify.json | 4 +
tests/nodedevmdevctltest.c | 90 ++++++-
9 files changed, 376 insertions(+), 3 deletions(-)
create mode 100644 tests/nodedevmdevctldata/mdev_c60cc60c_c60c_c60c_c60c_c=
60cc60cc60c_update.xml
create mode 100644 tests/nodedevmdevctldata/mdevctl-modify.argv
create mode 100644 tests/nodedevmdevctldata/mdevctl-modify.json
diff --git a/NEWS.rst b/NEWS.rst
index cf9692130a..bb264a4bcc 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -17,6 +17,13 @@ v10.1.0 (unreleased)
=20
* **New features**
=20
+ * nodedev: Support updating mdevs
+
+ The node device driver has been extended to allow updating mediated no=
de
+ devices. Options are available to target the update against the persis=
tent,
+ active or both configurations of a mediated device.
+ **Note:** The support is only available with at least mdevctl v1.3.0 i=
nstalled.
+
* qemu: Add support for /dev/userfaultfd
=20
On hosts with new enough kernel which supports /dev/userfaultfd libvir=
t will
diff --git a/libvirt.spec.in b/libvirt.spec.in
index a1386590e7..3358589413 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -620,6 +620,7 @@ Requires: libvirt-libs =3D %{version}-%{release}
# needed for device enumeration
Requires: systemd >=3D 185
# For managing persistent mediated devices
+# Note: for nodedev-update support at least mdevctl v1.3.0 is required
Requires: mdevctl
# for modprobe of pci devices
Requires: module-init-tools
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de=
vice_driver.c
index baff49a0ae..07a951533d 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -54,7 +54,7 @@ virNodeDeviceDriverState *driver;
=20
VIR_ENUM_IMPL(virMdevctlCommand,
MDEVCTL_CMD_LAST,
- "start", "stop", "define", "undefine", "create"
+ "start", "stop", "define", "undefine", "create", "modify"
);
=20
=20
@@ -754,6 +754,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
case MDEVCTL_CMD_START:
case MDEVCTL_CMD_DEFINE:
case MDEVCTL_CMD_UNDEFINE:
+ case MDEVCTL_CMD_MODIFY:
cmd =3D virCommandNewArgList(MDEVCTL, subcommand, NULL);
break;
case MDEVCTL_CMD_LAST:
@@ -767,6 +768,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
switch (cmd_type) {
case MDEVCTL_CMD_CREATE:
case MDEVCTL_CMD_DEFINE:
+ case MDEVCTL_CMD_MODIFY:
if (!def->caps->data.mdev.parent_addr) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to find parent device '%1$s'"), def->=
parent);
@@ -783,7 +785,8 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
virCommandAddArgPair(cmd, "--jsonfile", "/dev/stdin");
=20
virCommandSetInputBuffer(cmd, inbuf);
- virCommandSetOutputBuffer(cmd, outbuf);
+ if (outbuf)
+ virCommandSetOutputBuffer(cmd, outbuf);
break;
=20
case MDEVCTL_CMD_UNDEFINE:
@@ -868,6 +871,100 @@ virMdevctlDefine(virNodeDeviceDef *def, char **uuid)
}
=20
=20
+/* gets a virCommand object that executes a mdevctl command to modify a
+ * a device to an updated version
+ */
+virCommand*
+nodeDeviceGetMdevctlModifyCommand(virNodeDeviceDef *def,
+ bool defined,
+ bool live,
+ char **errmsg)
+{
+ virCommand *cmd =3D nodeDeviceGetMdevctlCommand(def,
+ MDEVCTL_CMD_MODIFY,
+ NULL, errmsg);
+
+ if (!cmd)
+ return NULL;
+
+ if (defined)
+ virCommandAddArg(cmd, "--defined");
+
+ if (live)
+ virCommandAddArg(cmd, "--live");
+
+ return cmd;
+}
+
+
+/* checks if mdevctl supports on the command modify the options live, defi=
ned
+ * and jsonfile
+ */
+static int
+nodeDeviceGetMdevctlModifySupportCheck(void)
+{
+ int status;
+ g_autoptr(virCommand) cmd =3D NULL;
+ const char *subcommand =3D virMdevctlCommandTypeToString(MDEVCTL_CMD_M=
ODIFY);
+
+ cmd =3D virCommandNewArgList(MDEVCTL,
+ subcommand,
+ "--defined",
+ "--live",
+ "--jsonfile",
+ "b",
+ "--help",
+ NULL);
+
+ if (!cmd)
+ return -1;
+
+ if (virCommandRun(cmd, &status) < 0)
+ return -1;
+
+ if (status !=3D 0) // update is unsupported
+ return -1;
+
+ return 0;
+}
+
+
+static int
+virMdevctlModify(virNodeDeviceDef *def,
+ bool defined,
+ bool live)
+{
+ int status;
+ g_autofree char *errmsg =3D NULL;
+ g_autoptr(virCommand) cmd =3D nodeDeviceGetMdevctlModifyCommand(def,
+ defined,
+ live,
+ &errmsg);
+
+ if (!cmd)
+ return -1;
+
+ if (nodeDeviceGetMdevctlModifySupportCheck() < 0) {
+ VIR_WARN("Installed mdevctl version does not support modify with o=
ptions jsonfile, defined and live");
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("Unable to modify mediated device: modify unsuppo=
rted"));
+ return -1;
+ }
+
+ if (virCommandRun(cmd, &status) < 0)
+ return -1;
+
+ if (status !=3D 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to modify mediated device: %1$s"),
+ MDEVCTL_ERROR(errmsg));
+ return -1;
+ }
+
+ return 0;
+}
+
+
static virNodeDevicePtr
nodeDeviceCreateXMLMdev(virConnectPtr conn,
virNodeDeviceDef *def)
@@ -2106,3 +2203,126 @@ nodeDeviceIsActive(virNodeDevice *device)
virNodeDeviceObjEndAPI(&obj);
return ret;
}
+
+
+static int
+nodeDeviceDefValidateUpdate(virNodeDeviceDef *def,
+ virNodeDeviceDef *new_def,
+ bool live)
+{
+ virNodeDevCapsDef *caps =3D NULL;
+ virNodeDevCapMdev *cap_mdev =3D NULL;
+ virNodeDevCapMdev *cap_new_mdev =3D NULL;
+
+ for (caps =3D def->caps; caps !=3D NULL; caps =3D caps->next) {
+ if (caps->data.type =3D=3D VIR_NODE_DEV_CAP_MDEV) {
+ cap_mdev =3D &caps->data.mdev;
+ }
+ }
+ if (!cap_mdev)
+ return -1;
+
+ for (caps =3D new_def->caps; caps !=3D NULL; caps =3D caps->next) {
+ if (caps->data.type =3D=3D VIR_NODE_DEV_CAP_MDEV) {
+ cap_new_mdev =3D &caps->data.mdev;
+ }
+ }
+ if (!cap_new_mdev)
+ return -1;
+
+ if (STRNEQ_NULLABLE(cap_mdev->uuid, cap_new_mdev->uuid)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Cannot update device '%1$s, uuid mismatch (curre=
nt uuid '%2$s')"),
+ def->name,
+ cap_mdev->uuid);
+ return -1;
+ }
+
+ /* A live update cannot change the mdev type. Since the new config is
+ * stored in defined_config, compare that to the mdev type of the curr=
ent
+ * live config to make sure they match */
+ if (live &&
+ STRNEQ_NULLABLE(cap_mdev->active_config.type, cap_new_mdev->define=
d_config.type)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Cannot update device '%1$s', type mismatch (curr=
ent type '%2$s')"),
+ def->name,
+ cap_mdev->active_config.type);
+ return -1;
+ }
+ if (STRNEQ_NULLABLE(cap_mdev->parent_addr, cap_new_mdev->parent_addr))=
{
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Cannot update device '%1$s', parent address mism=
atch (current parent address '%2$s')"),
+ def->name,
+ cap_mdev->parent_addr);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int
+nodeDeviceUpdate(virNodeDevice *device,
+ const char *xmlDesc,
+ unsigned int flags)
+{
+ int ret =3D -1;
+ virNodeDeviceObj *obj =3D NULL;
+ virNodeDeviceDef *def;
+ g_autoptr(virNodeDeviceDef) new_def =3D NULL;
+ const char *virt_type =3D NULL;
+ bool updated =3D false;
+
+ virCheckFlags(VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE |
+ VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG, -1);
+
+ if (nodeDeviceInitWait() < 0)
+ return -1;
+
+ if (!(obj =3D nodeDeviceObjFindByName(device->name)))
+ return -1;
+ def =3D virNodeDeviceObjGetDef(obj);
+
+ virt_type =3D virConnectGetType(device->conn);
+
+ if (virNodeDeviceUpdateEnsureACL(device->conn, def, flags) < 0)
+ goto cleanup;
+
+ if (!(new_def =3D virNodeDeviceDefParse(xmlDesc, NULL, EXISTING_DEVICE=
, virt_type,
+ &driver->parserCallbacks, NULL, =
true)))
+ goto cleanup;
+
+ if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV) &&
+ nodeDeviceHasCapability(new_def, VIR_NODE_DEV_CAP_MDEV)) {
+ // Checks flags are valid for the state and sets flags for current=
if flags not set
+ if (virNodeDeviceObjUpdateModificationImpact(obj, &flags) < 0)
+ goto cleanup;
+
+ // Compare def and new_def for compatibility e.g. parent, type and=
uuid
+ if (nodeDeviceDefValidateUpdate(def, new_def,
+ (flags & VIR_NODE_DEVICE_UPDATE_AF=
FECT_LIVE)) < 0)
+ goto cleanup;
+
+ // Update now
+ VIR_DEBUG("Update node device '%s' with mdevctl", def->name);
+ if (virMdevctlModify(new_def,
+ (flags & VIR_NODE_DEVICE_UPDATE_AFFECT_CONFIG=
),
+ (flags & VIR_NODE_DEVICE_UPDATE_AFFECT_LIVE))=
< 0) {
+ goto cleanup;
+ };
+ // Detect updates and also trigger events
+ updated =3D true;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Unsupported device type"));
+ goto cleanup;
+ }
+
+ ret =3D 0;
+ cleanup:
+ virNodeDeviceObjEndAPI(&obj);
+ if (updated)
+ nodeDeviceUpdateMediatedDevices();
+
+ return ret;
+}
diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_de=
vice_driver.h
index 4dce7e6f17..b3bc4b2e96 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -39,6 +39,7 @@ typedef enum {
* separation makes our code more readable in terms of knowing when we=
're
* starting a defined device and when we're creating a transient one */
MDEVCTL_CMD_CREATE,
+ MDEVCTL_CMD_MODIFY,
=20
MDEVCTL_CMD_LAST,
} virMdevctlCommand;
@@ -186,3 +187,13 @@ virCommand*
nodeDeviceGetMdevctlSetAutostartCommand(virNodeDeviceDef *def,
bool autostart,
char **errmsg);
+
+virCommand*
+nodeDeviceGetMdevctlModifyCommand(virNodeDeviceDef *def,
+ bool defined,
+ bool live,
+ char **errmsg);
+int
+nodeDeviceUpdate(virNodeDevice *dev,
+ const char *xmlDesc,
+ unsigned int flags);
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi=
ce_udev.c
index 57368a96c3..f1e402f8f7 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -2403,6 +2403,7 @@ static virNodeDeviceDriver udevNodeDeviceDriver =3D {
.nodeDeviceGetAutostart =3D nodeDeviceGetAutostart, /* 7.8.0 */
.nodeDeviceIsPersistent =3D nodeDeviceIsPersistent, /* 7.8.0 */
.nodeDeviceIsActive =3D nodeDeviceIsActive, /* 7.8.0 */
+ .nodeDeviceUpdate =3D nodeDeviceUpdate, /* 10.1.0 */
};
=20
=20
diff --git a/tests/nodedevmdevctldata/mdev_c60cc60c_c60c_c60c_c60c_c60cc60c=
c60c_update.xml b/tests/nodedevmdevctldata/mdev_c60cc60c_c60c_c60c_c60c_c60=
cc60cc60c_update.xml
new file mode 100644
index 0000000000..17e3611bf4
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_up=
date.xml
@@ -0,0 +1,16 @@
+
+ mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052
+ /sys/devices/css0/0.0.0052/c60cc60c-c60c-c60c-c60c-c60cc60cc60c
+ css_0_0_0052
+
+ vfio_ccw_mdev
+
+
+
+ c60cc60c-c60c-c60c-c60c-c60cc60cc60c
+ 0.0.0052
+
+
+
+
+
diff --git a/tests/nodedevmdevctldata/mdevctl-modify.argv b/tests/nodedevmd=
evctldata/mdevctl-modify.argv
new file mode 100644
index 0000000000..341c5e7fd0
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdevctl-modify.argv
@@ -0,0 +1,25 @@
+mdevctl \
+modify \
+--parent=3D0.0.0052 \
+--jsonfile=3D/dev/stdin \
+--uuid=3Dc60cc60c-c60c-c60c-c60c-c60cc60cc60c \
+--defined
+mdevctl \
+modify \
+--parent=3D0.0.0052 \
+--jsonfile=3D/dev/stdin \
+--uuid=3Dc60cc60c-c60c-c60c-c60c-c60cc60cc60c \
+--live
+mdevctl \
+modify \
+--parent=3D0.0.0052 \
+--jsonfile=3D/dev/stdin \
+--uuid=3Dc60cc60c-c60c-c60c-c60c-c60cc60cc60c \
+--live
+mdevctl \
+modify \
+--parent=3D0.0.0052 \
+--jsonfile=3D/dev/stdin \
+--uuid=3Dc60cc60c-c60c-c60c-c60c-c60cc60cc60c \
+--defined \
+--live
diff --git a/tests/nodedevmdevctldata/mdevctl-modify.json b/tests/nodedevmd=
evctldata/mdevctl-modify.json
new file mode 100644
index 0000000000..a778730fac
--- /dev/null
+++ b/tests/nodedevmdevctldata/mdevctl-modify.json
@@ -0,0 +1,4 @@
+{"mdev_type":"vfio_ccw-io","start":"manual"}
+{"mdev_type":"vfio_ccw-io","start":"manual","attrs":[{"add_attr_1":"val1"}=
,{"add_attr_2":"val2"}]}
+{"mdev_type":"vfio_ccw-io","start":"manual"}
+{"mdev_type":"vfio_ccw-io","start":"manual","attrs":[{"add_attr_1":"val1"}=
,{"add_attr_2":"val2"}]}
diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c
index f49d668461..de688c982e 100644
--- a/tests/nodedevmdevctltest.c
+++ b/tests/nodedevmdevctltest.c
@@ -33,7 +33,10 @@ testCommandDryRunCallback(const char *const*args G_GNUC_=
UNUSED,
{
char **stdinbuf =3D opaque;
=20
- *stdinbuf =3D g_strdup(input);
+ if (*stdinbuf)
+ *stdinbuf =3D g_strconcat(*stdinbuf, "\n", input, NULL);
+ else
+ *stdinbuf =3D g_strdup(input);
}
=20
typedef virCommand * (*MdevctlCmdFunc)(virNodeDeviceDef *, char **, char *=
*);
@@ -63,6 +66,7 @@ testMdevctlCmd(virMdevctlCommand cmd_type,
case MDEVCTL_CMD_START:
case MDEVCTL_CMD_STOP:
case MDEVCTL_CMD_UNDEFINE:
+ case MDEVCTL_CMD_MODIFY:
create =3D EXISTING_DEVICE;
break;
case MDEVCTL_CMD_LAST:
@@ -173,6 +177,85 @@ testMdevctlAutostart(const void *data G_GNUC_UNUSED)
return ret;
}
=20
+
+static int
+testMdevctlModify(const void *data G_GNUC_UNUSED)
+{
+ g_autoptr(virNodeDeviceDef) def =3D NULL;
+ g_autoptr(virNodeDeviceDef) def_update =3D NULL;
+ virBuffer buf =3D VIR_BUFFER_INITIALIZER;
+ const char *actualCmdline =3D NULL;
+ int ret =3D -1;
+ g_autoptr(virCommand) definedcmd =3D NULL;
+ g_autoptr(virCommand) livecmd =3D NULL;
+ g_autoptr(virCommand) bothcmd =3D NULL;
+ g_autofree char *errmsg =3D NULL;
+ g_autofree char *stdinbuf =3D NULL;
+ g_autofree char *mdevxml =3D
+ g_strdup_printf("%s/nodedevschemadata/mdev_c60cc60c_c60c_c60c_c60c=
_c60cc60cc60c.xml",
+ abs_srcdir);
+ g_autofree char *mdevxml_update =3D
+ g_strdup_printf("%s/nodedevmdevctldata/mdev_c60cc60c_c60c_c60c_c60=
c_c60cc60cc60c_update.xml",
+ abs_srcdir);
+ /* just concatenate both calls into the same output files */
+ g_autofree char *cmdlinefile =3D
+ g_strdup_printf("%s/nodedevmdevctldata/mdevctl-modify.argv",
+ abs_srcdir);
+ g_autofree char *jsonfile =3D
+ g_strdup_printf("%s/nodedevmdevctldata/mdevctl-modify.json",
+ abs_srcdir);
+ g_autoptr(virCommandDryRunToken) dryRunToken =3D virCommandDryRunToken=
New();
+
+ if (!(def =3D virNodeDeviceDefParse(NULL, mdevxml, CREATE_DEVICE, VIRT=
_TYPE,
+ &parser_callbacks, NULL, false)))
+ return -1;
+
+ virCommandSetDryRun(dryRunToken, &buf, true, true, testCommandDryRunCa=
llback, &stdinbuf);
+
+ if (!(definedcmd =3D nodeDeviceGetMdevctlModifyCommand(def, true, fals=
e, &errmsg)))
+ goto cleanup;
+
+ if (virCommandRun(definedcmd, NULL) < 0)
+ goto cleanup;
+
+ if (!(def_update =3D virNodeDeviceDefParse(NULL, mdevxml_update, EXIST=
ING_DEVICE, VIRT_TYPE,
+ &parser_callbacks, NULL, fals=
e)))
+ goto cleanup;
+
+ if (!(livecmd =3D nodeDeviceGetMdevctlModifyCommand(def_update, false,=
true, &errmsg)))
+ goto cleanup;
+
+ if (virCommandRun(livecmd, NULL) < 0)
+ goto cleanup;
+
+ if (!(livecmd =3D nodeDeviceGetMdevctlModifyCommand(def, false, true, =
&errmsg)))
+ goto cleanup;
+
+ if (virCommandRun(livecmd, NULL) < 0)
+ goto cleanup;
+
+ if (!(bothcmd =3D nodeDeviceGetMdevctlModifyCommand(def_update, true, =
true, &errmsg)))
+ goto cleanup;
+
+ if (virCommandRun(bothcmd, NULL) < 0)
+ goto cleanup;
+
+ if (!(actualCmdline =3D virBufferCurrentContent(&buf)))
+ goto cleanup;
+
+ if (virTestCompareToFileFull(actualCmdline, cmdlinefile, false) < 0)
+ goto cleanup;
+
+ if (virTestCompareToFile(stdinbuf, jsonfile) < 0)
+ goto cleanup;
+
+ ret =3D 0;
+
+ cleanup:
+ virBufferFreeAndReset(&buf);
+ return ret;
+}
+
static int
testMdevctlListDefined(const void *data G_GNUC_UNUSED)
{
@@ -457,6 +540,9 @@ mymain(void)
#define DO_TEST_AUTOSTART() \
DO_TEST_FULL("autostart mdevs", testMdevctlAutostart, NULL)
=20
+#define DO_TEST_MODIFY() \
+ DO_TEST_FULL("modify mdevs", testMdevctlModify, NULL)
+
#define DO_TEST_PARSE_JSON(filename) \
DO_TEST_FULL("parse mdevctl json " filename, testMdevctlParse, filenam=
e)
=20
@@ -485,6 +571,8 @@ mymain(void)
=20
DO_TEST_AUTOSTART();
=20
+ DO_TEST_MODIFY();
+
done:
nodedevTestDriverFree(driver);
=20
--=20
2.42.0
_______________________________________________
Devel mailing list -- devel@lists.libvirt.org
To unsubscribe send an email to devel-leave@lists.libvirt.org