From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:49330) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qqdof-0002CT-RS for qemu-devel@nongnu.org; Tue, 09 Aug 2011 00:21:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qqdoe-00030t-Dy for qemu-devel@nongnu.org; Tue, 09 Aug 2011 00:21:21 -0400 Received: from e2.ny.us.ibm.com ([32.97.182.142]:32806) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qqdoe-000301-9E for qemu-devel@nongnu.org; Tue, 09 Aug 2011 00:21:20 -0400 Received: from d01relay05.pok.ibm.com (d01relay05.pok.ibm.com [9.56.227.237]) by e2.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p793xg69007184 for ; Mon, 8 Aug 2011 23:59:42 -0400 Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay05.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p794LFJQ207918 for ; Tue, 9 Aug 2011 00:21:15 -0400 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p790L1rQ011981 for ; Mon, 8 Aug 2011 21:21:02 -0300 From: Zhi Yong Wu Date: Tue, 9 Aug 2011 12:17:49 +0800 Message-Id: <1312863472-6901-2-git-send-email-wuzhy@linux.vnet.ibm.com> In-Reply-To: <1312863472-6901-1-git-send-email-wuzhy@linux.vnet.ibm.com> References: <1312863472-6901-1-git-send-email-wuzhy@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH v5 1/4] block: add the command line support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, pair@us.ibm.com, stefanha@linux.vnet.ibm.com, kvm@vger.kernel.org, mtosatti@redhat.com, Zhi Yong Wu , zwu.kernel@gmail.com, ryanh@us.ibm.com, luowenj@cn.ibm.com Signed-off-by: Zhi Yong Wu --- Makefile.objs | 2 +- blockdev.c | 39 +++++++++++++++++++++++++++++++++++++++ qemu-config.c | 24 ++++++++++++++++++++++++ qemu-option.c | 17 +++++++++++++++++ qemu-option.h | 1 + qemu-options.hx | 1 + 6 files changed, 83 insertions(+), 1 deletions(-) diff --git a/Makefile.objs b/Makefile.objs index 9f99ed4..06f2033 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -23,7 +23,7 @@ block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vv block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-nested-y += qed-check.o -block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o +block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o blk-queue.o block-nested-$(CONFIG_WIN32) += raw-win32.o block-nested-$(CONFIG_POSIX) += raw-posix.o block-nested-$(CONFIG_CURL) += curl.o diff --git a/blockdev.c b/blockdev.c index c263663..9c78548 100644 --- a/blockdev.c +++ b/blockdev.c @@ -238,6 +238,10 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) int on_read_error, on_write_error; const char *devaddr; DriveInfo *dinfo; + BlockIOLimit io_limits; + bool iol_flag = false; + const char *iol_opts[7] = {"bps", "bps_rd", "bps_wr", + "iops", "iops_rd", "iops_wr"}; int is_extboot = 0; int snapshot = 0; int ret; @@ -372,6 +376,36 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) return NULL; } + /* disk io throttling */ + iol_flag = qemu_opt_io_limits_enable_flag(opts, iol_opts); + if (iol_flag) { + memset(&io_limits, 0, sizeof(BlockIOLimit)); + + io_limits.bps[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "bps", 0); + io_limits.bps[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "bps_rd", 0); + io_limits.bps[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "bps_wr", 0); + io_limits.iops[BLOCK_IO_LIMIT_TOTAL] = + qemu_opt_get_number(opts, "iops", 0); + io_limits.iops[BLOCK_IO_LIMIT_READ] = + qemu_opt_get_number(opts, "iops_rd", 0); + io_limits.iops[BLOCK_IO_LIMIT_WRITE] = + qemu_opt_get_number(opts, "iops_wr", 0); + + if (((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] != 0) + && ((io_limits.bps[BLOCK_IO_LIMIT_READ] != 0) + || (io_limits.bps[BLOCK_IO_LIMIT_WRITE] != 0))) + || ((io_limits.iops[BLOCK_IO_LIMIT_TOTAL] != 0) + && ((io_limits.iops[BLOCK_IO_LIMIT_READ] != 0) + || (io_limits.iops[BLOCK_IO_LIMIT_WRITE] != 0)))) { + error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_wr) \ + cannot be used at the same time"); + return NULL; + } + } + on_write_error = BLOCK_ERR_STOP_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { @@ -483,6 +517,11 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error); + /* disk I/O throttling */ + if (iol_flag) { + bdrv_set_io_limits(dinfo->bdrv, &io_limits); + } + switch(type) { case IF_IDE: case IF_SCSI: diff --git a/qemu-config.c b/qemu-config.c index efa892c..9232bbb 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -82,6 +82,30 @@ static QemuOptsList qemu_drive_opts = { .name = "boot", .type = QEMU_OPT_BOOL, .help = "make this a boot drive", + },{ + .name = "iops", + .type = QEMU_OPT_NUMBER, + .help = "limit total I/O operations per second", + },{ + .name = "iops_rd", + .type = QEMU_OPT_NUMBER, + .help = "limit read operations per second", + },{ + .name = "iops_wr", + .type = QEMU_OPT_NUMBER, + .help = "limit write operations per second", + },{ + .name = "bps", + .type = QEMU_OPT_NUMBER, + .help = "limit total bytes per second", + },{ + .name = "bps_rd", + .type = QEMU_OPT_NUMBER, + .help = "limit read bytes per second", + },{ + .name = "bps_wr", + .type = QEMU_OPT_NUMBER, + .help = "limit write bytes per second", }, { /* end of list */ } }, diff --git a/qemu-option.c b/qemu-option.c index 65db542..c5aa96a 100644 --- a/qemu-option.c +++ b/qemu-option.c @@ -562,6 +562,23 @@ uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval) return opt->value.uint; } +bool qemu_opt_io_limits_enable_flag(QemuOpts *opts, const char **iol_opts) +{ + int i; + uint64_t opt_val = 0; + bool iol_flag = false; + + for (i = 0; iol_opts[i]; i++) { + opt_val = qemu_opt_get_number(opts, iol_opts[i], 0); + if (opt_val != 0) { + iol_flag = true; + break; + } + } + + return iol_flag; +} + uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval) { QemuOpt *opt = qemu_opt_find(opts, name); diff --git a/qemu-option.h b/qemu-option.h index b515813..fc909f9 100644 --- a/qemu-option.h +++ b/qemu-option.h @@ -107,6 +107,7 @@ struct QemuOptsList { const char *qemu_opt_get(QemuOpts *opts, const char *name); int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval); uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval); +bool qemu_opt_io_limits_enable_flag(QemuOpts *opts, const char **iol_opts); uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval); int qemu_opt_set(QemuOpts *opts, const char *name, const char *value); typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque); diff --git a/qemu-options.hx b/qemu-options.hx index cb3347e..ae219f5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -121,6 +121,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive, " [,cache=writethrough|writeback|none|unsafe][,format=f]\n" " [,serial=s][,addr=A][,id=name][,aio=threads|native]\n" " [,readonly=on|off][,boot=on|off]\n" + " [[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]\n" " use 'file' as a drive image\n", QEMU_ARCH_ALL) STEXI @item -drive @var{option}[,@var{option}[,@var{option}[,...]]] -- 1.7.2.3