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:
John Ferlan 2016-10-31 17:22:59 -04:00
parent d0f82df205
commit c53bd25b13
9 changed files with 144 additions and 22 deletions

View File

@ -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:
*

View File

@ -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);

View File

@ -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;

View File

@ -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(&params[(*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);

View File

@ -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);

View File

@ -880,6 +880,7 @@ int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions,
bool supportGroupNameOption,
bool supportMaxLengthOptions);
int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,

View File

@ -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",

View File

@ -328,6 +328,7 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions,
bool supportGroupNameOption,
bool supportMaxLengthOptions);
int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,

View File

@ -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;
}