提交 223438a2 编写于 作者: J John Ferlan

qemu: Add length for bps/iops throttling parameters to driver

Add support for a duration/length for the bps/iops and friends.

Modify the API in order to add the "blkdeviotune." specific definitions
for the iotune throttling duration/length options

    total_bytes_sec_max_length
    write_bytes_sec_max_length
    read_bytes_sec_max_length
    total_iops_sec_max_length
    write_iops_sec_max_length
    read_iops_sec_max_length
上级 d379552b
......@@ -3846,6 +3846,60 @@ typedef void (*virConnectDomainEventJobCompletedCallback)(virConnectPtr conn,
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_SIZE_IOPS_SEC "blkdeviotune.size_iops_sec"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.total_bytes_sec_max,
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_BYTES_SEC_MAX_LENGTH "blkdeviotune.total_bytes_sec_max_length"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.read_bytes_sec_max
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_READ_BYTES_SEC_MAX_LENGTH "blkdeviotune.read_bytes_sec_max_length"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.write_bytes_sec_max
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_BYTES_SEC_MAX_LENGTH "blkdeviotune.write_bytes_sec_max_length"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.total_iops_sec_max
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_TOTAL_IOPS_SEC_MAX_LENGTH "blkdeviotune.total_iops_sec_max_length"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.read_iops_sec_max
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_READ_IOPS_SEC_MAX_LENGTH "blkdeviotune.read_iops_sec_max_length"
/**
* VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH:
*
* Macro represents the length in seconds allowed for a burst period
* for the blkdeviotune.write_iops_sec_max
* as VIR_TYPED_PARAM_ULLONG.
*/
# define VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH "blkdeviotune.write_iops_sec_max_length"
/**
* virConnectDomainEventTunableCallback:
* @conn: connection object
......
......@@ -548,6 +548,12 @@ struct _virDomainBlockIoTuneInfo {
unsigned long long read_iops_sec_max;
unsigned long long write_iops_sec_max;
unsigned long long size_iops_sec;
unsigned long long total_bytes_sec_max_length;
unsigned long long read_bytes_sec_max_length;
unsigned long long write_bytes_sec_max_length;
unsigned long long total_iops_sec_max_length;
unsigned long long read_iops_sec_max_length;
unsigned long long write_iops_sec_max_length;
};
typedef virDomainBlockIoTuneInfo *virDomainBlockIoTuneInfoPtr;
......
......@@ -114,6 +114,7 @@ VIR_LOG_INIT("qemu.qemu_driver");
#define QEMU_NB_BLOCK_IO_TUNE_PARAM 6
#define QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX 13
#define QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX_LENGTH 19
#define QEMU_NB_NUMA_PARAM 2
......@@ -17302,7 +17303,9 @@ qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfoPtr newinfo,
bool set_iops,
bool set_bytes_max,
bool set_iops_max,
bool set_size_iops)
bool set_size_iops,
bool set_bytes_max_length,
bool set_iops_max_length)
{
#define SET_IOTUNE_DEFAULTS(BOOL, FIELD) \
if (!BOOL) { \
......@@ -17319,6 +17322,36 @@ qemuDomainSetBlockIoTuneDefaults(virDomainBlockIoTuneInfoPtr newinfo,
if (!set_size_iops)
newinfo->size_iops_sec = oldinfo->size_iops_sec;
/* 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
* the same family is set or not.
*
* Similar to other values, if nothing in the family is defined/set,
* then take whatever is in the oldinfo.
*
* To clear an existing limit, a 0 is provided; however, passing that
* 0 onto QEMU if there's a family value defined/set (or defaulted)
* will cause an error. So, to mimic that, if our oldinfo was set and
* our newinfo is clearing, then set max_length based on whether we
* have a value in the family set/defined. */
#define SET_MAX_LENGTH(BOOL, FIELD) \
if (!BOOL) \
newinfo->FIELD##_max_length = oldinfo->FIELD##_max_length; \
else if (BOOL && oldinfo->FIELD##_max_length && \
!newinfo->FIELD##_max_length) \
newinfo->FIELD##_max_length = (newinfo->FIELD || \
newinfo->FIELD##_max) ? 1 : 0;
SET_MAX_LENGTH(set_bytes_max_length, total_bytes_sec);
SET_MAX_LENGTH(set_bytes_max_length, read_bytes_sec);
SET_MAX_LENGTH(set_bytes_max_length, write_bytes_sec);
SET_MAX_LENGTH(set_iops_max_length, total_iops_sec);
SET_MAX_LENGTH(set_iops_max_length, read_iops_sec);
SET_MAX_LENGTH(set_iops_max_length, write_iops_sec);
#undef SET_MAX_LENGTH
}
......@@ -17345,7 +17378,10 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
bool set_bytes_max = false;
bool set_iops_max = false;
bool set_size_iops = false;
bool set_bytes_max_length = false;
bool set_iops_max_length = false;
bool supportMaxOptions = true;
bool supportMaxLengthOptions = true;
virQEMUDriverConfigPtr cfg = NULL;
virObjectEventPtr event = NULL;
virTypedParameterPtr eventParams = NULL;
......@@ -17381,6 +17417,18 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH,
VIR_TYPED_PARAM_ULLONG,
NULL) < 0)
return -1;
......@@ -17448,6 +17496,19 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
SET_IOTUNE_FIELD(write_iops_sec_max, set_iops_max,
WRITE_IOPS_SEC_MAX);
SET_IOTUNE_FIELD(size_iops_sec, set_size_iops, SIZE_IOPS_SEC);
SET_IOTUNE_FIELD(total_bytes_sec_max_length, set_bytes_max_length,
TOTAL_BYTES_SEC_MAX_LENGTH);
SET_IOTUNE_FIELD(read_bytes_sec_max_length, set_bytes_max_length,
READ_BYTES_SEC_MAX_LENGTH);
SET_IOTUNE_FIELD(write_bytes_sec_max_length, set_bytes_max_length,
WRITE_BYTES_SEC_MAX_LENGTH);
SET_IOTUNE_FIELD(total_iops_sec_max_length, set_iops_max_length,
TOTAL_IOPS_SEC_MAX_LENGTH);
SET_IOTUNE_FIELD(read_iops_sec_max_length, set_iops_max_length,
READ_IOPS_SEC_MAX_LENGTH);
SET_IOTUNE_FIELD(write_iops_sec_max_length, set_iops_max_length,
WRITE_IOPS_SEC_MAX_LENGTH);
}
#undef SET_IOTUNE_FIELD
......@@ -17487,6 +17548,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
if (def) {
supportMaxOptions = virQEMUCapsGet(priv->qemuCaps,
QEMU_CAPS_DRIVE_IOTUNE_MAX);
supportMaxLengthOptions =
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH);
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("block I/O throttling not supported with this "
......@@ -17502,6 +17566,14 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
goto endjob;
}
if (!supportMaxLengthOptions &&
(set_iops_max_length || set_bytes_max_length)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("a block I/O throttling length parameter is not "
"supported with this QEMU binary"));
goto endjob;
}
if (!(disk = qemuDomainDiskByName(def, path)))
goto endjob;
......@@ -17510,7 +17582,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
qemuDomainSetBlockIoTuneDefaults(&info, &disk->blkdeviotune,
set_bytes, set_iops, set_bytes_max,
set_iops_max, set_size_iops);
set_iops_max, set_size_iops,
set_bytes_max_length,
set_iops_max_length);
#define CHECK_MAX(val) \
do { \
......@@ -17532,9 +17606,13 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
#undef CHECK_MAX
/* NB: Let's let QEMU decide how to handle issues with _length
* via the JSON error code from the block_set_io_throttle call */
qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorSetBlockIoThrottle(priv->mon, device,
&info, supportMaxOptions);
&info, supportMaxOptions,
supportMaxLengthOptions);
if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
if (ret < 0)
......@@ -17561,7 +17639,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom,
}
qemuDomainSetBlockIoTuneDefaults(&info, &conf_disk->blkdeviotune,
set_bytes, set_iops, set_bytes_max,
set_iops_max, set_size_iops);
set_iops_max, set_size_iops,
set_bytes_max_length,
set_iops_max_length);
conf_disk->blkdeviotune = info;
ret = virDomainSaveConfig(cfg->configDir, driver->caps, persistentDef);
if (ret < 0)
......@@ -17597,7 +17677,7 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
virDomainBlockIoTuneInfo reply;
char *device = NULL;
int ret = -1;
int maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX;
int maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX_LENGTH;
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
VIR_DOMAIN_AFFECT_CONFIG |
......@@ -17633,6 +17713,9 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_IOTUNE_MAX))
maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM;
else if (!virQEMUCapsGet(priv->qemuCaps,
QEMU_CAPS_DRIVE_IOTUNE_MAX_LENGTH))
maxparams = QEMU_NB_BLOCK_IO_TUNE_PARAM_MAX;
}
if (*nparams == 0) {
......@@ -17696,6 +17779,13 @@ qemuDomainGetBlockIoTune(virDomainPtr dom,
BLOCK_IOTUNE_ASSIGN(SIZE_IOPS_SEC, size_iops_sec);
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);
BLOCK_IOTUNE_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_length);
BLOCK_IOTUNE_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_length);
BLOCK_IOTUNE_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_length);
#undef BLOCK_IOTUNE_ASSIGN
ret = 0;
......
......@@ -3427,14 +3427,17 @@ int
qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions)
bool supportMaxOptions,
bool supportMaxLengthOptions)
{
VIR_DEBUG("device=%p, info=%p", device, info);
QEMU_CHECK_MONITOR(mon);
if (mon->json)
return qemuMonitorJSONSetBlockIoThrottle(mon, device, info, supportMaxOptions);
return qemuMonitorJSONSetBlockIoThrottle(mon, device, info,
supportMaxOptions,
supportMaxLengthOptions);
else
return qemuMonitorTextSetBlockIoThrottle(mon, device, info);
}
......
......@@ -876,7 +876,8 @@ int qemuMonitorOpenGraphics(qemuMonitorPtr mon,
int qemuMonitorSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions);
bool supportMaxOptions,
bool supportMaxLengthOptions);
int qemuMonitorGetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
......
......@@ -4563,6 +4563,12 @@ 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);
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);
GET_THROTTLE_STATS_OPTIONAL("iops_max_length", total_iops_sec_max_length);
GET_THROTTLE_STATS_OPTIONAL("iops_rd_max_length", read_iops_sec_max_length);
GET_THROTTLE_STATS_OPTIONAL("iops_wr_max_length", write_iops_sec_max_length);
break;
}
......@@ -4584,7 +4590,8 @@ qemuMonitorJSONBlockIoThrottleInfo(virJSONValuePtr result,
int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions)
bool supportMaxOptions,
bool supportMaxLengthOptions)
{
int ret = -1;
virJSONValuePtr cmd = NULL;
......@@ -4593,7 +4600,8 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
/* The qemu capability check has already been made in
* qemuDomainSetBlockIoTune. NB, once a NULL is found in
* the sequence, qemuMonitorJSONMakeCommand will stop. So
* let's make use of that when !supportMaxOptions */
* let's make use of that when !supportMaxOptions and
* similarly when !supportMaxLengthOptions */
cmd = qemuMonitorJSONMakeCommand("block_set_io_throttle",
"s:device", device,
"U:bps", info->total_bytes_sec,
......@@ -4610,6 +4618,19 @@ int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
"U:iops_rd_max", info->read_iops_sec_max,
"U:iops_wr_max", info->write_iops_sec_max,
"U:iops_size", info->size_iops_sec,
!supportMaxLengthOptions ? NULL :
"P:bps_max_length",
info->total_bytes_sec_max_length,
"P:bps_rd_max_length",
info->read_bytes_sec_max_length,
"P:bps_wr_max_length",
info->write_bytes_sec_max_length,
"P:iops_max_length",
info->total_iops_sec_max_length,
"P:iops_rd_max_length",
info->read_iops_sec_max_length,
"P:iops_wr_max_length",
info->write_iops_sec_max_length,
NULL);
if (!cmd)
return -1;
......
......@@ -327,7 +327,8 @@ int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon,
int qemuMonitorJSONSetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
virDomainBlockIoTuneInfoPtr info,
bool supportMaxOptions);
bool supportMaxOptions,
bool supportMaxLengthOptions);
int qemuMonitorJSONGetBlockIoThrottle(qemuMonitorPtr mon,
const char *device,
......
......@@ -67,6 +67,12 @@ 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,"
" \"file\": \"/home/zippy/work/tmp/gentoo.qcow2\","
" \"encryption_key_missing\": false"
" },"
......@@ -1996,7 +2002,7 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
if (!test)
return -1;
expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 ||
qemuMonitorTestAddItemParams(test, "block_set_io_throttle",
......@@ -2008,6 +2014,12 @@ 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",
NULL, NULL) < 0)
goto cleanup;
......@@ -2022,7 +2034,8 @@ testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *data)
}
if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
"drive-virtio-disk1", &info, true) < 0)
"drive-virtio-disk1", &info, true,
true) < 0)
goto cleanup;
ret = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册