nodedev: Introduce virNodeDeviceCapsListExport

Whether asking for a number of capabilities supported by a device or
listing them, it's handled essentially by a copy-paste code, so extract
the common stuff into this new helper which also updates all
capabilities just before touching them.

Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Erik Skultety 2018-01-19 10:57:03 +01:00
parent 349dda1fc8
commit 36546e3cdb
4 changed files with 97 additions and 57 deletions

View File

@ -2487,6 +2487,79 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
}
/**
* virNodeDeviceCapsListExport:
* @def: node device definition
* @list: pointer to an array to store all supported capabilities by a device
*
* Takes the definition, scans through all the capabilities that the device
* supports (including the nested caps) and populates a newly allocated list
* with them. Caller is responsible for freeing the list.
* If NULL is passed to @list, only the number of caps will be returned.
*
* Returns the number of capabilities the device supports, -1 on error.
*/
int
virNodeDeviceCapsListExport(virNodeDeviceDefPtr def,
virNodeDevCapType **list)
{
virNodeDevCapsDefPtr caps = NULL;
virNodeDevCapType *tmp = NULL;
bool want_list = !!list;
int ncaps = 0;
int ret = -1;
#define MAYBE_ADD_CAP(cap) \
do { \
if (want_list) \
tmp[ncaps] = cap; \
} while (0)
if (want_list && VIR_ALLOC_N(tmp, VIR_NODE_DEV_CAP_LAST - 1) < 0)
goto cleanup;
for (caps = def->caps; caps; caps = caps->next) {
unsigned int flags;
MAYBE_ADD_CAP(caps->data.type);
ncaps++;
/* check nested caps for a given type as well */
if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
flags = caps->data.scsi_host.flags;
if (flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_FC_HOST);
ncaps++;
}
if (flags & VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS) {
MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_VPORTS);
ncaps++;
}
}
if (caps->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
flags = caps->data.pci_dev.flags;
if (flags & VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) {
MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES);
ncaps++;
}
}
}
#undef MAYBE_ADD_CAP
if (want_list)
VIR_STEAL_PTR(*list, tmp);
ret = ncaps;
cleanup:
VIR_FREE(tmp);
return ret;
}
#ifdef __linux__
int

View File

@ -403,4 +403,9 @@ virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath,
int
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def);
int
virNodeDeviceCapsListExport(virNodeDeviceDefPtr def,
virNodeDevCapType **list);
#endif /* __VIR_NODE_DEVICE_CONF_H__ */

View File

@ -699,6 +699,7 @@ virNodeDevCapMdevTypeFree;
virNodeDevCapsDefFree;
virNodeDevCapTypeFromString;
virNodeDevCapTypeToString;
virNodeDeviceCapsListExport;
virNodeDeviceCreateVport;
virNodeDeviceDefFormat;
virNodeDeviceDefFree;

View File

@ -306,8 +306,6 @@ nodeDeviceNumOfCaps(virNodeDevicePtr device)
{
virNodeDeviceObjPtr obj;
virNodeDeviceDefPtr def;
virNodeDevCapsDefPtr caps;
int ncaps = 0;
int ret = -1;
if (!(obj = nodeDeviceObjFindByName(device->name)))
@ -317,27 +315,7 @@ nodeDeviceNumOfCaps(virNodeDevicePtr device)
if (virNodeDeviceNumOfCapsEnsureACL(device->conn, def) < 0)
goto cleanup;
for (caps = def->caps; caps; caps = caps->next) {
++ncaps;
if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
if (caps->data.scsi_host.flags &
VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)
ncaps++;
if (caps->data.scsi_host.flags &
VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)
ncaps++;
}
if (caps->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
if (caps->data.pci_dev.flags &
VIR_NODE_DEV_CAP_FLAG_PCI_MDEV)
ncaps++;
}
}
ret = ncaps;
ret = virNodeDeviceCapsListExport(def, NULL);
cleanup:
virNodeDeviceObjEndAPI(&obj);
@ -353,9 +331,10 @@ nodeDeviceListCaps(virNodeDevicePtr device,
{
virNodeDeviceObjPtr obj;
virNodeDeviceDefPtr def;
virNodeDevCapsDefPtr caps;
virNodeDevCapType *list = NULL;
int ncaps = 0;
int ret = -1;
size_t i = 0;
if (!(obj = nodeDeviceObjFindByName(device->name)))
return -1;
@ -364,46 +343,28 @@ nodeDeviceListCaps(virNodeDevicePtr device,
if (virNodeDeviceListCapsEnsureACL(device->conn, def) < 0)
goto cleanup;
for (caps = def->caps; caps && ncaps < maxnames; caps = caps->next) {
if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
if ((ncaps = virNodeDeviceCapsListExport(def, &list)) < 0)
goto cleanup;
if (ncaps > maxnames)
ncaps = maxnames;
for (i = 0; i < ncaps; i++) {
if (VIR_STRDUP(names[i], virNodeDevCapTypeToString(list[i])) < 0)
goto cleanup;
if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
if (ncaps < maxnames &&
caps->data.scsi_host.flags &
VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
if (VIR_STRDUP(names[ncaps++],
virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_FC_HOST)) < 0)
goto cleanup;
}
if (ncaps < maxnames &&
caps->data.scsi_host.flags &
VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS) {
if (VIR_STRDUP(names[ncaps++],
virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS)) < 0)
goto cleanup;
}
}
if (caps->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
if (ncaps < maxnames &&
caps->data.pci_dev.flags &
VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) {
if (VIR_STRDUP(names[ncaps++],
virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_MDEV_TYPES)) < 0)
goto cleanup;
}
}
}
ret = ncaps;
cleanup:
virNodeDeviceObjEndAPI(&obj);
if (ret == -1) {
--ncaps;
while (--ncaps >= 0)
VIR_FREE(names[ncaps]);
if (ret < 0) {
size_t j;
for (j = 0; j < i; j++)
VIR_FREE(names[j]);
}
VIR_FREE(list);
return ret;
}