mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
nodedev: add support for mdev attributes
Mediated devices support arbitrary vendor-specific attributes that can be attached to a mediated device. These attributes are ordered, and are written to sysfs in order after a device is created. This patch adds support for these attributes to the mdev data types and XML schema. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Erik Skultety <eskultet@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
37ab63a6fc
commit
c952d9cc1e
@ -394,6 +394,13 @@
|
|||||||
belongs. This is a read-only field that is reported by the
|
belongs. This is a read-only field that is reported by the
|
||||||
device driver.
|
device driver.
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>attr</code></dt>
|
||||||
|
<dd>
|
||||||
|
This optional element can occur multiple times. It represents a
|
||||||
|
vendor-specific attribute that is used to configure this
|
||||||
|
mediated device. It has two required attributes:
|
||||||
|
<code>name</code> and <code>value</code>.
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>ccw</code></dt>
|
<dt><code>ccw</code></dt>
|
||||||
|
@ -636,6 +636,12 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
|
<zeroOrMore>
|
||||||
|
<element name="attr">
|
||||||
|
<attribute name="name"/>
|
||||||
|
<attribute name="value"/>
|
||||||
|
</element>
|
||||||
|
</zeroOrMore>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name='capccwdev'>
|
<define name='capccwdev'>
|
||||||
|
@ -500,6 +500,22 @@ virNodeDeviceCapStorageDefFormat(virBufferPtr buf,
|
|||||||
virBufferAddLit(buf, "<capability type='hotpluggable'/>\n");
|
virBufferAddLit(buf, "<capability type='hotpluggable'/>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virNodeDeviceCapMdevDefFormat(virBufferPtr buf,
|
||||||
|
const virNodeDevCapData *data)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.type);
|
||||||
|
virBufferAsprintf(buf, "<iommuGroup number='%u'/>\n",
|
||||||
|
data->mdev.iommuGroupNumber);
|
||||||
|
|
||||||
|
for (i = 0; i < data->mdev.nattributes; i++) {
|
||||||
|
virMediatedDeviceAttrPtr attr = data->mdev.attributes[i];
|
||||||
|
virBufferAsprintf(buf, "<attr name='%s' value='%s'/>\n",
|
||||||
|
attr->name, attr->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
||||||
@ -583,9 +599,7 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
|||||||
virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
|
virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
virBufferEscapeString(&buf, "<type id='%s'/>\n", data->mdev.type);
|
virNodeDeviceCapMdevDefFormat(&buf, data);
|
||||||
virBufferAsprintf(&buf, "<iommuGroup number='%u'/>\n",
|
|
||||||
data->mdev.iommuGroupNumber);
|
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_CCW_DEV:
|
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||||
virBufferAsprintf(&buf, "<cssid>0x%x</cssid>\n",
|
virBufferAsprintf(&buf, "<cssid>0x%x</cssid>\n",
|
||||||
@ -1757,6 +1771,27 @@ virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNodeDevCapMdevAttributeParseXML(xmlXPathContextPtr ctxt,
|
||||||
|
xmlNodePtr node,
|
||||||
|
virNodeDevCapMdevPtr mdev)
|
||||||
|
{
|
||||||
|
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
||||||
|
g_autoptr(virMediatedDeviceAttr) attr = virMediatedDeviceAttrNew();
|
||||||
|
|
||||||
|
ctxt->node = node;
|
||||||
|
attr->name = virXPathString("string(./@name)", ctxt);
|
||||||
|
attr->value = virXPathString("string(./@value)", ctxt);
|
||||||
|
if (!attr->name || !attr->value) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("mdev attribute missing name or value"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VIR_APPEND_ELEMENT(mdev->attributes,
|
||||||
|
mdev->nattributes,
|
||||||
|
attr);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
||||||
@ -1766,6 +1801,9 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
|||||||
{
|
{
|
||||||
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
VIR_XPATH_NODE_AUTORESTORE(ctxt);
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
int nattrs = 0;
|
||||||
|
g_autofree xmlNodePtr *attrs = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
ctxt->node = node;
|
ctxt->node = node;
|
||||||
|
|
||||||
@ -1785,6 +1823,12 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((nattrs = virXPathNodeSet("./attr", ctxt, &attrs)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (i = 0; i < nattrs; i++)
|
||||||
|
virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], mdev);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
@ -2174,6 +2218,9 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
|||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
VIR_FREE(data->mdev.type);
|
VIR_FREE(data->mdev.type);
|
||||||
|
for (i = 0; i < data->mdev.nattributes; i++)
|
||||||
|
virMediatedDeviceAttrFree(data->mdev.attributes[i]);
|
||||||
|
VIR_FREE(data->mdev.attributes);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_DRM:
|
case VIR_NODE_DEV_CAP_DRM:
|
||||||
|
@ -141,6 +141,8 @@ typedef virNodeDevCapMdev *virNodeDevCapMdevPtr;
|
|||||||
struct _virNodeDevCapMdev {
|
struct _virNodeDevCapMdev {
|
||||||
char *type;
|
char *type;
|
||||||
unsigned int iommuGroupNumber;
|
unsigned int iommuGroupNumber;
|
||||||
|
virMediatedDeviceAttrPtr *attributes;
|
||||||
|
size_t nattributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
|
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
|
||||||
|
@ -2487,6 +2487,8 @@ virMacMapRemove;
|
|||||||
virMacMapWriteFile;
|
virMacMapWriteFile;
|
||||||
|
|
||||||
# util/virmdev.h
|
# util/virmdev.h
|
||||||
|
virMediatedDeviceAttrFree;
|
||||||
|
virMediatedDeviceAttrNew;
|
||||||
virMediatedDeviceFree;
|
virMediatedDeviceFree;
|
||||||
virMediatedDeviceGetIOMMUGroupDev;
|
virMediatedDeviceGetIOMMUGroupDev;
|
||||||
virMediatedDeviceGetIOMMUGroupNum;
|
virMediatedDeviceGetIOMMUGroupNum;
|
||||||
|
@ -512,3 +512,15 @@ virMediatedDeviceTypeReadAttrs(const char *sysfspath,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virMediatedDeviceAttrPtr virMediatedDeviceAttrNew(void)
|
||||||
|
{
|
||||||
|
return g_new0(virMediatedDeviceAttr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void virMediatedDeviceAttrFree(virMediatedDeviceAttrPtr attr)
|
||||||
|
{
|
||||||
|
g_free(attr->name);
|
||||||
|
g_free(attr->value);
|
||||||
|
g_free(attr);
|
||||||
|
}
|
||||||
|
@ -37,6 +37,17 @@ typedef struct _virMediatedDevice virMediatedDevice;
|
|||||||
typedef virMediatedDevice *virMediatedDevicePtr;
|
typedef virMediatedDevice *virMediatedDevicePtr;
|
||||||
typedef struct _virMediatedDeviceList virMediatedDeviceList;
|
typedef struct _virMediatedDeviceList virMediatedDeviceList;
|
||||||
typedef virMediatedDeviceList *virMediatedDeviceListPtr;
|
typedef virMediatedDeviceList *virMediatedDeviceListPtr;
|
||||||
|
typedef struct _virMediatedDeviceAttr virMediatedDeviceAttr;
|
||||||
|
typedef virMediatedDeviceAttr *virMediatedDeviceAttrPtr;
|
||||||
|
|
||||||
|
struct _virMediatedDeviceAttr {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
virMediatedDeviceAttrPtr virMediatedDeviceAttrNew(void);
|
||||||
|
void virMediatedDeviceAttrFree(virMediatedDeviceAttrPtr attr);
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMediatedDeviceAttr, virMediatedDeviceAttrFree);
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMediatedDeviceList, virObjectUnref);
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virMediatedDeviceList, virObjectUnref);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user