mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
nodedev: add an active config to mdev
The configuration of a defined mdev can be modified after the mdev is started. The defined configuration and the active configuration can therefore run out of sync. Handle this by storing the modifiable data which is the mdev type and attributes in two separate active and defined configurations. mdevctl supports with callout scripts to do an attribute retrieval of started mdevs which is already implemented in libvirt. Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
c65c078655
commit
e67bca23e4
@ -117,6 +117,17 @@ int virNodeDeviceListCaps (virNodeDevicePtr dev,
|
|||||||
char **const names,
|
char **const names,
|
||||||
int maxnames);
|
int maxnames);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virNodeDeviceXMLFlags:
|
||||||
|
*
|
||||||
|
* Flags used to provide the state of the returned node device configuration.
|
||||||
|
*
|
||||||
|
* Since: 10.1.0
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VIR_NODE_DEVICE_XML_INACTIVE = 1 << 0, /* dump inactive device configuration (Since: 10.1.0) */
|
||||||
|
} virNodeDeviceXMLFlags;
|
||||||
|
|
||||||
char * virNodeDeviceGetXMLDesc (virNodeDevicePtr dev,
|
char * virNodeDeviceGetXMLDesc (virNodeDevicePtr dev,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
@ -602,16 +602,22 @@ virNodeDeviceCapMdevAttrFormat(virBuffer *buf,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
virNodeDeviceCapMdevDefFormat(virBuffer *buf,
|
virNodeDeviceCapMdevDefFormat(virBuffer *buf,
|
||||||
const virNodeDevCapData *data)
|
const virNodeDevCapData *data,
|
||||||
|
bool defined)
|
||||||
{
|
{
|
||||||
virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.dev_config.type);
|
if (defined)
|
||||||
|
virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.defined_config.type);
|
||||||
|
else
|
||||||
|
virBufferEscapeString(buf, "<type id='%s'/>\n", data->mdev.active_config.type);
|
||||||
virBufferEscapeString(buf, "<uuid>%s</uuid>\n", data->mdev.uuid);
|
virBufferEscapeString(buf, "<uuid>%s</uuid>\n", data->mdev.uuid);
|
||||||
virBufferEscapeString(buf, "<parent_addr>%s</parent_addr>\n",
|
virBufferEscapeString(buf, "<parent_addr>%s</parent_addr>\n",
|
||||||
data->mdev.parent_addr);
|
data->mdev.parent_addr);
|
||||||
virBufferAsprintf(buf, "<iommuGroup number='%u'/>\n",
|
virBufferAsprintf(buf, "<iommuGroup number='%u'/>\n",
|
||||||
data->mdev.iommuGroupNumber);
|
data->mdev.iommuGroupNumber);
|
||||||
|
if (defined)
|
||||||
virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.dev_config);
|
virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.defined_config);
|
||||||
|
else
|
||||||
|
virNodeDeviceCapMdevAttrFormat(buf, &data->mdev.active_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -662,25 +668,29 @@ virNodeDeviceCapCSSDefFormat(virBuffer *buf,
|
|||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags)
|
||||||
{
|
{
|
||||||
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
||||||
virNodeDevCapsDef *caps;
|
virNodeDevCapsDef *caps;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
bool inactive_state = flags & VIR_NODE_DEVICE_XML_INACTIVE;
|
||||||
|
|
||||||
virBufferAddLit(&buf, "<device>\n");
|
virBufferAddLit(&buf, "<device>\n");
|
||||||
virBufferAdjustIndent(&buf, 2);
|
virBufferAdjustIndent(&buf, 2);
|
||||||
virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
|
virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
|
||||||
virBufferEscapeString(&buf, "<path>%s</path>\n", def->sysfs_path);
|
if (!inactive_state) {
|
||||||
virBufferEscapeString(&buf, "<devnode type='dev'>%s</devnode>\n",
|
virBufferEscapeString(&buf, "<path>%s</path>\n", def->sysfs_path);
|
||||||
def->devnode);
|
virBufferEscapeString(&buf, "<devnode type='dev'>%s</devnode>\n",
|
||||||
if (def->devlinks) {
|
def->devnode);
|
||||||
for (i = 0; def->devlinks[i]; i++)
|
if (def->devlinks) {
|
||||||
virBufferEscapeString(&buf, "<devnode type='link'>%s</devnode>\n",
|
for (i = 0; def->devlinks[i]; i++) {
|
||||||
def->devlinks[i]);
|
virBufferEscapeString(&buf, "<devnode type='link'>%s</devnode>\n",
|
||||||
|
def->devlinks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
virBufferEscapeString(&buf, "<parent>%s</parent>\n", def->parent);
|
virBufferEscapeString(&buf, "<parent>%s</parent>\n", def->parent);
|
||||||
if (def->driver) {
|
if (def->driver && !inactive_state) {
|
||||||
virBufferAddLit(&buf, "<driver>\n");
|
virBufferAddLit(&buf, "<driver>\n");
|
||||||
virBufferAdjustIndent(&buf, 2);
|
virBufferAdjustIndent(&buf, 2);
|
||||||
virBufferEscapeString(&buf, "<name>%s</name>\n", def->driver);
|
virBufferEscapeString(&buf, "<name>%s</name>\n", def->driver);
|
||||||
@ -741,7 +751,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:
|
||||||
virNodeDeviceCapMdevDefFormat(&buf, data);
|
virNodeDeviceCapMdevDefFormat(&buf, data, inactive_state);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_CCW_DEV:
|
case VIR_NODE_DEV_CAP_CCW_DEV:
|
||||||
virNodeDeviceCapCCWDefFormat(&buf, data);
|
virNodeDeviceCapCCWDefFormat(&buf, data);
|
||||||
@ -2207,7 +2217,7 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
|||||||
|
|
||||||
ctxt->node = node;
|
ctxt->node = node;
|
||||||
|
|
||||||
if (!(mdev->dev_config.type = virXPathString("string(./type[1]/@id)", ctxt))) {
|
if (!(mdev->defined_config.type = virXPathString("string(./type[1]/@id)", ctxt))) {
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
_("missing type id attribute for '%1$s'"), def->name);
|
_("missing type id attribute for '%1$s'"), def->name);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2239,7 +2249,7 @@ virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < nattrs; i++)
|
for (i = 0; i < nattrs; i++)
|
||||||
virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], &mdev->dev_config);
|
virNodeDevCapMdevAttributeParseXML(ctxt, attrs[i], &mdev->defined_config);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2582,11 +2592,15 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps)
|
|||||||
g_free(data->sg.path);
|
g_free(data->sg.path);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
g_free(data->mdev.dev_config.type);
|
g_free(data->mdev.defined_config.type);
|
||||||
|
g_free(data->mdev.active_config.type);
|
||||||
g_free(data->mdev.uuid);
|
g_free(data->mdev.uuid);
|
||||||
for (i = 0; i < data->mdev.dev_config.nattributes; i++)
|
for (i = 0; i < data->mdev.defined_config.nattributes; i++)
|
||||||
virMediatedDeviceAttrFree(data->mdev.dev_config.attributes[i]);
|
virMediatedDeviceAttrFree(data->mdev.defined_config.attributes[i]);
|
||||||
g_free(data->mdev.dev_config.attributes);
|
g_free(data->mdev.defined_config.attributes);
|
||||||
|
for (i = 0; i < data->mdev.active_config.nattributes; i++)
|
||||||
|
virMediatedDeviceAttrFree(data->mdev.active_config.attributes[i]);
|
||||||
|
g_free(data->mdev.active_config.attributes);
|
||||||
g_free(data->mdev.parent_addr);
|
g_free(data->mdev.parent_addr);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_CSS_DEV:
|
case VIR_NODE_DEV_CAP_CSS_DEV:
|
||||||
|
@ -153,7 +153,8 @@ typedef struct _virNodeDevCapMdev virNodeDevCapMdev;
|
|||||||
struct _virNodeDevCapMdev {
|
struct _virNodeDevCapMdev {
|
||||||
unsigned int iommuGroupNumber;
|
unsigned int iommuGroupNumber;
|
||||||
char *uuid;
|
char *uuid;
|
||||||
virMediatedDeviceConfig dev_config;
|
virMediatedDeviceConfig defined_config;
|
||||||
|
virMediatedDeviceConfig active_config;
|
||||||
char *parent_addr;
|
char *parent_addr;
|
||||||
bool autostart;
|
bool autostart;
|
||||||
};
|
};
|
||||||
@ -360,7 +361,7 @@ struct _virNodeDeviceDef {
|
|||||||
};
|
};
|
||||||
|
|
||||||
char *
|
char *
|
||||||
virNodeDeviceDefFormat(const virNodeDeviceDef *def);
|
virNodeDeviceDefFormat(const virNodeDeviceDef *def, unsigned int flags);
|
||||||
|
|
||||||
|
|
||||||
typedef int (*virNodeDeviceDefPostParseCallback)(virNodeDeviceDef *dev,
|
typedef int (*virNodeDeviceDefPostParseCallback)(virNodeDeviceDef *dev,
|
||||||
|
@ -264,7 +264,7 @@ virNodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,
|
|||||||
/**
|
/**
|
||||||
* virNodeDeviceGetXMLDesc:
|
* virNodeDeviceGetXMLDesc:
|
||||||
* @dev: pointer to the node device
|
* @dev: pointer to the node device
|
||||||
* @flags: extra flags; not used yet, so callers should always pass 0
|
* @flags: bitwise-OR of virNodeDeviceXMLFlags
|
||||||
*
|
*
|
||||||
* Fetch an XML document describing all aspects of
|
* Fetch an XML document describing all aspects of
|
||||||
* the device.
|
* the device.
|
||||||
|
@ -338,7 +338,7 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr device,
|
|||||||
virNodeDeviceDef *def;
|
virNodeDeviceDef *def;
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
|
|
||||||
virCheckFlags(0, NULL);
|
virCheckFlags(VIR_NODE_DEVICE_XML_INACTIVE, NULL);
|
||||||
|
|
||||||
if (nodeDeviceInitWait() < 0)
|
if (nodeDeviceInitWait() < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -356,7 +356,19 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr device,
|
|||||||
if (virNodeDeviceUpdateCaps(def) < 0)
|
if (virNodeDeviceUpdateCaps(def) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
ret = virNodeDeviceDefFormat(def);
|
if (flags & VIR_NODE_DEVICE_XML_INACTIVE) {
|
||||||
|
if (!virNodeDeviceObjIsPersistent(obj)) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
_("node device '%1$s' is not persistent"),
|
||||||
|
def->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!virNodeDeviceObjIsActive(obj))
|
||||||
|
flags |= VIR_NODE_DEVICE_XML_INACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virNodeDeviceDefFormat(def, flags);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virNodeDeviceObjEndAPI(&obj);
|
virNodeDeviceObjEndAPI(&obj);
|
||||||
@ -629,19 +641,20 @@ nodeDeviceAttributesToJSON(virJSONValue *json,
|
|||||||
/* format a json string that provides configuration information about this mdev
|
/* format a json string that provides configuration information about this mdev
|
||||||
* to the mdevctl utility */
|
* to the mdevctl utility */
|
||||||
static int
|
static int
|
||||||
nodeDeviceDefToMdevctlConfig(virNodeDeviceDef *def, char **buf)
|
nodeDeviceDefToMdevctlConfig(virNodeDeviceDef *def, char **buf, bool defined)
|
||||||
{
|
{
|
||||||
virNodeDevCapMdev *mdev = &def->caps->data.mdev;
|
virNodeDevCapMdev *mdev = &def->caps->data.mdev;
|
||||||
|
virMediatedDeviceConfig *mdev_config = defined ? &mdev->defined_config : &mdev->active_config;
|
||||||
g_autoptr(virJSONValue) json = virJSONValueNewObject();
|
g_autoptr(virJSONValue) json = virJSONValueNewObject();
|
||||||
const char *startval = mdev->autostart ? "auto" : "manual";
|
const char *startval = mdev->autostart ? "auto" : "manual";
|
||||||
|
|
||||||
if (virJSONValueObjectAppendString(json, "mdev_type", mdev->dev_config.type) < 0)
|
if (virJSONValueObjectAppendString(json, "mdev_type", mdev_config->type) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (virJSONValueObjectAppendString(json, "start", startval) < 0)
|
if (virJSONValueObjectAppendString(json, "start", startval) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (nodeDeviceAttributesToJSON(json, &mdev->dev_config) < 0)
|
if (nodeDeviceAttributesToJSON(json, mdev_config) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*buf = virJSONValueToString(json, false);
|
*buf = virJSONValueToString(json, false);
|
||||||
@ -760,7 +773,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodeDeviceDefToMdevctlConfig(def, &inbuf) < 0) {
|
if (nodeDeviceDefToMdevctlConfig(def, &inbuf, true) < 0) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("couldn't convert node device def to mdevctl JSON"));
|
_("couldn't convert node device def to mdevctl JSON"));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1139,9 +1152,11 @@ nodeDeviceParseMdevctlAttributes(virMediatedDeviceConfig *config,
|
|||||||
|
|
||||||
static virNodeDeviceDef*
|
static virNodeDeviceDef*
|
||||||
nodeDeviceParseMdevctlChildDevice(const char *parent,
|
nodeDeviceParseMdevctlChildDevice(const char *parent,
|
||||||
virJSONValue *json)
|
virJSONValue *json,
|
||||||
|
bool defined)
|
||||||
{
|
{
|
||||||
virNodeDevCapMdev *mdev;
|
virNodeDevCapMdev *mdev;
|
||||||
|
virMediatedDeviceConfig *mdev_config;
|
||||||
const char *uuid;
|
const char *uuid;
|
||||||
virJSONValue *props;
|
virJSONValue *props;
|
||||||
g_autoptr(virNodeDeviceDef) child = g_new0(virNodeDeviceDef, 1);
|
g_autoptr(virNodeDeviceDef) child = g_new0(virNodeDeviceDef, 1);
|
||||||
@ -1171,14 +1186,15 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
|
|||||||
child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
|
child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
|
||||||
|
|
||||||
mdev = &child->caps->data.mdev;
|
mdev = &child->caps->data.mdev;
|
||||||
|
mdev_config = defined ? &mdev->defined_config : &mdev->active_config;
|
||||||
mdev->uuid = g_strdup(uuid);
|
mdev->uuid = g_strdup(uuid);
|
||||||
mdev->parent_addr = g_strdup(parent);
|
mdev->parent_addr = g_strdup(parent);
|
||||||
mdev->dev_config.type =
|
mdev_config->type =
|
||||||
g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
|
g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
|
||||||
start = virJSONValueObjectGetString(props, "start");
|
start = virJSONValueObjectGetString(props, "start");
|
||||||
mdev->autostart = STREQ_NULLABLE(start, "auto");
|
mdev->autostart = STREQ_NULLABLE(start, "auto");
|
||||||
|
|
||||||
if (nodeDeviceParseMdevctlAttributes(&mdev->dev_config,
|
if (nodeDeviceParseMdevctlAttributes(mdev_config,
|
||||||
virJSONValueObjectGet(props, "attrs")) < 0)
|
virJSONValueObjectGet(props, "attrs")) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -1190,7 +1206,8 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
|
|||||||
|
|
||||||
int
|
int
|
||||||
nodeDeviceParseMdevctlJSON(const char *jsonstring,
|
nodeDeviceParseMdevctlJSON(const char *jsonstring,
|
||||||
virNodeDeviceDef ***devs)
|
virNodeDeviceDef ***devs,
|
||||||
|
bool defined)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
g_autoptr(virJSONValue) json_devicelist = NULL;
|
g_autoptr(virJSONValue) json_devicelist = NULL;
|
||||||
@ -1260,7 +1277,7 @@ nodeDeviceParseMdevctlJSON(const char *jsonstring,
|
|||||||
g_autoptr(virNodeDeviceDef) child = NULL;
|
g_autoptr(virNodeDeviceDef) child = NULL;
|
||||||
virJSONValue *child_obj = virJSONValueArrayGet(child_array, j);
|
virJSONValue *child_obj = virJSONValueArrayGet(child_array, j);
|
||||||
|
|
||||||
if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj))) {
|
if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj, defined))) {
|
||||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("Unable to parse child device"));
|
_("Unable to parse child device"));
|
||||||
goto error;
|
goto error;
|
||||||
@ -1403,7 +1420,7 @@ nodeDeviceUpdateMediatedDevice(virNodeDeviceDef *def,
|
|||||||
/* Active devices contain some additional information (e.g. sysfs
|
/* Active devices contain some additional information (e.g. sysfs
|
||||||
* path) that is not provided by mdevctl, so re-use the existing
|
* path) that is not provided by mdevctl, so re-use the existing
|
||||||
* definition and copy over new mdev data */
|
* definition and copy over new mdev data */
|
||||||
changed = nodeDeviceDefCopyFromMdevctl(olddef, owned);
|
changed = nodeDeviceDefCopyFromMdevctl(olddef, owned, defined);
|
||||||
|
|
||||||
if (was_defined && !changed) {
|
if (was_defined && !changed) {
|
||||||
/* if this device was already defined and the definition
|
/* if this device was already defined and the definition
|
||||||
@ -1673,7 +1690,7 @@ virMdevctlList(bool defined,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeDeviceParseMdevctlJSON(output, devs);
|
return nodeDeviceParseMdevctlJSON(output, devs, defined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1830,16 +1847,24 @@ virMediatedDeviceAttrsCopy(virMediatedDeviceConfig *dst_config,
|
|||||||
* Returns true if anything was copied, else returns false */
|
* Returns true if anything was copied, else returns false */
|
||||||
bool
|
bool
|
||||||
nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
|
nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
|
||||||
virNodeDeviceDef *src)
|
virNodeDeviceDef *src,
|
||||||
|
bool defined)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
virNodeDevCapMdev *srcmdev = &src->caps->data.mdev;
|
virNodeDevCapMdev *srcmdev = &src->caps->data.mdev;
|
||||||
virNodeDevCapMdev *dstmdev = &dst->caps->data.mdev;
|
virNodeDevCapMdev *dstmdev = &dst->caps->data.mdev;
|
||||||
|
virMediatedDeviceConfig *srcmdevconfig = &src->caps->data.mdev.active_config;
|
||||||
|
virMediatedDeviceConfig *dstmdevconfig = &dst->caps->data.mdev.active_config;
|
||||||
|
|
||||||
if (STRNEQ_NULLABLE(dstmdev->dev_config.type, srcmdev->dev_config.type)) {
|
if (defined) {
|
||||||
|
srcmdevconfig = &src->caps->data.mdev.defined_config;
|
||||||
|
dstmdevconfig = &dst->caps->data.mdev.defined_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STRNEQ_NULLABLE(dstmdevconfig->type, srcmdevconfig->type)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
g_free(dstmdev->dev_config.type);
|
g_free(dstmdevconfig->type);
|
||||||
dstmdev->dev_config.type = g_strdup(srcmdev->dev_config.type);
|
dstmdevconfig->type = g_strdup(srcmdevconfig->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STRNEQ_NULLABLE(dstmdev->uuid, srcmdev->uuid)) {
|
if (STRNEQ_NULLABLE(dstmdev->uuid, srcmdev->uuid)) {
|
||||||
@ -1848,7 +1873,7 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
|
|||||||
dstmdev->uuid = g_strdup(srcmdev->uuid);
|
dstmdev->uuid = g_strdup(srcmdev->uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virMediatedDeviceAttrsCopy(&dstmdev->dev_config, &srcmdev->dev_config))
|
if (virMediatedDeviceAttrsCopy(dstmdevconfig, srcmdevconfig))
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
if (dstmdev->autostart != srcmdev->autostart) {
|
if (dstmdev->autostart != srcmdev->autostart) {
|
||||||
|
@ -142,7 +142,8 @@ nodeDeviceGetMdevctlListCommand(bool defined,
|
|||||||
|
|
||||||
int
|
int
|
||||||
nodeDeviceParseMdevctlJSON(const char *jsonstring,
|
nodeDeviceParseMdevctlJSON(const char *jsonstring,
|
||||||
virNodeDeviceDef ***devs);
|
virNodeDeviceDef ***devs,
|
||||||
|
bool defined);
|
||||||
|
|
||||||
int
|
int
|
||||||
nodeDeviceUpdateMediatedDevices(void);
|
nodeDeviceUpdateMediatedDevices(void);
|
||||||
@ -154,7 +155,8 @@ nodeDeviceGenerateName(virNodeDeviceDef *def,
|
|||||||
const char *s);
|
const char *s);
|
||||||
|
|
||||||
bool nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
|
bool nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
|
||||||
virNodeDeviceDef *src);
|
virNodeDeviceDef *src,
|
||||||
|
bool defined);
|
||||||
|
|
||||||
int
|
int
|
||||||
nodeDeviceCreate(virNodeDevice *dev,
|
nodeDeviceCreate(virNodeDevice *dev,
|
||||||
|
@ -1069,7 +1069,7 @@ udevProcessMediatedDevice(struct udev_device *dev,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->dev_config.type = g_path_get_basename(canonicalpath);
|
data->active_config.type = g_path_get_basename(canonicalpath);
|
||||||
|
|
||||||
data->uuid = g_strdup(udev_device_get_sysname(dev));
|
data->uuid = g_strdup(udev_device_get_sysname(dev));
|
||||||
if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(data->uuid)) < 0)
|
if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(data->uuid)) < 0)
|
||||||
@ -1572,7 +1572,7 @@ udevAddOneDevice(struct udev_device *device)
|
|||||||
objdef = virNodeDeviceObjGetDef(obj);
|
objdef = virNodeDeviceObjGetDef(obj);
|
||||||
|
|
||||||
if (is_mdev)
|
if (is_mdev)
|
||||||
nodeDeviceDefCopyFromMdevctl(def, objdef);
|
nodeDeviceDefCopyFromMdevctl(def, objdef, false);
|
||||||
|
|
||||||
persistent = virNodeDeviceObjIsPersistent(obj);
|
persistent = virNodeDeviceObjIsPersistent(obj);
|
||||||
autostart = virNodeDeviceObjIsAutostart(obj);
|
autostart = virNodeDeviceObjIsAutostart(obj);
|
||||||
|
@ -7514,12 +7514,12 @@ testNodeDeviceGetXMLDesc(virNodeDevicePtr dev,
|
|||||||
virNodeDeviceObj *obj;
|
virNodeDeviceObj *obj;
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
|
|
||||||
virCheckFlags(0, NULL);
|
virCheckFlags(VIR_NODE_DEVICE_XML_INACTIVE, NULL);
|
||||||
|
|
||||||
if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
|
if (!(obj = testNodeDeviceObjFindByName(driver, dev->name)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj));
|
ret = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(obj), flags);
|
||||||
|
|
||||||
virNodeDeviceObjEndAPI(&obj);
|
virNodeDeviceObjEndAPI(&obj);
|
||||||
return ret;
|
return ret;
|
||||||
@ -7619,7 +7619,7 @@ testNodeDeviceMockCreateVport(testDriver *driver,
|
|||||||
"scsi_host11")))
|
"scsi_host11")))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy));
|
xml = virNodeDeviceDefFormat(virNodeDeviceObjGetDef(objcopy), 0);
|
||||||
virNodeDeviceObjEndAPI(&objcopy);
|
virNodeDeviceObjEndAPI(&objcopy);
|
||||||
if (!xml)
|
if (!xml)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -229,13 +229,13 @@ testMdevctlParse(const void *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nmdevs = nodeDeviceParseMdevctlJSON(buf, &mdevs)) < 0) {
|
if ((nmdevs = nodeDeviceParseMdevctlJSON(buf, &mdevs, true)) < 0) {
|
||||||
VIR_TEST_DEBUG("Unable to parse json for %s", filename);
|
VIR_TEST_DEBUG("Unable to parse json for %s", filename);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nmdevs; i++) {
|
for (i = 0; i < nmdevs; i++) {
|
||||||
g_autofree char *devxml = virNodeDeviceDefFormat(mdevs[i]);
|
g_autofree char *devxml = virNodeDeviceDefFormat(mdevs[i], VIR_NODE_DEVICE_XML_INACTIVE);
|
||||||
if (!devxml)
|
if (!devxml)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
virBufferAddStr(&xmloutbuf, devxml);
|
virBufferAddStr(&xmloutbuf, devxml);
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
<device>
|
||||||
|
<name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
|
||||||
|
<path>/sys/devices/css0/0.0.0052/c60cc60c-c60c-c60c-c60c-c60cc60cc60c</path>
|
||||||
|
<parent>css_0_0_0052</parent>
|
||||||
|
<driver>
|
||||||
|
<name>vfio_ccw_mdev</name>
|
||||||
|
</driver>
|
||||||
|
<capability type='mdev'>
|
||||||
|
<type id='vfio_ccw-io'/>
|
||||||
|
<uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
|
||||||
|
<parent_addr>0.0.0052</parent_addr>
|
||||||
|
<iommuGroup number='4'/>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -0,0 +1 @@
|
|||||||
|
mdev_3627463d_b7f0_4fea_b468_f1da537d301b.xml
|
@ -0,0 +1,10 @@
|
|||||||
|
<device>
|
||||||
|
<name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
|
||||||
|
<path>/sys/devices/css0/0.0.0052/c60cc60c-c60c-c60c-c60c-c60cc60cc60c</path>
|
||||||
|
<parent>css_0_0_0052</parent>
|
||||||
|
<capability type='mdev'>
|
||||||
|
<type id='vfio_ccw-io'/>
|
||||||
|
<uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
|
||||||
|
<iommuGroup number='4'/>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -0,0 +1,9 @@
|
|||||||
|
<device>
|
||||||
|
<name>mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c_0_0_0052</name>
|
||||||
|
<parent>css_0_0_0052</parent>
|
||||||
|
<capability type='mdev'>
|
||||||
|
<type id='vfio_ccw-io'/>
|
||||||
|
<uuid>c60cc60c-c60c-c60c-c60c-c60cc60cc60c</uuid>
|
||||||
|
<iommuGroup number='4'/>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -0,0 +1 @@
|
|||||||
|
mdev_d069d019_36ea_4111_8f0a_8c9a70e21366.xml
|
@ -0,0 +1 @@
|
|||||||
|
mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9.xml
|
@ -0,0 +1,8 @@
|
|||||||
|
<device>
|
||||||
|
<name>mdev_ee0b88c4-f554-4dc1-809d-b2a01e8e48ad</name>
|
||||||
|
<parent>ap_matrix</parent>
|
||||||
|
<capability type='mdev'>
|
||||||
|
<type id='vfio_ap-passthrough'/>
|
||||||
|
<iommuGroup number='0'/>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -0,0 +1 @@
|
|||||||
|
mdev_fedc4916_1ca8_49ac_b176_871d16c13076.xml
|
@ -11,14 +11,20 @@
|
|||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_NONE
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
||||||
|
|
||||||
|
struct TestData {
|
||||||
|
const char *filename;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
testCompareXMLToXMLFiles(const char *xml, const char *outfile)
|
testCompareXMLToXMLFiles(const char *xml, const char *outfile, unsigned int flags)
|
||||||
{
|
{
|
||||||
g_autofree char *xmlData = NULL;
|
g_autofree char *xmlData = NULL;
|
||||||
g_autofree char *actual = NULL;
|
g_autofree char *actual = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
virNodeDeviceDef *dev = NULL;
|
virNodeDeviceDef *dev = NULL;
|
||||||
virNodeDevCapsDef *caps;
|
virNodeDevCapsDef *caps;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (virTestLoadFile(xml, &xmlData) < 0)
|
if (virTestLoadFile(xml, &xmlData) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -46,9 +52,23 @@ testCompareXMLToXMLFiles(const char *xml, const char *outfile)
|
|||||||
data->storage.logical_block_size;
|
data->storage.logical_block_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (caps->data.type == VIR_NODE_DEV_CAP_MDEV &&
|
||||||
|
!(flags & VIR_NODE_DEVICE_XML_INACTIVE)) {
|
||||||
|
data->mdev.active_config.type = g_strdup(data->mdev.defined_config.type);
|
||||||
|
for (i = 0; i < data->mdev.defined_config.nattributes; i++) {
|
||||||
|
g_autoptr(virMediatedDeviceAttr) attr = g_new0(virMediatedDeviceAttr, 1);
|
||||||
|
|
||||||
|
attr->name = g_strdup(data->mdev.defined_config.attributes[i]->name);
|
||||||
|
attr->value = g_strdup(data->mdev.defined_config.attributes[i]->value);
|
||||||
|
VIR_APPEND_ELEMENT(data->mdev.active_config.attributes,
|
||||||
|
data->mdev.active_config.nattributes,
|
||||||
|
attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(actual = virNodeDeviceDefFormat(dev)))
|
if (!(actual = virNodeDeviceDefFormat(dev, flags)))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (virTestCompareToFile(actual, outfile) < 0)
|
if (virTestCompareToFile(actual, outfile) < 0)
|
||||||
@ -65,16 +85,21 @@ static int
|
|||||||
testCompareXMLToXMLHelper(const void *data)
|
testCompareXMLToXMLHelper(const void *data)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
const struct TestData *tdata = data;
|
||||||
g_autofree char *xml = NULL;
|
g_autofree char *xml = NULL;
|
||||||
g_autofree char *outfile = NULL;
|
g_autofree char *outfile = NULL;
|
||||||
|
|
||||||
xml = g_strdup_printf("%s/nodedevschemadata/%s.xml", abs_srcdir,
|
xml = g_strdup_printf("%s/nodedevschemadata/%s.xml", abs_srcdir,
|
||||||
(const char *)data);
|
tdata->filename);
|
||||||
|
|
||||||
outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s.xml", abs_srcdir,
|
if (tdata->flags & VIR_NODE_DEVICE_XML_INACTIVE)
|
||||||
(const char *)data);
|
outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s_inactive.xml", abs_srcdir,
|
||||||
|
tdata->filename);
|
||||||
|
else
|
||||||
|
outfile = g_strdup_printf("%s/nodedevxml2xmlout/%s.xml", abs_srcdir,
|
||||||
|
tdata->filename);
|
||||||
|
|
||||||
result = testCompareXMLToXMLFiles(xml, outfile);
|
result = testCompareXMLToXMLFiles(xml, outfile, tdata->flags);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -85,10 +110,20 @@ mymain(void)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
#define DO_TEST_FLAGS(desc, filename, flags) \
|
||||||
|
do { \
|
||||||
|
struct TestData data = { filename, flags }; \
|
||||||
|
if (virTestRun(desc, testCompareXMLToXMLHelper, &data) < 0) \
|
||||||
|
ret = -1; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
#define DO_TEST(name) \
|
#define DO_TEST(name) \
|
||||||
if (virTestRun("Node device XML-2-XML " name, \
|
DO_TEST_FLAGS("Node device XML-2-XML " name, name, 0)
|
||||||
testCompareXMLToXMLHelper, (name)) < 0) \
|
|
||||||
ret = -1
|
#define DO_TEST_INACTIVE(name) \
|
||||||
|
DO_TEST_FLAGS("Node device XML-2-XML INACTIVE " name, \
|
||||||
|
name, VIR_NODE_DEVICE_XML_INACTIVE)
|
||||||
|
|
||||||
DO_TEST("computer");
|
DO_TEST("computer");
|
||||||
DO_TEST("DVD_GCC_4247N");
|
DO_TEST("DVD_GCC_4247N");
|
||||||
@ -121,6 +156,7 @@ mymain(void)
|
|||||||
DO_TEST("pci_0000_02_10_7_mdev_types");
|
DO_TEST("pci_0000_02_10_7_mdev_types");
|
||||||
DO_TEST("pci_0000_42_00_0_vpd");
|
DO_TEST("pci_0000_42_00_0_vpd");
|
||||||
DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
|
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_ffff");
|
||||||
DO_TEST("css_0_0_ffff");
|
DO_TEST("css_0_0_ffff");
|
||||||
DO_TEST("css_0_0_ffff_channel_dev_addr");
|
DO_TEST("css_0_0_ffff_channel_dev_addr");
|
||||||
@ -134,7 +170,13 @@ mymain(void)
|
|||||||
DO_TEST("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
|
DO_TEST("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
|
||||||
DO_TEST("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
|
DO_TEST("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
|
||||||
DO_TEST("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
|
DO_TEST("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
|
||||||
|
DO_TEST_INACTIVE("mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad");
|
||||||
|
DO_TEST_INACTIVE("mdev_d069d019_36ea_4111_8f0a_8c9a70e21366");
|
||||||
|
DO_TEST_INACTIVE("mdev_d2441d39_495e_4243_ad9f_beb3f14c23d9");
|
||||||
|
DO_TEST_INACTIVE("mdev_fedc4916_1ca8_49ac_b176_871d16c13076");
|
||||||
DO_TEST("hba_vport_ops");
|
DO_TEST("hba_vport_ops");
|
||||||
|
DO_TEST("mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c");
|
||||||
|
DO_TEST_INACTIVE("mdev_c60cc60c_c60c_c60c_c60c_c60cc60cc60c");
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user