mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 07:17:44 +00:00
qemu: Add support for parsing iotune group setting
Add support to read/parse the iotune group setting for qemu. Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
d0f82df205
commit
c53bd25b13
@ -3964,6 +3964,14 @@ typedef void (*virConnectDomainEventJobCompletedCallback)(virConnectPtr conn,
|
||||
*/
|
||||
# define VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC "blkdeviotune.size_iops_sec"
|
||||
|
||||
/**
|
||||
* VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME:
|
||||
*
|
||||
* Macro represents the group name to be used,
|
||||
* as VIR_TYPED_PARAM_STRING.
|
||||
*/
|
||||
# define VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME "blkdeviotune.group_name"
|
||||
|
||||
/**
|
||||
* VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH:
|
||||
*
|
||||
|
@ -1656,6 +1656,7 @@ virDomainDiskDefFree(virDomainDiskDefPtr def)
|
||||
VIR_FREE(def->vendor);
|
||||
VIR_FREE(def->product);
|
||||
VIR_FREE(def->domain_name);
|
||||
VIR_FREE(def->blkdeviotune.group_name);
|
||||
virDomainDeviceInfoClear(&def->info);
|
||||
virObjectUnref(def->privateData);
|
||||
|
||||
|
@ -566,6 +566,7 @@ struct _virDomainBlockIoTuneInfo {
|
||||
unsigned long long read_iops_sec_max;
|
||||
unsigned long long write_iops_sec_max;
|
||||
unsigned long long size_iops_sec;
|
||||
char *group_name;
|
||||
unsigned long long total_bytes_sec_max_length;
|
||||
unsigned long long read_bytes_sec_max_length;
|
||||
unsigned long long write_bytes_sec_max_length;
|
||||
|
@ -115,8 +115,10 @@ VIR_LOG_INIT("qemu.qemu_driver");
|
||||
#define QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS 6
|
||||
#define QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS 7
|
||||
#define QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS 6
|
||||
#define QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS 1
|
||||
#define QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS (QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS + \
|
||||
QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS + \
|
||||
QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS + \
|
||||
QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS)
|
||||
|
||||
#define QEMU_NB_NUMA_PARAM 2
|
||||
@ -17343,8 +17345,9 @@ typedef enum {
|
||||
QEMU_BLOCK_IOTUNE_SET_BYTES_MAX = 1 << 2,
|
||||
QEMU_BLOCK_IOTUNE_SET_IOPS_MAX = 1 << 3,
|
||||
QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS = 1 << 4,
|
||||
QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH = 1 << 5,
|
||||
QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH = 1 << 6,
|
||||
QEMU_BLOCK_IOTUNE_SET_GROUP_NAME = 1 << 5,
|
||||
QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH = 1 << 6,
|
||||
QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH = 1 << 7,
|
||||
} qemuBlockIoTuneSetFlags;
|
||||
|
||||
|
||||
@ -17370,6 +17373,8 @@ qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfoPtr newinfo,
|
||||
|
||||
if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_SIZE_IOPS))
|
||||
newinfo->size_iops_sec = oldinfo->size_iops_sec;
|
||||
if (!(set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME))
|
||||
VIR_STEAL_PTR(newinfo->group_name, oldinfo->group_name);
|
||||
|
||||
/* The length field is handled a bit differently. If not defined/set,
|
||||
* QEMU will default these to 0 or 1 depending on whether something in
|
||||
@ -17424,6 +17429,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
virDomainDiskDefPtr disk;
|
||||
qemuBlockIoTuneSetFlags set_fields = 0;
|
||||
bool supportMaxOptions = true;
|
||||
bool supportGroupNameOption = true;
|
||||
bool supportMaxLengthOptions = true;
|
||||
virQEMUDriverConfigPtr cfg = NULL;
|
||||
virObjectEventPtr event = NULL;
|
||||
@ -17460,6 +17466,8 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
|
||||
VIR_TYPED_PARAM_STRING,
|
||||
VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
|
||||
VIR_TYPED_PARAM_ULLONG,
|
||||
VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
|
||||
@ -17540,6 +17548,19 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
WRITE_IOPS_SEC_MAX);
|
||||
SET_IOTUNE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC);
|
||||
|
||||
/* NB: Cannot use macro since this is a value.s not a value.ul */
|
||||
if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) {
|
||||
if (VIR_STRDUP(info.group_name, params->value.s) < 0)
|
||||
goto endjob;
|
||||
set_fields |= QEMU_BLOCK_IOTUNE_SET_GROUP_NAME;
|
||||
if (virTypedParamsAddString(&eventParams, &eventNparams,
|
||||
&eventMaxparams,
|
||||
VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NAME,
|
||||
param->value.s) < 0)
|
||||
goto endjob;
|
||||
continue;
|
||||
}
|
||||
|
||||
SET_IOTUNE_FIELD(total_bytes_sec_max_length, BYTES_MAX_LENGTH,
|
||||
TOTAL_BYTES_SEC_MAX_LENGTH);
|
||||
SET_IOTUNE_FIELD(read_bytes_sec_max_length, BYTES_MAX_LENGTH,
|
||||
@ -17591,6 +17612,8 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
if (def) {
|
||||
supportMaxOptions = virQEMUCapsGet(priv->qemuCaps,
|
||||
QEMU_CAPS_DRIVE_IOTUNE_MAX);
|
||||
supportGroupNameOption = virQEMUCapsGet(priv->qemuCaps,
|
||||
QEMU_CAPS_DRIVE_IOTUNE_GROUP);
|
||||
supportMaxLengthOptions =
|
||||
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH);
|
||||
|
||||
@ -17611,6 +17634,14 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if (!supportGroupNameOption &&
|
||||
(set_fields & QEMU_BLOCK_IOTUNE_SET_GROUP_NAME)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("the block I/O throttling group parameter is not "
|
||||
"supported with this QEMU binary"));
|
||||
goto endjob;
|
||||
}
|
||||
|
||||
if (!supportMaxLengthOptions &&
|
||||
(set_fields & (QEMU_BLOCK_IOTUNE_SET_BYTES_MAX_LENGTH |
|
||||
QEMU_BLOCK_IOTUNE_SET_IOPS_MAX_LENGTH))) {
|
||||
@ -17655,12 +17686,14 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
qemuDomainObjEnterMonitor(driver, vm);
|
||||
ret = qemuMonitorSetBlockIoThrottle(priv->mon, device,
|
||||
&info, supportMaxOptions,
|
||||
supportGroupNameOption,
|
||||
supportMaxLengthOptions);
|
||||
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
||||
ret = -1;
|
||||
if (ret < 0)
|
||||
goto endjob;
|
||||
disk->blkdeviotune = info;
|
||||
info.group_name = NULL;
|
||||
|
||||
ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps);
|
||||
if (ret < 0)
|
||||
@ -17683,6 +17716,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
qemuDomainSetBlockIoTuneDefaults(&info, &conf_disk->blkdeviotune,
|
||||
set_fields);
|
||||
conf_disk->blkdeviotune = info;
|
||||
info.group_name = NULL;
|
||||
ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
|
||||
if (ret < 0)
|
||||
goto endjob;
|
||||
@ -17693,6 +17727,7 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
|
||||
qemuDomainObjEndJob(driver, vm);
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(info.group_name);
|
||||
VIR_FREE(device);
|
||||
virDomainObjEndAPI(&vm);
|
||||
if (eventNparams)
|
||||
@ -17714,7 +17749,7 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
|
||||
qemuDomainObjPrivatePtr priv = NULL;
|
||||
virDomainDefPtr def = NULL;
|
||||
virDomainDefPtr persistentDef = NULL;
|
||||
virDomainBlockIoTuneInfo reply;
|
||||
virDomainBlockIoTuneInfo reply = {0};
|
||||
char *device = NULL;
|
||||
int ret = -1;
|
||||
int maxparams;
|
||||
@ -17754,6 +17789,8 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
|
||||
maxparams = QEMU_NB_BLOCK_IO_TUNE_BASE_PARAMS;
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX))
|
||||
maxparams += QEMU_NB_BLOCK_IO_TUNE_MAX_PARAMS;
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_GROUP))
|
||||
maxparams += QEMU_NB_BLOCK_IO_TUNE_GROUP_PARAMS;
|
||||
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH))
|
||||
maxparams += QEMU_NB_BLOCK_IO_TUNE_LENGTH_PARAMS;
|
||||
} else {
|
||||
@ -17821,6 +17858,14 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
|
||||
|
||||
BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
|
||||
|
||||
/* NB: Cannot use macro since this is a STRING not a ULLONG */
|
||||
if (*nparams < maxparams &&
|
||||
virTypedParameterAssign(¶ms[(*nparams)++],
|
||||
VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME,
|
||||
VIR_TYPED_PARAM_STRING,
|
||||
reply.group_name) < 0)
|
||||
goto endjob;
|
||||
|
||||
BLOCK_IOTUNE_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_length);
|
||||
BLOCK_IOTUNE_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_length);
|
||||
BLOCK_IOTUNE_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_length);
|
||||
|
@ -3471,6 +3471,7 @@ qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockIoTuneInfoPtr info,
|
||||
bool supportMaxOptions,
|
||||
bool supportGroupNameOption,
|
||||
bool supportMaxLengthOptions)
|
||||
{
|
||||
VIR_DEBUG("device=%p, info=%p", device, info);
|
||||
@ -3480,6 +3481,7 @@ qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
if (mon->json)
|
||||
return qemuMonitorJSONSetBlockIoThrottle(mon, device, info,
|
||||
supportMaxOptions,
|
||||
supportGroupNameOption,
|
||||
supportMaxLengthOptions);
|
||||
else
|
||||
return qemuMonitorTextSetBlockIoThrottle(mon, device, info);
|
||||
|
@ -880,6 +880,7 @@ int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockIoTuneInfoPtr info,
|
||||
bool supportMaxOptions,
|
||||
bool supportGroupNameOption,
|
||||
bool supportMaxLengthOptions);
|
||||
|
||||
int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
|
@ -4521,7 +4521,6 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
|
||||
"was not in expected format"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
GET_THROTTLE_STATS("bps", total_bytes_sec);
|
||||
GET_THROTTLE_STATS("bps_rd", read_bytes_sec);
|
||||
GET_THROTTLE_STATS("bps_wr", write_bytes_sec);
|
||||
@ -4535,6 +4534,11 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
|
||||
GET_THROTTLE_STATS_OPTIONAL("iops_rd_max", read_iops_sec_max);
|
||||
GET_THROTTLE_STATS_OPTIONAL("iops_wr_max", write_iops_sec_max);
|
||||
GET_THROTTLE_STATS_OPTIONAL("iops_size", size_iops_sec);
|
||||
|
||||
if (VIR_STRDUP(reply->group_name,
|
||||
virJSONValueObjectGetString(inserted, "group")) < 0)
|
||||
goto cleanup;
|
||||
|
||||
GET_THROTTLE_STATS_OPTIONAL("bps_max_length", total_bytes_sec_max_length);
|
||||
GET_THROTTLE_STATS_OPTIONAL("bps_rd_max_length", read_bytes_sec_max_length);
|
||||
GET_THROTTLE_STATS_OPTIONAL("bps_wr_max_length", write_bytes_sec_max_length);
|
||||
@ -4563,6 +4567,7 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockIoTuneInfoPtr info,
|
||||
bool supportMaxOptions,
|
||||
bool supportGroupNameOption,
|
||||
bool supportMaxLengthOptions)
|
||||
{
|
||||
int ret = -1;
|
||||
@ -4596,6 +4601,12 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
NULL) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (supportGroupNameOption &&
|
||||
virJSONValueObjectAdd(args,
|
||||
"s:group", info->group_name,
|
||||
NULL) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (supportMaxLengthOptions &&
|
||||
virJSONValueObjectAdd(args,
|
||||
"P:bps_max_length",
|
||||
|
@ -328,6 +328,7 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
const char *device,
|
||||
virDomainBlockIoTuneInfoPtr info,
|
||||
bool supportMaxOptions,
|
||||
bool supportGroupNameOption,
|
||||
bool supportMaxLengthOptions);
|
||||
|
||||
int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
|
||||
|
@ -67,12 +67,13 @@ const char *queryBlockReply =
|
||||
" \"iops_rd_max\": 11,"
|
||||
" \"iops_wr_max\": 12,"
|
||||
" \"iops_size\": 13,"
|
||||
" \"bps_max_length\": 14,"
|
||||
" \"bps_rd_max_length\": 15,"
|
||||
" \"bps_wr_max_length\": 16,"
|
||||
" \"iops_max_length\": 17,"
|
||||
" \"iops_rd_max_length\": 18,"
|
||||
" \"iops_wr_max_length\": 19,"
|
||||
" \"group\": \"group14\","
|
||||
" \"bps_max_length\": 15,"
|
||||
" \"bps_rd_max_length\": 16,"
|
||||
" \"bps_wr_max_length\": 17,"
|
||||
" \"iops_max_length\": 18,"
|
||||
" \"iops_rd_max_length\": 19,"
|
||||
" \"iops_wr_max_length\": 20,"
|
||||
" \"file\": \"/home/zippy/work/tmp/gentoo.qcow2\","
|
||||
" \"encryption_key_missing\": false"
|
||||
" },"
|
||||
@ -2008,6 +2009,55 @@ testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
testValidateGetBlockIoThrottle(virDomainBlockIoTuneInfo info,
|
||||
virDomainBlockIoTuneInfo expectedInfo)
|
||||
{
|
||||
#define VALIDATE_IOTUNE(field) \
|
||||
if (info.field != expectedInfo.field) { \
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
||||
"info.%s=%llu != expected=%llu", \
|
||||
#field, info.field, expectedInfo.field); \
|
||||
return -1; \
|
||||
} \
|
||||
if (info.field##_max != expectedInfo.field##_max) { \
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
||||
"info.%s_max=%llu != expected=%llu", \
|
||||
#field, info.field##_max, expectedInfo.field##_max); \
|
||||
return -1; \
|
||||
} \
|
||||
if (info.field##_max_length != expectedInfo.field##_max_length) { \
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, \
|
||||
"info.%s_max_length=%llu != expected=%llu", \
|
||||
#field, info.field##_max_length, \
|
||||
expectedInfo.field##_max_length); \
|
||||
return -1; \
|
||||
}
|
||||
VALIDATE_IOTUNE(total_bytes_sec);
|
||||
VALIDATE_IOTUNE(read_bytes_sec);
|
||||
VALIDATE_IOTUNE(write_bytes_sec);
|
||||
VALIDATE_IOTUNE(total_iops_sec);
|
||||
VALIDATE_IOTUNE(read_iops_sec);
|
||||
VALIDATE_IOTUNE(write_iops_sec);
|
||||
if (info.size_iops_sec != expectedInfo.size_iops_sec) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"info.size_iops_sec=%llu != expected=%llu",
|
||||
info.size_iops_sec, expectedInfo.size_iops_sec);
|
||||
return -1;
|
||||
}
|
||||
if (STRNEQ(info.group_name, expectedInfo.group_name)) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"info.group_name=%s != expected=%s",
|
||||
info.group_name, expectedInfo.group_name);
|
||||
return -1;
|
||||
}
|
||||
#undef VALIDATE_IOTUNE
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
|
||||
{
|
||||
@ -2019,7 +2069,9 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
|
||||
if (!test)
|
||||
return -1;
|
||||
|
||||
expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
|
||||
expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NULL, 15, 16, 17, 18, 19, 20};
|
||||
if (VIR_STRDUP(expectedInfo.group_name, "group14") < 0)
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 ||
|
||||
qemuMonitorTestAddItemParams(test, "block_set_io_throttle",
|
||||
@ -2031,12 +2083,13 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
|
||||
"bps_wr_max", "9",
|
||||
"iops_max", "10", "iops_rd_max", "11",
|
||||
"iops_wr_max", "12", "iops_size", "13",
|
||||
"bps_max_length", "14",
|
||||
"bps_rd_max_length", "15",
|
||||
"bps_wr_max_length", "16",
|
||||
"iops_max_length", "17",
|
||||
"iops_rd_max_length", "18",
|
||||
"iops_wr_max_length", "19",
|
||||
"group", "\"group14\"",
|
||||
"bps_max_length", "15",
|
||||
"bps_rd_max_length", "16",
|
||||
"bps_wr_max_length", "17",
|
||||
"iops_max_length", "18",
|
||||
"iops_rd_max_length", "19",
|
||||
"iops_wr_max_length", "20",
|
||||
NULL, NULL) < 0)
|
||||
goto cleanup;
|
||||
|
||||
@ -2044,19 +2097,18 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
|
||||
"drive-virtio-disk0", &info) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (memcmp(&info, &expectedInfo, sizeof(info)) != 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
"Invalid @info");
|
||||
if (testValidateGetBlockIoThrottle(info, expectedInfo) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
|
||||
"drive-virtio-disk1", &info, true,
|
||||
true) < 0)
|
||||
true, true) < 0)
|
||||
goto cleanup;
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
VIR_FREE(info.group_name);
|
||||
VIR_FREE(expectedInfo.group_name);
|
||||
qemuMonitorTestFree(test);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user