Add the group membership information to a CCW device. Allow to filter CCW devices based on a group membership. Signed-off-by: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxx> --- docs/manpages/virsh.rst | 19 ++-- include/libvirt/libvirt-nodedev.h | 1 + src/conf/node_device_conf.c | 105 +++++++++++++++++- src/conf/node_device_conf.h | 10 +- src/conf/schemas/nodedev.rng | 12 ++ src/conf/virnodedeviceobj.c | 11 +- src/libvirt_private.syms | 1 + src/node_device/node_device_driver.c | 2 + src/node_device/node_device_udev.c | 4 + src/util/virccw.c | 23 ++++ src/util/virccw.h | 3 + .../ccw_0_0_ff02_ccwgroup.xml | 13 +++ .../ccw_0_0_ff02_ccwgroup.xml | 1 + tests/nodedevxml2xmltest.c | 1 + tools/virsh-nodedev.c | 3 + 15 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 tests/nodedevschemadata/ccw_0_0_ff02_ccwgroup.xml create mode 120000 tests/nodedevxml2xmlout/ccw_0_0_ff02_ccwgroup.xml diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index 5e5734dff1..9e549f25a6 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -5532,15 +5532,16 @@ List all of the devices available on the node that are known by libvirt. separated by comma, e.g. --cap pci,scsi. Valid capability types include 'system', 'pci', 'usb_device', 'usb', 'net', 'scsi_host', 'scsi_target', 'scsi', 'storage', 'fc_host', 'vports', 'scsi_generic', 'drm', 'mdev', -'mdev_types', 'ccw', 'ccwgroup', 'css', 'ap_card', 'ap_queue', 'ap_matrix'. -By default, only active devices are listed. *--inactive* is used to list only -inactive devices, and *--all* is used to list both active and inactive devices. -*--persistent* is used to list only persistent devices, and *--transient* is -used to list only transient devices. Not providing *--persistent* or -*--transient* will list all devices unless filtered otherwise. *--transient* -is mutually exclusive with *--persistent* and *--inactive*. -If *--tree* is used, the output is formatted in a tree representing parents of -each node. *--tree* is mutually exclusive with all other options but *--all*. +'mdev_types', 'ccw', 'ccwgroup', 'ccwgroup_member', 'css', 'ap_card', +'ap_queue', 'ap_matrix'. By default, only active devices are listed. +*--inactive* is used to list only inactive devices, and *--all* is used to +list both active and inactive devices. *--persistent* is used to list only +persistent devices, and *--transient* is used to list only transient devices. +Not providing *--persistent* or *--transient* will list all devices unless +filtered otherwise. *--transient* is mutually exclusive with *--persistent* +and *--inactive*. If *--tree* is used, the output is formatted in a tree +representing parents of each node. *--tree* is mutually exclusive with all +other options but *--all*. nodedev-reattach diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h index 79bee4fb04..9fccbeefeb 100644 --- a/include/libvirt/libvirt-nodedev.h +++ b/include/libvirt/libvirt-nodedev.h @@ -91,6 +91,7 @@ typedef enum { VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_MATRIX = 1 << 20, /* s390 AP Matrix (Since: 7.0.0) */ VIR_CONNECT_LIST_NODE_DEVICES_CAP_VPD = 1 << 21, /* Device with VPD (Since: 7.9.0) */ VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_DEV = 1 << 22, /* s390 CCWGROUP device (Since: 11.1.0) */ + VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_MEMBER = 1 << 23, /* s390 CCW device member of CCWGROUP device (Since: 11.1.0) */ VIR_CONNECT_LIST_NODE_DEVICES_PERSISTENT = 1 << 28, /* Persisted devices (Since: 10.1.0) */ VIR_CONNECT_LIST_NODE_DEVICES_TRANSIENT = 1 << 29, /* Transient devices (Since: 10.1.0) */ diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 1649df09a1..3e88f5da87 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -72,6 +72,7 @@ VIR_ENUM_IMPL(virNodeDevCap, "ap_matrix", "vpd", "ccwgroup", + "ccwgroup_member", ); VIR_ENUM_IMPL(virNodeDevCCWGroupCap, @@ -642,6 +643,23 @@ virCCWDeviceAddressFormat(virBuffer *buf, } +static void +virNodeDeviceCapCCWGroupMemberDefFormat(virBuffer *buf, + const virNodeDevCapData *data) +{ + virNodeDevCapCCW ccw_dev = data->ccw_dev; + + if (ccw_dev.group_dev) { + virBufferAddLit(buf, "<capability type='ccwgroup_member'>\n"); + virBufferAdjustIndent(buf, 2); + virBufferEscapeString(buf, "<group_device>%s</group_device>\n", + ccw_dev.group_dev); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</capability>\n"); + } +} + + static void virNodeDeviceCapCSSDefFormat(virBuffer *buf, const virNodeDevCapData *data) @@ -812,6 +830,8 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags) case VIR_NODE_DEV_CAP_CCW_DEV: virNodeDeviceCapCCWStateTypeFormat(&buf, data->ccw_dev.state); virCCWDeviceAddressFormat(&buf, data->ccw_dev.dev_addr); + if (data->ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER) + virNodeDeviceCapCCWGroupMemberDefFormat(&buf, data); break; case VIR_NODE_DEV_CAP_CSS_DEV: virNodeDeviceCapCSSDefFormat(&buf, data); @@ -843,6 +863,7 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags) case VIR_NODE_DEV_CAP_CCWGROUP_DEV: virNodeDeviceCapCCWGroupDefFormat(&buf, data); break; + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_VPD: @@ -1252,6 +1273,33 @@ virNodeDevCCWDeviceAddressParseXML(xmlXPathContextPtr ctxt, } +static int +virNodeDevCCWCapabilityParseXML(xmlXPathContextPtr ctxt, + xmlNodePtr node, + const char *dev_name, + virNodeDevCapCCW *ccw_dev) +{ + g_autofree char *type = virXMLPropString(node, "type"); + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = node; + + if (!type) + return 0; /* optional */ + + if (STREQ(type, "ccwgroup_member")) { + if (!(ccw_dev->group_dev = virXPathString("string(./group_device[1])", ctxt))) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("missing group_device value for '%1$s'"), dev_name); + return -1; + } + ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER; + } + + return 0; +} + + static int virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDef *def, @@ -1260,7 +1308,10 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt, { VIR_XPATH_NODE_AUTORESTORE(ctxt) g_autofree virCCWDeviceAddress *ccw_addr = NULL; + g_autofree xmlNodePtr *nodes = NULL; g_autofree char *state = NULL; + int n = 0; + size_t i = 0; int val; ctxt->node = node; @@ -1284,6 +1335,15 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt, ccw_dev->dev_addr = g_steal_pointer(&ccw_addr); + /* capabilities are optional */ + if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0) + return -1; + + for (i = 0; i < n; i++) { + if (virNodeDevCCWCapabilityParseXML(ctxt, nodes[i], def->name, ccw_dev) < 0) + return -1; + } + return 0; } @@ -2504,6 +2564,7 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, ret = virNodeDevCapCCWGroupParseXML(ctxt, def, node, &caps->data.ccwgroup_dev); break; + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: @@ -2795,6 +2856,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps) break; case VIR_NODE_DEV_CAP_CCW_DEV: g_free(data->ccw_dev.dev_addr); + g_free(data->ccw_dev.group_dev); break; case VIR_NODE_DEV_CAP_CCWGROUP_DEV: g_free(data->ccwgroup_dev.address); @@ -2809,6 +2871,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps) break; } break; + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: @@ -2868,6 +2931,12 @@ virNodeDeviceUpdateCaps(virNodeDeviceDef *def) &cap->data.mdev_parent) < 0) return -1; break; + case VIR_NODE_DEV_CAP_CCW_DEV: + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: + if (virNodeDeviceGetCCWDynamicCaps(def->sysfs_path, + &cap->data.ccw_dev) < 0) + return -1; + break; case VIR_NODE_DEV_CAP_CCWGROUP_DEV: if (virNodeDeviceGetCCWGroupDynamicCaps(def->sysfs_path, &cap->data.ccwgroup_dev) < 0) @@ -2887,7 +2956,6 @@ virNodeDeviceUpdateCaps(virNodeDeviceDef *def) case VIR_NODE_DEV_CAP_VPORTS: case VIR_NODE_DEV_CAP_SCSI_GENERIC: case VIR_NODE_DEV_CAP_MDEV: - case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_VDPA: case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_QUEUE: @@ -2986,6 +3054,15 @@ virNodeDeviceCapsListExport(virNodeDeviceDef *def, ncaps++; } } + + if (caps->data.type == VIR_NODE_DEV_CAP_CCW_DEV) { + flags = caps->data.ccw_dev.flags; + + if (flags & VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER) { + MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_CCWGROUP_MEMBER); + ncaps++; + } + } } #undef MAYBE_ADD_CAP @@ -3335,6 +3412,25 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath, return 0; } +/* virNodeDeviceGetCCWDynamicCaps() get info that is stored in sysfs + * about devices related to this device, i.e. things that can change + * without this device itself changing. These must be refreshed + * anytime full XML of the device is requested, because they can + * change with no corresponding notification from the kernel/udev. + */ +int +virNodeDeviceGetCCWDynamicCaps(const char *sysfsPath, + virNodeDevCapCCW *ccw_dev) +{ + g_free(ccw_dev->group_dev); + ccw_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER; + + if ((ccw_dev->group_dev = virCCWDeviceGetGroupDev(sysfsPath))) + ccw_dev->flags |= VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER; + + return 0; +} + /* virNodeDeviceGetAPMatrixDynamicCaps() get info that is stored in sysfs * about devices related to this device, i.e. things that can change * without this device itself changing. These must be refreshed @@ -3428,6 +3524,13 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, return -1; } +int +virNodeDeviceGetCCWDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, + virNodeDevCapCCW *ccw_dev G_GNUC_UNUSED) +{ + return -1; +} + int virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, virNodeDevCapAPMatrix *ap_matrix G_GNUC_UNUSED) diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index d94670e074..a6cef57b95 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -72,6 +72,7 @@ typedef enum { VIR_NODE_DEV_CAP_AP_MATRIX, /* s390 AP Matrix device */ VIR_NODE_DEV_CAP_VPD, /* Device provides VPD */ VIR_NODE_DEV_CAP_CCWGROUP_DEV, /* s390 CCWGROUP device */ + VIR_NODE_DEV_CAP_CCWGROUP_MEMBER, /* s390 CCW device is member of CCWGROUP */ VIR_NODE_DEV_CAP_LAST } virNodeDevCapType; @@ -118,6 +119,7 @@ typedef enum { typedef enum { VIR_NODE_DEV_CAP_FLAG_CSS_MDEV = (1 << 0), + VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER = (2 << 0), } virNodeDevCCWCapFlags; typedef enum { @@ -295,6 +297,7 @@ struct _virNodeDevCapCCW { size_t nmdev_types; virCCWDeviceAddress *channel_dev_addr; virNodeDevCCWStateType state; + char *group_dev; }; typedef struct _virNodeDevCapVDPA virNodeDevCapVDPA; @@ -457,7 +460,8 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(virNodeDevCapsDef, virNodeDevCapsDefFree); VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_QUEUE | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_AP_MATRIX | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_VPD | \ - VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_DEV) + VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_DEV | \ + VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_MEMBER) #define VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_ACTIVE \ VIR_CONNECT_LIST_NODE_DEVICES_ACTIVE | \ @@ -495,6 +499,10 @@ int virNodeDeviceGetMdevParentDynamicCaps(const char *sysfsPath, virNodeDevCapMdevParent *mdev_parent); +int +virNodeDeviceGetCCWDynamicCaps(const char *sysfsPath, + virNodeDevCapCCW *ccw_dev); + int virNodeDeviceGetCCWGroupDynamicCaps(const char *sysfsPath, virNodeDevCapCCWGroup *ccwgroup); diff --git a/src/conf/schemas/nodedev.rng b/src/conf/schemas/nodedev.rng index ebcda30f1f..f52c6ab752 100644 --- a/src/conf/schemas/nodedev.rng +++ b/src/conf/schemas/nodedev.rng @@ -712,6 +712,17 @@ </element> </define> + <define name="capccwgroupmember"> + <optional> + <element name="capability"> + <attribute name="type"> + <value>ccwgroup_member</value> + </attribute> + <element name="group_device"><text/></element> + </element> + </optional> + </define> + <define name="capccwdev"> <attribute name="type"> <value>ccw</value> @@ -725,6 +736,7 @@ </element> </optional> <ref name="capccwaddress"/> + <ref name="capccwgroupmember"/> </define> <define name="capcssdev"> diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c index 23984995c8..c5ddf0b4fb 100644 --- a/src/conf/virnodedeviceobj.c +++ b/src/conf/virnodedeviceobj.c @@ -723,6 +723,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj, return true; break; + case VIR_NODE_DEV_CAP_CCW_DEV: + if (type == VIR_NODE_DEV_CAP_CCWGROUP_MEMBER && + (cap->data.ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CCW_CCWGROUP_MEMBER)) + return true; + break; + case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_INTERFACE: @@ -736,12 +742,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj, case VIR_NODE_DEV_CAP_DRM: case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_MDEV: - case VIR_NODE_DEV_CAP_CCW_DEV: case VIR_NODE_DEV_CAP_VDPA: case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_QUEUE: case VIR_NODE_DEV_CAP_VPD: case VIR_NODE_DEV_CAP_CCWGROUP_DEV: + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_LAST: break; } @@ -901,7 +907,8 @@ virNodeDeviceObjMatch(virNodeDeviceObj *obj, MATCH_CAP(AP_QUEUE) || MATCH_CAP(AP_MATRIX) || MATCH_CAP(VPD) || - MATCH_CAP(CCWGROUP_DEV))) + MATCH_CAP(CCWGROUP_DEV) || + MATCH_CAP(CCWGROUP_MEMBER))) return false; } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 07e1e673f0..8abda5fa7e 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -899,6 +899,7 @@ virNodeDeviceDefFree; virNodeDeviceDefParse; virNodeDeviceDefParseXML; virNodeDeviceGetAPMatrixDynamicCaps; +virNodeDeviceGetCCWDynamicCaps; virNodeDeviceGetCCWGroupDynamicCaps; virNodeDeviceGetCSSDynamicCaps; virNodeDeviceGetMdevParentDynamicCaps; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index d716561361..123b16a292 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -717,6 +717,7 @@ nodeDeviceObjFormatAddress(virNodeDeviceObj *obj) case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_QUEUE: case VIR_NODE_DEV_CAP_VPD: + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_LAST: break; } @@ -2194,6 +2195,7 @@ int nodeDeviceDefValidate(virNodeDeviceDef *def, case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_VPD: case VIR_NODE_DEV_CAP_CCWGROUP_DEV: + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_LAST: break; } diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index a78f47b65a..ba5727ed8f 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1239,6 +1239,9 @@ udevProcessCCW(struct udev_device *device, udevGenerateDeviceName(device, def, NULL); + if (virNodeDeviceGetCCWDynamicCaps(def->sysfs_path, &def->caps->data.ccw_dev) < 0) + return -1; + return 0; } @@ -1575,6 +1578,7 @@ udevGetDeviceDetails(virNodeDeviceDriverState *driver_state, return udevProcessMdevParent(device, def); case VIR_NODE_DEV_CAP_CCWGROUP_DEV: return udevProcessCCWGroup(device, def); + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: case VIR_NODE_DEV_CAP_VPD: case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_FC_HOST: diff --git a/src/util/virccw.c b/src/util/virccw.c index 0873c61889..762ef671a2 100644 --- a/src/util/virccw.c +++ b/src/util/virccw.c @@ -203,3 +203,26 @@ virCCWGroupTypeQethFree(virCCWGroupTypeQeth *qeth) VIR_FREE(qeth->card_type); VIR_FREE(qeth->chpid); } + +char * +virCCWDeviceGetGroupDev(const char *sysfs_path) +{ + g_autofree char *ccwgroup_path = NULL; + g_autofree char *group_dev_path = NULL; + + group_dev_path = g_build_filename(sysfs_path, "group_device", NULL); + + if (!virFileExists(group_dev_path)) + return NULL; + + if (virFileIsLink(group_dev_path) != 1) + return NULL; + + if (virFileResolveLink(group_dev_path, &ccwgroup_path) < 0) + return NULL; + + if (!virFileExists(ccwgroup_path)) + return NULL; + + return virCCWGroupDeviceDevNodeName("ccwgroup", ccwgroup_path); +} diff --git a/src/util/virccw.h b/src/util/virccw.h index a8c9fa83ef..67faf878a8 100644 --- a/src/util/virccw.h +++ b/src/util/virccw.h @@ -71,4 +71,7 @@ int virCCWGroupDeviceGetMembers(const char *sysfs_path, void virCCWGroupTypeQethFree(virCCWGroupTypeQeth *qeth); +char* virCCWDeviceGetGroupDev(const char *sysfs_path) + ATTRIBUTE_NONNULL(1); + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCCWGroupMemberType, virCCWGroupMemberTypeFree); diff --git a/tests/nodedevschemadata/ccw_0_0_ff02_ccwgroup.xml b/tests/nodedevschemadata/ccw_0_0_ff02_ccwgroup.xml new file mode 100644 index 0000000000..11767facd3 --- /dev/null +++ b/tests/nodedevschemadata/ccw_0_0_ff02_ccwgroup.xml @@ -0,0 +1,13 @@ +<device> + <name>ccw_0_0_ff02</name> + <path>/sys/devices/css0/0.0.0070/0.0.ff02</path> + <parent>css_0_0_0070</parent> + <capability type='ccw'> + <cssid>0x0</cssid> + <ssid>0x0</ssid> + <devno>0xff02</devno> + <capability type='ccwgroup_member'> + <group_device>ccwgroup_0_0_ff00</group_device> + </capability> + </capability> +</device> diff --git a/tests/nodedevxml2xmlout/ccw_0_0_ff02_ccwgroup.xml b/tests/nodedevxml2xmlout/ccw_0_0_ff02_ccwgroup.xml new file mode 120000 index 0000000000..4d2b000b11 --- /dev/null +++ b/tests/nodedevxml2xmlout/ccw_0_0_ff02_ccwgroup.xml @@ -0,0 +1 @@ +../nodedevschemadata/ccw_0_0_ff02_ccwgroup.xml \ No newline at end of file diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index d4d87b3bdc..265b37b218 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -146,6 +146,7 @@ mymain(void) DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b"); DO_TEST_INACTIVE("mdev_3627463d_b7f0_4fea_b468_f1da537d301b"); DO_TEST("ccw_0_0_ffff"); + DO_TEST("ccw_0_0_ff02_ccwgroup"); DO_TEST("ccwgroup_0_0_bd00"); DO_TEST("css_0_0_ffff"); DO_TEST("css_0_0_ffff_channel_dev_addr"); diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c index 3aae7285a9..e759b9f629 100644 --- a/tools/virsh-nodedev.c +++ b/tools/virsh-nodedev.c @@ -504,6 +504,9 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED) case VIR_NODE_DEV_CAP_CCWGROUP_DEV: flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_DEV; break; + case VIR_NODE_DEV_CAP_CCWGROUP_MEMBER: + flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCWGROUP_MEMBER; + break; case VIR_NODE_DEV_CAP_LAST: break; } -- 2.47.0