}
+/**
+ * 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
{
virNodeDeviceObjPtr obj;
virNodeDeviceDefPtr def;
- virNodeDevCapsDefPtr caps;
- int ncaps = 0;
int ret = -1;
if (!(obj = nodeDeviceObjFindByName(device->name)))
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);
{
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;
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)
- goto cleanup;
+ if ((ncaps = virNodeDeviceCapsListExport(def, &list)) < 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;
- }
- }
+ if (ncaps > maxnames)
+ ncaps = maxnames;
+
+ for (i = 0; i < ncaps; i++) {
+ if (VIR_STRDUP(names[i], virNodeDevCapTypeToString(list[i])) < 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;
}