From mboxrd@z Thu Jan 1 00:00:00 1970 From: Zhi Yong Wu Subject: Re: [PATCH v8 2/4] block: add the command line support Date: Mon, 26 Sep 2011 14:15:05 +0800 Message-ID: References: <1315476668-19812-1-git-send-email-wuzhy@linux.vnet.ibm.com> <1315476668-19812-3-git-send-email-wuzhy@linux.vnet.ibm.com> <4E7CABC0.4050501@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: Zhi Yong Wu , qemu-devel@nongnu.org, kvm@vger.kernel.org, stefanha@linux.vnet.ibm.com, mtosatti@redhat.com, aliguori@us.ibm.com, ryanh@us.ibm.com, pair@us.ibm.com To: Kevin Wolf Return-path: Received: from mail-ww0-f44.google.com ([74.125.82.44]:41509 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750808Ab1IZGPG convert rfc822-to-8bit (ORCPT ); Mon, 26 Sep 2011 02:15:06 -0400 Received: by wwf22 with SMTP id 22so6267392wwf.1 for ; Sun, 25 Sep 2011 23:15:05 -0700 (PDT) In-Reply-To: <4E7CABC0.4050501@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: On Fri, Sep 23, 2011 at 11:54 PM, Kevin Wolf wrote: > Am 08.09.2011 12:11, schrieb Zhi Yong Wu: >> Signed-off-by: Zhi Yong Wu >> --- >> =A0block.c =A0 =A0 =A0 =A0 | =A0 59 ++++++++++++++++++++++++++++++++= +++++++++++++++++++++++ >> =A0block.h =A0 =A0 =A0 =A0 | =A0 =A05 ++++ >> =A0block_int.h =A0 =A0 | =A0 =A03 ++ >> =A0blockdev.c =A0 =A0 =A0| =A0 29 +++++++++++++++++++++++++++ >> =A0qemu-config.c =A0 | =A0 24 ++++++++++++++++++++++ >> =A0qemu-options.hx | =A0 =A01 + >> =A06 files changed, 121 insertions(+), 0 deletions(-) >> >> diff --git a/block.c b/block.c >> index 43742b7..cd75183 100644 >> --- a/block.c >> +++ b/block.c >> @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) >> =A0} >> =A0#endif >> >> +/* throttling disk I/O limits */ >> +void bdrv_io_limits_disable(BlockDriverState *bs) >> +{ >> + =A0 =A0bs->io_limits_enabled =3D false; >> + >> + =A0 =A0if (bs->block_queue) { >> + =A0 =A0 =A0 =A0qemu_block_queue_flush(bs->block_queue); >> + =A0 =A0 =A0 =A0qemu_del_block_queue(bs->block_queue); >> + =A0 =A0 =A0 =A0bs->block_queue =3D NULL; >> + =A0 =A0} >> + >> + =A0 =A0if (bs->block_timer) { >> + =A0 =A0 =A0 =A0qemu_del_timer(bs->block_timer); >> + =A0 =A0 =A0 =A0qemu_free_timer(bs->block_timer); >> + =A0 =A0 =A0 =A0bs->block_timer =A0 =A0 =3D NULL; >> + =A0 =A0} >> + >> + =A0 =A0bs->slice_start =3D 0; >> + >> + =A0 =A0bs->slice_end =A0 =3D 0; > > Remove the empty line between slice_start and slice_end? Yeah, thanks. > >> +} >> + >> +static void bdrv_block_timer(void *opaque) >> +{ >> + =A0 =A0BlockDriverState *bs =3D opaque; >> + =A0 =A0BlockQueue *queue =A0 =A0=3D bs->block_queue; >> + >> + =A0 =A0qemu_block_queue_flush(queue); > > Hm, didn't really notice it while reading patch 1, but > qemu_block_queue_flush() is misleading. It's really something like Why do you say this is misleading? > qemu_block_queue_submit(). Right. It will resubmit all enqueued I/O requests. > >> +} >> + >> +void bdrv_io_limits_enable(BlockDriverState *bs) >> +{ >> + =A0 =A0bs->block_queue =3D qemu_new_block_queue(); >> + =A0 =A0bs->block_timer =3D qemu_new_timer_ns(vm_clock, bdrv_block_= timer, bs); >> + >> + =A0 =A0bs->slice_start =3D qemu_get_clock_ns(vm_clock); >> + >> + =A0 =A0bs->slice_end =A0 =3D bs->slice_start + BLOCK_IO_SLICE_TIME= ; >> +} > > Same as above. got it. I will remove, thanks. > >> + >> +bool bdrv_io_limits_enabled(BlockDriverState *bs) >> +{ >> + =A0 =A0BlockIOLimit *io_limits =3D &bs->io_limits; >> + =A0 =A0return io_limits->bps[BLOCK_IO_LIMIT_READ] >> + =A0 =A0 =A0 =A0 || io_limits->bps[BLOCK_IO_LIMIT_WRITE] >> + =A0 =A0 =A0 =A0 || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_READ] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_WRITE] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; >> +} >> + >> =A0/* check if the path starts with ":" */ >> =A0static int path_has_protocol(const char *path) >> =A0{ >> @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState = *bs, >> =A0 =A0 =A0*psecs =3D bs->secs; >> =A0} >> >> +/* throttling disk io limits */ >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BlockIOLimi= t *io_limits) >> +{ >> + =A0 =A0bs->io_limits =3D *io_limits; >> + =A0 =A0bs->io_limits_enabled =3D bdrv_io_limits_enabled(bs); >> +} >> + >> =A0/* Recognize floppy formats */ >> =A0typedef struct FDFormat { >> =A0 =A0 =A0FDriveType drive; >> diff --git a/block.h b/block.h >> index 3ac0b94..a3e69db 100644 >> --- a/block.h >> +++ b/block.h >> @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); >> =A0void bdrv_stats_print(Monitor *mon, const QObject *data); >> =A0void bdrv_info_stats(Monitor *mon, QObject **ret_data); >> >> +/* disk I/O throttling */ >> +void bdrv_io_limits_enable(BlockDriverState *bs); >> +void bdrv_io_limits_disable(BlockDriverState *bs); >> +bool bdrv_io_limits_enabled(BlockDriverState *bs); >> + >> =A0void bdrv_init(void); >> =A0void bdrv_init_with_whitelist(void); >> =A0BlockDriver *bdrv_find_protocol(const char *filename); >> diff --git a/block_int.h b/block_int.h >> index 201e635..368c776 100644 >> --- a/block_int.h >> +++ b/block_int.h >> @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); >> >> =A0void *qemu_blockalign(BlockDriverState *bs, size_t size); >> >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BlockIOLimi= t *io_limits); >> + >> =A0#ifdef _WIN32 >> =A0int is_windows_drive(const char *filename); >> =A0#endif >> diff --git a/blockdev.c b/blockdev.c >> index 2602591..619ae9f 100644 >> --- a/blockdev.c >> +++ b/blockdev.c >> @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int defaul= t_to_scsi) >> =A0 =A0 =A0int on_read_error, on_write_error; >> =A0 =A0 =A0const char *devaddr; >> =A0 =A0 =A0DriveInfo *dinfo; >> + =A0 =A0BlockIOLimit io_limits; >> =A0 =A0 =A0int snapshot =3D 0; >> =A0 =A0 =A0int ret; >> >> @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int defau= lt_to_scsi) >> =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0} >> >> + =A0 =A0/* disk I/O throttling */ >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_TOTAL] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "bps", 0); >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_READ] =A0 =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "bps_rd", 0); >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_WRITE] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "bps_wr", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "iops", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_READ] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "iops_rd", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_WRITE] =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_n= umber(opts, "iops_wr", 0); >> + >> + =A0 =A0if (((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] !=3D 0) >> + =A0 =A0 =A0 =A0 =A0 =A0&& ((io_limits.bps[BLOCK_IO_LIMIT_READ] !=3D= 0) >> + =A0 =A0 =A0 =A0 =A0 =A0|| (io_limits.bps[BLOCK_IO_LIMIT_WRITE] !=3D= 0))) >> + =A0 =A0 =A0 =A0 =A0 =A0|| ((io_limits.iops[BLOCK_IO_LIMIT_TOTAL] != =3D 0) >> + =A0 =A0 =A0 =A0 =A0 =A0&& ((io_limits.iops[BLOCK_IO_LIMIT_READ] !=3D= 0) >> + =A0 =A0 =A0 =A0 =A0 =A0|| (io_limits.iops[BLOCK_IO_LIMIT_WRITE] !=3D= 0)))) { > > -EWRITEONLY Sorry, what does this mean? > > Seriously, break this up into some temporary bool variables if you wa= nt > it to be readable. OK, good advice, and i will. > >> + =A0 =A0 =A0 =A0error_report("bps(iops) and bps_rd/bps_wr(iops_rd/i= ops_wr)" >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "cannot be used at the sam= e time"); >> + =A0 =A0 =A0 =A0return NULL; >> + =A0 =A0} >> + >> =A0 =A0 =A0on_write_error =3D BLOCK_ERR_STOP_ENOSPC; >> =A0 =A0 =A0if ((buf =3D qemu_opt_get(opts, "werror")) !=3D NULL) { >> =A0 =A0 =A0 =A0 =A0if (type !=3D IF_IDE && type !=3D IF_SCSI && type= !=3D IF_VIRTIO && type !=3D IF_NONE) { >> @@ -461,6 +487,9 @@ DriveInfo *drive_init(QemuOpts *opts, int defaul= t_to_scsi) >> >> =A0 =A0 =A0bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_er= ror); >> >> + =A0 =A0/* disk I/O throttling */ >> + =A0 =A0bdrv_set_io_limits(dinfo->bdrv, &io_limits); >> + >> =A0 =A0 =A0switch(type) { >> =A0 =A0 =A0case IF_IDE: >> =A0 =A0 =A0case IF_SCSI: >> diff --git a/qemu-config.c b/qemu-config.c >> index 7a7854f..405e587 100644 >> --- a/qemu-config.c >> +++ b/qemu-config.c >> @@ -85,6 +85,30 @@ static QemuOptsList qemu_drive_opts =3D { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.name =3D "readonly", >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_BOOL, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.help =3D "open drive file as read-only", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit total I/O operations per s= econd", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops_rd", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit read operations per second= ", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops_wr", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit write operations per secon= d", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit total bytes per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps_rd", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit read bytes per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps_wr", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit write bytes per second", >> =A0 =A0 =A0 =A0 =A0}, >> =A0 =A0 =A0 =A0 =A0{ /* end of list */ } >> =A0 =A0 =A0}, >> diff --git a/qemu-options.hx b/qemu-options.hx >> index 659ecb2..2e42c5c 100644 >> --- a/qemu-options.hx >> +++ b/qemu-options.hx >> @@ -136,6 +136,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive, >> =A0 =A0 =A0" =A0 =A0 =A0 [,cache=3Dwritethrough|writeback|none|direc= tsync|unsafe][,format=3Df]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 [,serial=3Ds][,addr=3DA][,id=3Dname][,aio=3D= threads|native]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 [,readonly=3Don|off]\n" >> + =A0 =A0" =A0 =A0 =A0 [[,bps=3Db]|[[,bps_rd=3Dr][,bps_wr=3Dw]]][[,i= ops=3Di]|[[,iops_rd=3Dr][,iops_wr=3Dw]]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0use 'file' as a drive im= age\n", QEMU_ARCH_ALL) >> =A0STEXI >> =A0@item -drive @var{option}[,@var{option}[,@var{option}[,...]]] > > Kevin > --=20 Regards, Zhi Yong Wu From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:52236) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R84T5-0000yD-UC for qemu-devel@nongnu.org; Mon, 26 Sep 2011 02:15:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1R84T4-0004su-J9 for qemu-devel@nongnu.org; Mon, 26 Sep 2011 02:15:07 -0400 Received: from mail-ww0-f53.google.com ([74.125.82.53]:38685) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1R84T4-0004rJ-8f for qemu-devel@nongnu.org; Mon, 26 Sep 2011 02:15:06 -0400 Received: by wwg14 with SMTP id 14so5187972wwg.10 for ; Sun, 25 Sep 2011 23:15:05 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <4E7CABC0.4050501@redhat.com> References: <1315476668-19812-1-git-send-email-wuzhy@linux.vnet.ibm.com> <1315476668-19812-3-git-send-email-wuzhy@linux.vnet.ibm.com> <4E7CABC0.4050501@redhat.com> Date: Mon, 26 Sep 2011 14:15:05 +0800 Message-ID: From: Zhi Yong Wu Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v8 2/4] block: add the command line support List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Kevin Wolf Cc: aliguori@us.ibm.com, stefanha@linux.vnet.ibm.com, kvm@vger.kernel.org, mtosatti@redhat.com, qemu-devel@nongnu.org, pair@us.ibm.com, ryanh@us.ibm.com, Zhi Yong Wu On Fri, Sep 23, 2011 at 11:54 PM, Kevin Wolf wrote: > Am 08.09.2011 12:11, schrieb Zhi Yong Wu: >> Signed-off-by: Zhi Yong Wu >> --- >> =A0block.c =A0 =A0 =A0 =A0 | =A0 59 ++++++++++++++++++++++++++++++++++++= +++++++++++++++++++ >> =A0block.h =A0 =A0 =A0 =A0 | =A0 =A05 ++++ >> =A0block_int.h =A0 =A0 | =A0 =A03 ++ >> =A0blockdev.c =A0 =A0 =A0| =A0 29 +++++++++++++++++++++++++++ >> =A0qemu-config.c =A0 | =A0 24 ++++++++++++++++++++++ >> =A0qemu-options.hx | =A0 =A01 + >> =A06 files changed, 121 insertions(+), 0 deletions(-) >> >> diff --git a/block.c b/block.c >> index 43742b7..cd75183 100644 >> --- a/block.c >> +++ b/block.c >> @@ -104,6 +104,57 @@ int is_windows_drive(const char *filename) >> =A0} >> =A0#endif >> >> +/* throttling disk I/O limits */ >> +void bdrv_io_limits_disable(BlockDriverState *bs) >> +{ >> + =A0 =A0bs->io_limits_enabled =3D false; >> + >> + =A0 =A0if (bs->block_queue) { >> + =A0 =A0 =A0 =A0qemu_block_queue_flush(bs->block_queue); >> + =A0 =A0 =A0 =A0qemu_del_block_queue(bs->block_queue); >> + =A0 =A0 =A0 =A0bs->block_queue =3D NULL; >> + =A0 =A0} >> + >> + =A0 =A0if (bs->block_timer) { >> + =A0 =A0 =A0 =A0qemu_del_timer(bs->block_timer); >> + =A0 =A0 =A0 =A0qemu_free_timer(bs->block_timer); >> + =A0 =A0 =A0 =A0bs->block_timer =A0 =A0 =3D NULL; >> + =A0 =A0} >> + >> + =A0 =A0bs->slice_start =3D 0; >> + >> + =A0 =A0bs->slice_end =A0 =3D 0; > > Remove the empty line between slice_start and slice_end? Yeah, thanks. > >> +} >> + >> +static void bdrv_block_timer(void *opaque) >> +{ >> + =A0 =A0BlockDriverState *bs =3D opaque; >> + =A0 =A0BlockQueue *queue =A0 =A0=3D bs->block_queue; >> + >> + =A0 =A0qemu_block_queue_flush(queue); > > Hm, didn't really notice it while reading patch 1, but > qemu_block_queue_flush() is misleading. It's really something like Why do you say this is misleading? > qemu_block_queue_submit(). Right. It will resubmit all enqueued I/O requests. > >> +} >> + >> +void bdrv_io_limits_enable(BlockDriverState *bs) >> +{ >> + =A0 =A0bs->block_queue =3D qemu_new_block_queue(); >> + =A0 =A0bs->block_timer =3D qemu_new_timer_ns(vm_clock, bdrv_block_time= r, bs); >> + >> + =A0 =A0bs->slice_start =3D qemu_get_clock_ns(vm_clock); >> + >> + =A0 =A0bs->slice_end =A0 =3D bs->slice_start + BLOCK_IO_SLICE_TIME; >> +} > > Same as above. got it. I will remove, thanks. > >> + >> +bool bdrv_io_limits_enabled(BlockDriverState *bs) >> +{ >> + =A0 =A0BlockIOLimit *io_limits =3D &bs->io_limits; >> + =A0 =A0return io_limits->bps[BLOCK_IO_LIMIT_READ] >> + =A0 =A0 =A0 =A0 || io_limits->bps[BLOCK_IO_LIMIT_WRITE] >> + =A0 =A0 =A0 =A0 || io_limits->bps[BLOCK_IO_LIMIT_TOTAL] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_READ] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_WRITE] >> + =A0 =A0 =A0 =A0 || io_limits->iops[BLOCK_IO_LIMIT_TOTAL]; >> +} >> + >> =A0/* check if the path starts with ":" */ >> =A0static int path_has_protocol(const char *path) >> =A0{ >> @@ -1453,6 +1504,14 @@ void bdrv_get_geometry_hint(BlockDriverState *bs, >> =A0 =A0 =A0*psecs =3D bs->secs; >> =A0} >> >> +/* throttling disk io limits */ >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BlockIOLimit *i= o_limits) >> +{ >> + =A0 =A0bs->io_limits =3D *io_limits; >> + =A0 =A0bs->io_limits_enabled =3D bdrv_io_limits_enabled(bs); >> +} >> + >> =A0/* Recognize floppy formats */ >> =A0typedef struct FDFormat { >> =A0 =A0 =A0FDriveType drive; >> diff --git a/block.h b/block.h >> index 3ac0b94..a3e69db 100644 >> --- a/block.h >> +++ b/block.h >> @@ -58,6 +58,11 @@ void bdrv_info(Monitor *mon, QObject **ret_data); >> =A0void bdrv_stats_print(Monitor *mon, const QObject *data); >> =A0void bdrv_info_stats(Monitor *mon, QObject **ret_data); >> >> +/* disk I/O throttling */ >> +void bdrv_io_limits_enable(BlockDriverState *bs); >> +void bdrv_io_limits_disable(BlockDriverState *bs); >> +bool bdrv_io_limits_enabled(BlockDriverState *bs); >> + >> =A0void bdrv_init(void); >> =A0void bdrv_init_with_whitelist(void); >> =A0BlockDriver *bdrv_find_protocol(const char *filename); >> diff --git a/block_int.h b/block_int.h >> index 201e635..368c776 100644 >> --- a/block_int.h >> +++ b/block_int.h >> @@ -257,6 +257,9 @@ void qemu_aio_release(void *p); >> >> =A0void *qemu_blockalign(BlockDriverState *bs, size_t size); >> >> +void bdrv_set_io_limits(BlockDriverState *bs, >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BlockIOLimit *i= o_limits); >> + >> =A0#ifdef _WIN32 >> =A0int is_windows_drive(const char *filename); >> =A0#endif >> diff --git a/blockdev.c b/blockdev.c >> index 2602591..619ae9f 100644 >> --- a/blockdev.c >> +++ b/blockdev.c >> @@ -236,6 +236,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to= _scsi) >> =A0 =A0 =A0int on_read_error, on_write_error; >> =A0 =A0 =A0const char *devaddr; >> =A0 =A0 =A0DriveInfo *dinfo; >> + =A0 =A0BlockIOLimit io_limits; >> =A0 =A0 =A0int snapshot =3D 0; >> =A0 =A0 =A0int ret; >> >> @@ -354,6 +355,31 @@ DriveInfo *drive_init(QemuOpts *opts, int default_t= o_scsi) >> =A0 =A0 =A0 =A0 =A0} >> =A0 =A0 =A0} >> >> + =A0 =A0/* disk I/O throttling */ >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_TOTAL] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "bps", 0); >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_READ] =A0 =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "bps_rd", 0); >> + =A0 =A0io_limits.bps[BLOCK_IO_LIMIT_WRITE] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "bps_wr", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_TOTAL] =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "iops", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_READ] =A0=3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "iops_rd", 0); >> + =A0 =A0io_limits.iops[BLOCK_IO_LIMIT_WRITE] =3D >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 qemu_opt_get_numbe= r(opts, "iops_wr", 0); >> + >> + =A0 =A0if (((io_limits.bps[BLOCK_IO_LIMIT_TOTAL] !=3D 0) >> + =A0 =A0 =A0 =A0 =A0 =A0&& ((io_limits.bps[BLOCK_IO_LIMIT_READ] !=3D 0) >> + =A0 =A0 =A0 =A0 =A0 =A0|| (io_limits.bps[BLOCK_IO_LIMIT_WRITE] !=3D 0)= )) >> + =A0 =A0 =A0 =A0 =A0 =A0|| ((io_limits.iops[BLOCK_IO_LIMIT_TOTAL] !=3D = 0) >> + =A0 =A0 =A0 =A0 =A0 =A0&& ((io_limits.iops[BLOCK_IO_LIMIT_READ] !=3D 0= ) >> + =A0 =A0 =A0 =A0 =A0 =A0|| (io_limits.iops[BLOCK_IO_LIMIT_WRITE] !=3D 0= )))) { > > -EWRITEONLY Sorry, what does this mean? > > Seriously, break this up into some temporary bool variables if you want > it to be readable. OK, good advice, and i will. > >> + =A0 =A0 =A0 =A0error_report("bps(iops) and bps_rd/bps_wr(iops_rd/iops_= wr)" >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "cannot be used at the same ti= me"); >> + =A0 =A0 =A0 =A0return NULL; >> + =A0 =A0} >> + >> =A0 =A0 =A0on_write_error =3D BLOCK_ERR_STOP_ENOSPC; >> =A0 =A0 =A0if ((buf =3D qemu_opt_get(opts, "werror")) !=3D NULL) { >> =A0 =A0 =A0 =A0 =A0if (type !=3D IF_IDE && type !=3D IF_SCSI && type != =3D IF_VIRTIO && type !=3D IF_NONE) { >> @@ -461,6 +487,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to= _scsi) >> >> =A0 =A0 =A0bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error)= ; >> >> + =A0 =A0/* disk I/O throttling */ >> + =A0 =A0bdrv_set_io_limits(dinfo->bdrv, &io_limits); >> + >> =A0 =A0 =A0switch(type) { >> =A0 =A0 =A0case IF_IDE: >> =A0 =A0 =A0case IF_SCSI: >> diff --git a/qemu-config.c b/qemu-config.c >> index 7a7854f..405e587 100644 >> --- a/qemu-config.c >> +++ b/qemu-config.c >> @@ -85,6 +85,30 @@ static QemuOptsList qemu_drive_opts =3D { >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.name =3D "readonly", >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_BOOL, >> =A0 =A0 =A0 =A0 =A0 =A0 =A0.help =3D "open drive file as read-only", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit total I/O operations per secon= d", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops_rd", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit read operations per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "iops_wr", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit write operations per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit total bytes per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps_rd", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit read bytes per second", >> + =A0 =A0 =A0 =A0},{ >> + =A0 =A0 =A0 =A0 =A0 =A0.name =3D "bps_wr", >> + =A0 =A0 =A0 =A0 =A0 =A0.type =3D QEMU_OPT_NUMBER, >> + =A0 =A0 =A0 =A0 =A0 =A0.help =3D "limit write bytes per second", >> =A0 =A0 =A0 =A0 =A0}, >> =A0 =A0 =A0 =A0 =A0{ /* end of list */ } >> =A0 =A0 =A0}, >> diff --git a/qemu-options.hx b/qemu-options.hx >> index 659ecb2..2e42c5c 100644 >> --- a/qemu-options.hx >> +++ b/qemu-options.hx >> @@ -136,6 +136,7 @@ DEF("drive", HAS_ARG, QEMU_OPTION_drive, >> =A0 =A0 =A0" =A0 =A0 =A0 [,cache=3Dwritethrough|writeback|none|directsyn= c|unsafe][,format=3Df]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 [,serial=3Ds][,addr=3DA][,id=3Dname][,aio=3Dthr= eads|native]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 [,readonly=3Don|off]\n" >> + =A0 =A0" =A0 =A0 =A0 [[,bps=3Db]|[[,bps_rd=3Dr][,bps_wr=3Dw]]][[,iops= =3Di]|[[,iops_rd=3Dr][,iops_wr=3Dw]]\n" >> =A0 =A0 =A0" =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0use 'file' as a drive image\= n", QEMU_ARCH_ALL) >> =A0STEXI >> =A0@item -drive @var{option}[,@var{option}[,@var{option}[,...]]] > > Kevin > --=20 Regards, Zhi Yong Wu