mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
hmp/qmp: add block_set_io_throttle
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
98f90dba5e
commit
727f005e6a
9 changed files with 175 additions and 2 deletions
15
block.c
15
block.c
|
@ -1978,6 +1978,21 @@ BlockInfoList *qmp_query_block(Error **errp)
|
|||
info->value->inserted->has_backing_file = true;
|
||||
info->value->inserted->backing_file = g_strdup(bs->backing_file);
|
||||
}
|
||||
|
||||
if (bs->io_limits_enabled) {
|
||||
info->value->inserted->bps =
|
||||
bs->io_limits.bps[BLOCK_IO_LIMIT_TOTAL];
|
||||
info->value->inserted->bps_rd =
|
||||
bs->io_limits.bps[BLOCK_IO_LIMIT_READ];
|
||||
info->value->inserted->bps_wr =
|
||||
bs->io_limits.bps[BLOCK_IO_LIMIT_WRITE];
|
||||
info->value->inserted->iops =
|
||||
bs->io_limits.iops[BLOCK_IO_LIMIT_TOTAL];
|
||||
info->value->inserted->iops_rd =
|
||||
bs->io_limits.iops[BLOCK_IO_LIMIT_READ];
|
||||
info->value->inserted->iops_wr =
|
||||
bs->io_limits.iops[BLOCK_IO_LIMIT_WRITE];
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: waiting for the qapi to support GSList */
|
||||
|
|
59
blockdev.c
59
blockdev.c
|
@ -759,6 +759,65 @@ int do_change_block(Monitor *mon, const char *device,
|
|||
return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
|
||||
}
|
||||
|
||||
/* throttling disk I/O limits */
|
||||
int do_block_set_io_throttle(Monitor *mon,
|
||||
const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
BlockIOLimit io_limits;
|
||||
const char *devname = qdict_get_str(qdict, "device");
|
||||
BlockDriverState *bs;
|
||||
|
||||
io_limits.bps[BLOCK_IO_LIMIT_TOTAL]
|
||||
= qdict_get_try_int(qdict, "bps", -1);
|
||||
io_limits.bps[BLOCK_IO_LIMIT_READ]
|
||||
= qdict_get_try_int(qdict, "bps_rd", -1);
|
||||
io_limits.bps[BLOCK_IO_LIMIT_WRITE]
|
||||
= qdict_get_try_int(qdict, "bps_wr", -1);
|
||||
io_limits.iops[BLOCK_IO_LIMIT_TOTAL]
|
||||
= qdict_get_try_int(qdict, "iops", -1);
|
||||
io_limits.iops[BLOCK_IO_LIMIT_READ]
|
||||
= qdict_get_try_int(qdict, "iops_rd", -1);
|
||||
io_limits.iops[BLOCK_IO_LIMIT_WRITE]
|
||||
= qdict_get_try_int(qdict, "iops_wr", -1);
|
||||
|
||||
bs = bdrv_find(devname);
|
||||
if (!bs) {
|
||||
qerror_report(QERR_DEVICE_NOT_FOUND, devname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] == -1)
|
||||
|| (io_limits.bps[BLOCK_IO_LIMIT_READ] == -1)
|
||||
|| (io_limits.bps[BLOCK_IO_LIMIT_WRITE] == -1)
|
||||
|| (io_limits.iops[BLOCK_IO_LIMIT_TOTAL] == -1)
|
||||
|| (io_limits.iops[BLOCK_IO_LIMIT_READ] == -1)
|
||||
|| (io_limits.iops[BLOCK_IO_LIMIT_WRITE] == -1)) {
|
||||
qerror_report(QERR_MISSING_PARAMETER,
|
||||
"bps/bps_rd/bps_wr/iops/iops_rd/iops_wr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!do_check_io_limits(&io_limits)) {
|
||||
qerror_report(QERR_INVALID_PARAMETER_COMBINATION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bs->io_limits = io_limits;
|
||||
bs->slice_time = BLOCK_IO_SLICE_TIME;
|
||||
|
||||
if (!bs->io_limits_enabled && bdrv_io_limits_enabled(bs)) {
|
||||
bdrv_io_limits_enable(bs);
|
||||
} else if (bs->io_limits_enabled && !bdrv_io_limits_enabled(bs)) {
|
||||
bdrv_io_limits_disable(bs);
|
||||
} else {
|
||||
if (bs->block_timer) {
|
||||
qemu_mod_timer(bs->block_timer, qemu_get_clock_ns(vm_clock));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
const char *id = qdict_get_str(qdict, "id");
|
||||
|
|
|
@ -63,6 +63,8 @@ int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
|||
int do_change_block(Monitor *mon, const char *device,
|
||||
const char *filename, const char *fmt);
|
||||
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_block_set_io_throttle(Monitor *mon,
|
||||
const QDict *qdict, QObject **ret_data);
|
||||
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
|
||||
|
|
|
@ -1206,6 +1206,21 @@ ETEXI
|
|||
.mhandler.cmd_new = do_block_set_passwd,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item block_set_io_throttle @var{device} @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
|
||||
@findex block_set_io_throttle
|
||||
Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
|
||||
ETEXI
|
||||
|
||||
{
|
||||
.name = "block_set_io_throttle",
|
||||
.args_type = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
|
||||
.params = "device bps bps_rd bps_wr iops iops_rd iops_wr",
|
||||
.help = "change I/O throttle limits for a block drive",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.cmd_new = do_block_set_io_throttle,
|
||||
},
|
||||
|
||||
STEXI
|
||||
@item block_passwd @var{device} @var{password}
|
||||
@findex block_passwd
|
||||
|
|
10
hmp.c
10
hmp.c
|
@ -216,6 +216,16 @@ void hmp_info_block(Monitor *mon)
|
|||
info->value->inserted->ro,
|
||||
info->value->inserted->drv,
|
||||
info->value->inserted->encrypted);
|
||||
|
||||
monitor_printf(mon, " bps=%" PRId64 " bps_rd=%" PRId64
|
||||
" bps_wr=%" PRId64 " iops=%" PRId64
|
||||
" iops_rd=%" PRId64 " iops_wr=%" PRId64,
|
||||
info->value->inserted->bps,
|
||||
info->value->inserted->bps_rd,
|
||||
info->value->inserted->bps_wr,
|
||||
info->value->inserted->iops,
|
||||
info->value->inserted->iops_rd,
|
||||
info->value->inserted->iops_wr);
|
||||
} else {
|
||||
monitor_printf(mon, " [not inserted]");
|
||||
}
|
||||
|
|
|
@ -370,13 +370,27 @@
|
|||
#
|
||||
# @encrypted: true if the backing device is encrypted
|
||||
#
|
||||
# @bps: total throughput limit in bytes per second is specified
|
||||
#
|
||||
# @bps_rd: read throughput limit in bytes per second is specified
|
||||
#
|
||||
# @bps_wr: write throughput limit in bytes per second is specified
|
||||
#
|
||||
# @iops: total I/O operations per second is specified
|
||||
#
|
||||
# @iops_rd: read I/O operations per second is specified
|
||||
#
|
||||
# @iops_wr: write I/O operations per second is specified
|
||||
#
|
||||
# Since: 0.14.0
|
||||
#
|
||||
# Notes: This interface is only found in @BlockInfo.
|
||||
##
|
||||
{ 'type': 'BlockDeviceInfo',
|
||||
'data': { 'file': 'str', 'ro': 'bool', 'drv': 'str',
|
||||
'*backing_file': 'str', 'encrypted': 'bool' } }
|
||||
'*backing_file': 'str', 'encrypted': 'bool',
|
||||
'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
|
||||
'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int'} }
|
||||
|
||||
##
|
||||
# @BlockDeviceIoStatus:
|
||||
|
|
4
qerror.c
4
qerror.c
|
@ -246,6 +246,10 @@ static const QErrorStringTable qerror_table[] = {
|
|||
.error_fmt = QERR_QGA_COMMAND_FAILED,
|
||||
.desc = "Guest agent command failed, error was '%(message)'",
|
||||
},
|
||||
{
|
||||
.error_fmt = QERR_INVALID_PARAMETER_COMBINATION,
|
||||
.desc = "Invalid paramter combination",
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
3
qerror.h
3
qerror.h
|
@ -204,4 +204,7 @@ QError *qobject_to_qerror(const QObject *obj);
|
|||
#define QERR_QGA_COMMAND_FAILED \
|
||||
"{ 'class': 'QgaCommandFailed', 'data': { 'message': %s } }"
|
||||
|
||||
#define QERR_INVALID_PARAMETER_COMBINATION \
|
||||
"{ 'class': 'InvalidParameterCombination', 'data': {} }"
|
||||
|
||||
#endif /* QERROR_H */
|
||||
|
|
|
@ -848,6 +848,44 @@ Example:
|
|||
"password": "12345" } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
.name = "block_set_io_throttle",
|
||||
.args_type = "device:B,bps:l,bps_rd:l,bps_wr:l,iops:l,iops_rd:l,iops_wr:l",
|
||||
.params = "device bps bps_rd bps_wr iops iops_rd iops_wr",
|
||||
.help = "change I/O throttle limits for a block drive",
|
||||
.user_print = monitor_user_noop,
|
||||
.mhandler.cmd_new = do_block_set_io_throttle,
|
||||
},
|
||||
|
||||
SQMP
|
||||
block_set_io_throttle
|
||||
------------
|
||||
|
||||
Change I/O throttle limits for a block drive.
|
||||
|
||||
Arguments:
|
||||
|
||||
- "device": device name (json-string)
|
||||
- "bps": total throughput limit in bytes per second(json-int)
|
||||
- "bps_rd": read throughput limit in bytes per second(json-int)
|
||||
- "bps_wr": read throughput limit in bytes per second(json-int)
|
||||
- "iops": total I/O operations per second(json-int)
|
||||
- "iops_rd": read I/O operations per second(json-int)
|
||||
- "iops_wr": write I/O operations per second(json-int)
|
||||
|
||||
Example:
|
||||
|
||||
-> { "execute": "block_set_io_throttle", "arguments": { "device": "virtio0",
|
||||
"bps": "1000000",
|
||||
"bps_rd": "0",
|
||||
"bps_wr": "0",
|
||||
"iops": "0",
|
||||
"iops_rd": "0",
|
||||
"iops_wr": "0" } }
|
||||
<- { "return": {} }
|
||||
|
||||
EQMP
|
||||
|
||||
{
|
||||
|
@ -1152,6 +1190,13 @@ Each json-object contain the following:
|
|||
"tftp", "vdi", "vmdk", "vpc", "vvfat"
|
||||
- "backing_file": backing file name (json-string, optional)
|
||||
- "encrypted": true if encrypted, false otherwise (json-bool)
|
||||
- "bps": limit total bytes per second (json-int)
|
||||
- "bps_rd": limit read bytes per second (json-int)
|
||||
- "bps_wr": limit write bytes per second (json-int)
|
||||
- "iops": limit total I/O operations per second (json-int)
|
||||
- "iops_rd": limit read operations per second (json-int)
|
||||
- "iops_wr": limit write operations per second (json-int)
|
||||
|
||||
- "io-status": I/O operation status, only present if the device supports it
|
||||
and the VM is configured to stop on errors. It's always reset
|
||||
to "ok" when the "cont" command is issued (json_string, optional)
|
||||
|
@ -1171,7 +1216,13 @@ Example:
|
|||
"ro":false,
|
||||
"drv":"qcow2",
|
||||
"encrypted":false,
|
||||
"file":"disks/test.img"
|
||||
"file":"disks/test.img",
|
||||
"bps":1000000,
|
||||
"bps_rd":0,
|
||||
"bps_wr":0,
|
||||
"iops":1000000,
|
||||
"iops_rd":0,
|
||||
"iops_wr":0,
|
||||
},
|
||||
"type":"unknown"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue