* [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle
@ 2011-11-08 5:00 Zhi Yong Wu
2011-11-08 10:12 ` Kevin Wolf
0 siblings, 1 reply; 5+ messages in thread
From: Zhi Yong Wu @ 2011-11-08 5:00 UTC (permalink / raw)
To: kwolf; +Cc: zwu.kernel, ryanh, Zhi Yong Wu, qemu-devel, stefanha
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
block.c | 15 +++++++++++++
blockdev.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
blockdev.h | 2 +
hmp-commands.hx | 15 +++++++++++++
hmp.c | 10 +++++++++
qapi-schema.json | 16 +++++++++++++-
qerror.c | 4 +++
qerror.h | 3 ++
qmp-commands.hx | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
9 files changed, 175 insertions(+), 2 deletions(-)
diff --git a/block.c b/block.c
index 3d0ec23..fffc7dc 100644
--- a/block.c
+++ b/block.c
@@ -1971,6 +1971,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 */
diff --git a/blockdev.c b/blockdev.c
index 651828c..95d1faa 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -757,6 +757,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");
diff --git a/blockdev.h b/blockdev.h
index 3587786..1b48a75 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -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);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 089c1ac..f8d855e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1207,6 +1207,21 @@ ETEXI
},
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
Set the encrypted device @var{device} password to @var{password}
diff --git a/hmp.c b/hmp.c
index 443d3a7..dfab7ad 100644
--- a/hmp.c
+++ b/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]");
}
diff --git a/qapi-schema.json b/qapi-schema.json
index cb1ba77..fbbdbe0 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -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:
diff --git a/qerror.c b/qerror.c
index 4b48b39..807fb55 100644
--- a/qerror.c
+++ b/qerror.c
@@ -238,6 +238,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",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index d4bfcfd..777a36a 100644
--- a/qerror.h
+++ b/qerror.h
@@ -198,4 +198,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 */
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 97975a5..94da2a8 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -851,6 +851,44 @@ Example:
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
+
+ {
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
@@ -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"
},
--
1.7.6
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle
2011-11-08 5:00 [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle Zhi Yong Wu
@ 2011-11-08 10:12 ` Kevin Wolf
0 siblings, 0 replies; 5+ messages in thread
From: Kevin Wolf @ 2011-11-08 10:12 UTC (permalink / raw)
To: Zhi Yong Wu; +Cc: zwu.kernel, ryanh, qemu-devel, stefanha
Am 08.11.2011 06:00, schrieb Zhi Yong Wu:
> Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> ---
> block.c | 15 +++++++++++++
> blockdev.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> blockdev.h | 2 +
> hmp-commands.hx | 15 +++++++++++++
> hmp.c | 10 +++++++++
> qapi-schema.json | 16 +++++++++++++-
> qerror.c | 4 +++
> qerror.h | 3 ++
> qmp-commands.hx | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
> 9 files changed, 175 insertions(+), 2 deletions(-)
Thanks, applied all to the block branch (for 1.1)
Kevin
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v12 0/5] The intro to QEMU block I/O throttling
@ 2011-11-03 8:57 Zhi Yong Wu
2011-11-03 8:57 ` [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle Zhi Yong Wu
0 siblings, 1 reply; 5+ messages in thread
From: Zhi Yong Wu @ 2011-11-03 8:57 UTC (permalink / raw)
To: kwolf; +Cc: zwu.kernel, ryanh, Zhi Yong Wu, qemu-devel, stefanha
The main goal of the patch is to effectively cap the disk I/O speed or counts of one single VM.It is only one draft, so it unavoidably has some drawbacks, if you catch them, please let me know.
The patch will mainly introduce one block I/O throttling algorithm, one timer and one block queue for each I/O limits enabled drive.
When a block request is coming in, the throttling algorithm will check if its I/O rate or counts exceed the limits; if yes, then it will enqueue to the block queue; The timer will handle the I/O requests in it.
Some available features follow as below:
(1) global bps limit.
-drive bps=xxx in bytes/s
(2) only read bps limit
-drive bps_rd=xxx in bytes/s
(3) only write bps limit
-drive bps_wr=xxx in bytes/s
(4) global iops limit
-drive iops=xxx in ios/s
(5) only read iops limit
-drive iops_rd=xxx in ios/s
(6) only write iops limit
-drive iops_wr=xxx in ios/s
(7) the combination of some limits.
-drive bps=xxx,iops=xxx
Known Limitations:
(1) #1 can not coexist with #2, #3
(2) #4 can not coexist with #5, #6
Changes since code V11:
Made some changes based on kevin's comments.
v11: Made some mininal changes based on stefan and Ryan's comments
Add one perf report for block I/O throttling
v10: Greately simply the logic and rebase request queue to CoQueue based on Stefan's comments.
v9: made a lot of changes based on kevin's comments.
slice_time is dynamically adjusted based on wait_time.
rebase the latest qemu upstream.
v8: fix the build per patch based on stefan's comments.
v7: Mainly simply the block queue.
Adjust codes based on stefan's comments.
v6: Mainly fix the aio callback issue for block queue.
Adjust codes based on Ram Pai's comments.
v5: add qmp/hmp support.
Adjust the codes based on stefan's comments
qmp/hmp: add block_set_io_throttle
v4: fix memory leaking based on ryan's feedback.
v3: Added the code for extending slice time, and modified the method to compute wait time for the timer.
v2: The codes V2 for QEMU disk I/O limits.
Modified the codes mainly based on stefan's comments.
v1: Submit the codes for QEMU disk I/O limits.
Zhi Yong Wu (5):
block: add the blockio limits command line support
CoQueue: introduce qemu_co_queue_wait_insert_head
block: add I/O throttling algorithm
hmp/qmp: add block_set_io_throttle
block: perf testing report based on block I/O throttling
10mbps.dat | 310 ++++++++++++++++++++++++++++++++++++++++++++
1mbps.dat | 339 +++++++++++++++++++++++++++++++++++++++++++++++++
block.c | 274 +++++++++++++++++++++++++++++++++++++++
block.h | 5 +
block_int.h | 30 +++++
blockdev.c | 103 +++++++++++++++
blockdev.h | 2 +
hmp-commands.hx | 15 ++
hmp.c | 10 ++
qapi-schema.json | 16 ++-
qemu-config.c | 24 ++++
qemu-coroutine-lock.c | 8 +
qemu-coroutine.h | 6 +
qemu-options.hx | 1 +
qerror.c | 4 +
qerror.h | 3 +
qmp-commands.hx | 53 ++++++++-
17 files changed, 1201 insertions(+), 2 deletions(-)
create mode 100644 10mbps.dat
create mode 100644 1mbps.dat
--
1.7.6
^ permalink raw reply [flat|nested] 5+ messages in thread* [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle
2011-11-03 8:57 [Qemu-devel] [PATCH v12 0/5] The intro to QEMU block I/O throttling Zhi Yong Wu
@ 2011-11-03 8:57 ` Zhi Yong Wu
2011-11-07 15:26 ` Kevin Wolf
0 siblings, 1 reply; 5+ messages in thread
From: Zhi Yong Wu @ 2011-11-03 8:57 UTC (permalink / raw)
To: kwolf; +Cc: zwu.kernel, ryanh, Zhi Yong Wu, qemu-devel, stefanha
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
block.c | 15 +++++++++++++
blockdev.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
blockdev.h | 2 +
hmp-commands.hx | 15 +++++++++++++
hmp.c | 10 +++++++++
qapi-schema.json | 16 +++++++++++++-
qerror.c | 4 +++
qerror.h | 3 ++
qmp-commands.hx | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
9 files changed, 175 insertions(+), 2 deletions(-)
diff --git a/block.c b/block.c
index b2af48f..ed6fe20 100644
--- a/block.c
+++ b/block.c
@@ -1971,6 +1971,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 */
diff --git a/blockdev.c b/blockdev.c
index 651828c..95d1faa 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -757,6 +757,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");
diff --git a/blockdev.h b/blockdev.h
index 3587786..1b48a75 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -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);
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 089c1ac..48f3c21 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1207,6 +1207,21 @@ ETEXI
},
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:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
+ .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
Set the encrypted device @var{device} password to @var{password}
diff --git a/hmp.c b/hmp.c
index 443d3a7..dfab7ad 100644
--- a/hmp.c
+++ b/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]");
}
diff --git a/qapi-schema.json b/qapi-schema.json
index cb1ba77..734076b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -370,13 +370,27 @@
#
# @encrypted: true if the backing device is encrypted
#
+# @bps: #optional if total throughput limit in bytes per second is specified
+#
+# @bps_rd: #optional if read throughput limit in bytes per second is specified
+#
+# @bps_wr: #optional if write throughput limit in bytes per second is specified
+#
+# @iops: #optional if total I/O operations per second is specified
+#
+# @iops_rd: #optional if read I/O operations per second is specified
+#
+# @iops_wr: #optional if 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:
diff --git a/qerror.c b/qerror.c
index 4b48b39..807fb55 100644
--- a/qerror.c
+++ b/qerror.c
@@ -238,6 +238,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",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index d4bfcfd..777a36a 100644
--- a/qerror.h
+++ b/qerror.h
@@ -198,4 +198,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 */
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 97975a5..cdc3c18 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -851,6 +851,44 @@ Example:
EQMP
{
+ .name = "block_set_io_throttle",
+ .args_type = "device:B,bps:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
+ .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, optional)
+- "bps_rd": read throughput limit in bytes per second(json-int, optional)
+- "bps_wr": read throughput limit in bytes per second(json-int, optional)
+- "iops": total I/O operations per second(json-int, optional)
+- "iops_rd": read I/O operations per second(json-int, optional)
+- "iops_wr": write I/O operations per second(json-int, optional)
+
+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
+
+ {
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
@@ -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"
},
--
1.7.6
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle
2011-11-03 8:57 ` [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle Zhi Yong Wu
@ 2011-11-07 15:26 ` Kevin Wolf
2011-11-08 2:21 ` Zhi Yong Wu
0 siblings, 1 reply; 5+ messages in thread
From: Kevin Wolf @ 2011-11-07 15:26 UTC (permalink / raw)
To: Zhi Yong Wu; +Cc: zwu.kernel, ryanh, qemu-devel, stefanha
Am 03.11.2011 09:57, schrieb Zhi Yong Wu:
> Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> ---
> block.c | 15 +++++++++++++
> blockdev.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> blockdev.h | 2 +
> hmp-commands.hx | 15 +++++++++++++
> hmp.c | 10 +++++++++
> qapi-schema.json | 16 +++++++++++++-
> qerror.c | 4 +++
> qerror.h | 3 ++
> qmp-commands.hx | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
> 9 files changed, 175 insertions(+), 2 deletions(-)
>
> diff --git a/block.c b/block.c
> index b2af48f..ed6fe20 100644
> --- a/block.c
> +++ b/block.c
> @@ -1971,6 +1971,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 */
> diff --git a/blockdev.c b/blockdev.c
> index 651828c..95d1faa 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -757,6 +757,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;
> + }
Here you require that all parameters are set...
> +
> + 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");
> diff --git a/blockdev.h b/blockdev.h
> index 3587786..1b48a75 100644
> --- a/blockdev.h
> +++ b/blockdev.h
> @@ -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);
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 089c1ac..48f3c21 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1207,6 +1207,21 @@ ETEXI
> },
>
> 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:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
> + .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,
> + },
> +
...but here....
> +STEXI
> @item block_passwd @var{device} @var{password}
> @findex block_passwd
> Set the encrypted device @var{device} password to @var{password}
> diff --git a/hmp.c b/hmp.c
> index 443d3a7..dfab7ad 100644
> --- a/hmp.c
> +++ b/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]");
> }
> diff --git a/qapi-schema.json b/qapi-schema.json
> index cb1ba77..734076b 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -370,13 +370,27 @@
> #
> # @encrypted: true if the backing device is encrypted
> #
> +# @bps: #optional if total throughput limit in bytes per second is specified
> +#
> +# @bps_rd: #optional if read throughput limit in bytes per second is specified
> +#
> +# @bps_wr: #optional if write throughput limit in bytes per second is specified
> +#
> +# @iops: #optional if total I/O operations per second is specified
> +#
> +# @iops_rd: #optional if read I/O operations per second is specified
> +#
> +# @iops_wr: #optional if 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:
> diff --git a/qerror.c b/qerror.c
> index 4b48b39..807fb55 100644
> --- a/qerror.c
> +++ b/qerror.c
> @@ -238,6 +238,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",
> + },
> {}
> };
>
> diff --git a/qerror.h b/qerror.h
> index d4bfcfd..777a36a 100644
> --- a/qerror.h
> +++ b/qerror.h
> @@ -198,4 +198,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 */
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 97975a5..cdc3c18 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -851,6 +851,44 @@ Example:
> EQMP
>
> {
> + .name = "block_set_io_throttle",
> + .args_type = "device:B,bps:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
> + .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, optional)
> +- "bps_rd": read throughput limit in bytes per second(json-int, optional)
> +- "bps_wr": read throughput limit in bytes per second(json-int, optional)
> +- "iops": total I/O operations per second(json-int, optional)
> +- "iops_rd": read I/O operations per second(json-int, optional)
> +- "iops_wr": write I/O operations per second(json-int, optional)
...and here they are described as optional. One part is wrong, though I
don't know which one.
Kevin
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle
2011-11-07 15:26 ` Kevin Wolf
@ 2011-11-08 2:21 ` Zhi Yong Wu
0 siblings, 0 replies; 5+ messages in thread
From: Zhi Yong Wu @ 2011-11-08 2:21 UTC (permalink / raw)
To: Kevin Wolf; +Cc: ryanh, Zhi Yong Wu, qemu-devel, stefanha
On Mon, Nov 7, 2011 at 11:26 PM, Kevin Wolf <kwolf@redhat.com> wrote:
> Am 03.11.2011 09:57, schrieb Zhi Yong Wu:
>> Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
>> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
>> ---
>> block.c | 15 +++++++++++++
>> blockdev.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> blockdev.h | 2 +
>> hmp-commands.hx | 15 +++++++++++++
>> hmp.c | 10 +++++++++
>> qapi-schema.json | 16 +++++++++++++-
>> qerror.c | 4 +++
>> qerror.h | 3 ++
>> qmp-commands.hx | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
>> 9 files changed, 175 insertions(+), 2 deletions(-)
>>
>> diff --git a/block.c b/block.c
>> index b2af48f..ed6fe20 100644
>> --- a/block.c
>> +++ b/block.c
>> @@ -1971,6 +1971,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 */
>> diff --git a/blockdev.c b/blockdev.c
>> index 651828c..95d1faa 100644
>> --- a/blockdev.c
>> +++ b/blockdev.c
>> @@ -757,6 +757,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;
>> + }
>
> Here you require that all parameters are set...
This is what i want.
>
>> +
>> + 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");
>> diff --git a/blockdev.h b/blockdev.h
>> index 3587786..1b48a75 100644
>> --- a/blockdev.h
>> +++ b/blockdev.h
>> @@ -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);
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index 089c1ac..48f3c21 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -1207,6 +1207,21 @@ ETEXI
>> },
>>
>> 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:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
>> + .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,
>> + },
>> +
>
> ...but here....
Sorry, i will update this.
>
>> +STEXI
>> @item block_passwd @var{device} @var{password}
>> @findex block_passwd
>> Set the encrypted device @var{device} password to @var{password}
>> diff --git a/hmp.c b/hmp.c
>> index 443d3a7..dfab7ad 100644
>> --- a/hmp.c
>> +++ b/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]");
>> }
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index cb1ba77..734076b 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -370,13 +370,27 @@
>> #
>> # @encrypted: true if the backing device is encrypted
>> #
>> +# @bps: #optional if total throughput limit in bytes per second is specified
>> +#
>> +# @bps_rd: #optional if read throughput limit in bytes per second is specified
>> +#
>> +# @bps_wr: #optional if write throughput limit in bytes per second is specified
>> +#
>> +# @iops: #optional if total I/O operations per second is specified
>> +#
>> +# @iops_rd: #optional if read I/O operations per second is specified
>> +#
>> +# @iops_wr: #optional if 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:
>> diff --git a/qerror.c b/qerror.c
>> index 4b48b39..807fb55 100644
>> --- a/qerror.c
>> +++ b/qerror.c
>> @@ -238,6 +238,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",
>> + },
>> {}
>> };
>>
>> diff --git a/qerror.h b/qerror.h
>> index d4bfcfd..777a36a 100644
>> --- a/qerror.h
>> +++ b/qerror.h
>> @@ -198,4 +198,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 */
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index 97975a5..cdc3c18 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -851,6 +851,44 @@ Example:
>> EQMP
>>
>> {
>> + .name = "block_set_io_throttle",
>> + .args_type = "device:B,bps:i?,bps_rd:i?,bps_wr:i?,iops:i?,iops_rd:i?,iops_wr:i?",
>> + .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, optional)
>> +- "bps_rd": read throughput limit in bytes per second(json-int, optional)
>> +- "bps_wr": read throughput limit in bytes per second(json-int, optional)
>> +- "iops": total I/O operations per second(json-int, optional)
>> +- "iops_rd": read I/O operations per second(json-int, optional)
>> +- "iops_wr": write I/O operations per second(json-int, optional)
>
> ...and here they are described as optional. One part is wrong, though I
> don't know which one.
This will be updated.
>
> Kevin
>
--
Regards,
Zhi Yong Wu
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-11-08 10:09 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-08 5:00 [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle Zhi Yong Wu
2011-11-08 10:12 ` Kevin Wolf
-- strict thread matches above, loose matches on Subject: below --
2011-11-03 8:57 [Qemu-devel] [PATCH v12 0/5] The intro to QEMU block I/O throttling Zhi Yong Wu
2011-11-03 8:57 ` [Qemu-devel] [PATCH v12 4/5] hmp/qmp: add block_set_io_throttle Zhi Yong Wu
2011-11-07 15:26 ` Kevin Wolf
2011-11-08 2:21 ` Zhi Yong Wu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.