diff mbox

[1/2,v16] fsdev: add IO throttle support to fsdev devices

Message ID 1486123043-26493-2-git-send-email-pradeep.jagadeesh@huawei.com
State New
Headers show

Commit Message

Pradeep Jagadeesh Feb. 3, 2017, 11:57 a.m. UTC
This patchset adds the throttle support for the 9p-local driver.
For now this functionality can be enabled only through qemu cli options.
QMP interface and support to other drivers need further extensions.
To make it simple for other 9p drivers, the throttle code has been put in
separate files.

Signed-off-by: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
---
 fsdev/Makefile.objs         |   2 +-
 fsdev/file-op-9p.h          |   3 ++
 fsdev/qemu-fsdev-opts.c     |  77 ++++++++++++++++++++++++++++-
 fsdev/qemu-fsdev-throttle.c | 118 ++++++++++++++++++++++++++++++++++++++++++++
 fsdev/qemu-fsdev-throttle.h |  39 +++++++++++++++
 hw/9pfs/9p-local.c          |   8 +++
 hw/9pfs/9p.c                |   5 ++
 hw/9pfs/cofile.c            |   2 +
 8 files changed, 252 insertions(+), 2 deletions(-)
 create mode 100644 fsdev/qemu-fsdev-throttle.c
 create mode 100644 fsdev/qemu-fsdev-throttle.h

Comments

Alberto Garcia Feb. 3, 2017, 12:21 p.m. UTC | #1
On Fri 03 Feb 2017 12:57:22 PM CET, Pradeep Jagadeesh wrote:

> This patchset adds the throttle support for the 9p-local driver.  For
> now this functionality can be enabled only through qemu cli options.
> QMP interface and support to other drivers need further extensions.
> To make it simple for other 9p drivers, the throttle code has been put
> in separate files.
>
> Signed-off-by: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>

Reviewed-by: Alberto Garcia <berto@igalia.com>

Berto
Eric Blake Feb. 6, 2017, 7:36 p.m. UTC | #2
On 02/03/2017 05:57 AM, Pradeep Jagadeesh wrote:
> This patchset adds the throttle support for the 9p-local driver.
> For now this functionality can be enabled only through qemu cli options.
> QMP interface and support to other drivers need further extensions.

This part is a bit scary - if 2.9 is released with just the cli option
and not the QMP interface, then how does someone like libvirt introspect
whether the feature is available for use?

Please make sure we don't reach 2.9 with only a half-baked feature;
whether that means finishing the QMP work or temporarily disabling the
cli additions until a later release can finish the work.
Greg Kurz Feb. 6, 2017, 11:15 p.m. UTC | #3
On Mon, 6 Feb 2017 13:36:43 -0600
Eric Blake <eblake@redhat.com> wrote:

> On 02/03/2017 05:57 AM, Pradeep Jagadeesh wrote:
> > This patchset adds the throttle support for the 9p-local driver.
> > For now this functionality can be enabled only through qemu cli options.
> > QMP interface and support to other drivers need further extensions.  
> 
> This part is a bit scary - if 2.9 is released with just the cli option
> and not the QMP interface, then how does someone like libvirt introspect
> whether the feature is available for use?
> 

I'm not aware of anything related to fsdev in QMP... and libvirt seems to
only parse the output of -help to guess fsdev capabilities. And indeed,
qemu-options.hx doesn't expose this new feature.

> Please make sure we don't reach 2.9 with only a half-baked feature;
> whether that means finishing the QMP work or temporarily disabling the
> cli additions until a later release can finish the work.
> 

Would this be ok to add the missing bits in qemu-options.hx or do you
expect more ?

Cheers.

--
Greg
Fam Zheng Feb. 7, 2017, 6:18 a.m. UTC | #4
On Mon, 02/06 13:36, Eric Blake wrote:
> On 02/03/2017 05:57 AM, Pradeep Jagadeesh wrote:
> > This patchset adds the throttle support for the 9p-local driver.
> > For now this functionality can be enabled only through qemu cli options.
> > QMP interface and support to other drivers need further extensions.
> 
> This part is a bit scary - if 2.9 is released with just the cli option
> and not the QMP interface, then how does someone like libvirt introspect
> whether the feature is available for use?

Not that I want to make an unconstructive point, but just for understanding
this: if libvirt does introspect via QMP, is it technically okay to release CLI
in 2.9 and QMP in 2.10? libvirt can just ignore the possible existence of CLI
options if QMP is not there, no?

Fam
Greg Kurz Feb. 7, 2017, 10:32 a.m. UTC | #5
On Tue, 7 Feb 2017 00:15:33 +0100
Greg Kurz <groug@kaod.org> wrote:

> On Mon, 6 Feb 2017 13:36:43 -0600
> Eric Blake <eblake@redhat.com> wrote:
> 
> > On 02/03/2017 05:57 AM, Pradeep Jagadeesh wrote:  
> > > This patchset adds the throttle support for the 9p-local driver.
> > > For now this functionality can be enabled only through qemu cli options.
> > > QMP interface and support to other drivers need further extensions.    
> > 
> > This part is a bit scary - if 2.9 is released with just the cli option
> > and not the QMP interface, then how does someone like libvirt introspect
> > whether the feature is available for use?
> >   
> 
> I'm not aware of anything related to fsdev in QMP... and libvirt seems to
> only parse the output of -help to guess fsdev capabilities.

Oops, reading some more libvirt code I now see that libvirt doesn't parse
-help anymore with QEMU >= 1.2.0... sorry for the noise :)

> And indeed,
> qemu-options.hx doesn't expose this new feature.
> 
> > Please make sure we don't reach 2.9 with only a half-baked feature;
> > whether that means finishing the QMP work or temporarily disabling the
> > cli additions until a later release can finish the work.
> >   
> 
> Would this be ok to add the missing bits in qemu-options.hx or do you
> expect more ?
> 
> Cheers.
> 
> --
> Greg
Pradeep Jagadeesh Feb. 7, 2017, 10:34 a.m. UTC | #6
On 2/6/2017 8:36 PM, Eric Blake wrote:
> On 02/03/2017 05:57 AM, Pradeep Jagadeesh wrote:
>> This patchset adds the throttle support for the 9p-local driver.
>> For now this functionality can be enabled only through qemu cli options.
>> QMP interface and support to other drivers need further extensions.
>
> This part is a bit scary - if 2.9 is released with just the cli option
> and not the QMP interface, then how does someone like libvirt introspect
> whether the feature is available for use?
I do have plans to extend the qmp interface for this feature.
Already started looking into it.Do not know, I can push it for 2.9. 
Because I am busy with some other work.
>
> Please make sure we don't reach 2.9 with only a half-baked feature;
> whether that means finishing the QMP work or temporarily disabling the
> cli additions until a later release can finish the work.
>
Eric Blake Feb. 7, 2017, 3:56 p.m. UTC | #7
On 02/07/2017 04:32 AM, Greg Kurz wrote:
>>
>> I'm not aware of anything related to fsdev in QMP... and libvirt seems to
>> only parse the output of -help to guess fsdev capabilities.
> 
> Oops, reading some more libvirt code I now see that libvirt doesn't parse
> -help anymore with QEMU >= 1.2.0... sorry for the noise :)
> 
>> And indeed,
>> qemu-options.hx doesn't expose this new feature.
>>
>>> Please make sure we don't reach 2.9 with only a half-baked feature;
>>> whether that means finishing the QMP work or temporarily disabling the
>>> cli additions until a later release can finish the work.
>>>   
>>
>> Would this be ok to add the missing bits in qemu-options.hx or do you
>> expect more ?

If it cannot be probed via QMP, then libvirt will most likely assume
that it does not exist.  I guess we're okay having command line only in
2.9 if you can't get QMP working, because libvirt will just never drive
the feature until 2.10 when QMP is available; but then we risk the
command line subtly changing and breaking someone else that was using
the command line without QMP.  Maybe the safest approach is to just use
the 'x-' prefix to the command line portion, until the feature is complete.
Greg Kurz Feb. 7, 2017, 4:29 p.m. UTC | #8
Cc'ing Stefan who reviewed patch 2/2.

On Tue, 7 Feb 2017 09:56:08 -0600
Eric Blake <eblake@redhat.com> wrote:

> On 02/07/2017 04:32 AM, Greg Kurz wrote:
> >>
> >> I'm not aware of anything related to fsdev in QMP... and libvirt seems to
> >> only parse the output of -help to guess fsdev capabilities.  
> > 
> > Oops, reading some more libvirt code I now see that libvirt doesn't parse
> > -help anymore with QEMU >= 1.2.0... sorry for the noise :)
> >   
> >> And indeed,
> >> qemu-options.hx doesn't expose this new feature.
> >>  
> >>> Please make sure we don't reach 2.9 with only a half-baked feature;
> >>> whether that means finishing the QMP work or temporarily disabling the
> >>> cli additions until a later release can finish the work.
> >>>     
> >>
> >> Would this be ok to add the missing bits in qemu-options.hx or do you
> >> expect more ?  
> 
> If it cannot be probed via QMP, then libvirt will most likely assume
> that it does not exist.  I guess we're okay having command line only in
> 2.9 if you can't get QMP working, because libvirt will just never drive
> the feature until 2.10 when QMP is available; but then we risk the
> command line subtly changing and breaking someone else that was using
> the command line without QMP.  Maybe the safest approach is to just use
> the 'x-' prefix to the command line portion, until the feature is complete.
> 

The semantics here are exactly the same as for block devices. The
command line options added to -fsdev are the very same already used
by -drive for years.

Patch 2/2 in this series even factors them out to a common header file
to be used by fsdev and blockdev. I really don't expect any modification
at all on the command line (nor the other people who reviewed that patch
obviously)... are you suggesting that we should put 2/2 on hold and
use the 'x-' prefix anyway ?

Cheers.

--
Greg
Stefan Hajnoczi Feb. 14, 2017, 1:21 p.m. UTC | #9
On Tue, Feb 07, 2017 at 05:29:33PM +0100, Greg Kurz wrote:
> Cc'ing Stefan who reviewed patch 2/2.
> 
> On Tue, 7 Feb 2017 09:56:08 -0600
> Eric Blake <eblake@redhat.com> wrote:
> 
> > On 02/07/2017 04:32 AM, Greg Kurz wrote:
> > >>
> > >> I'm not aware of anything related to fsdev in QMP... and libvirt seems to
> > >> only parse the output of -help to guess fsdev capabilities.  
> > > 
> > > Oops, reading some more libvirt code I now see that libvirt doesn't parse
> > > -help anymore with QEMU >= 1.2.0... sorry for the noise :)
> > >   
> > >> And indeed,
> > >> qemu-options.hx doesn't expose this new feature.
> > >>  
> > >>> Please make sure we don't reach 2.9 with only a half-baked feature;
> > >>> whether that means finishing the QMP work or temporarily disabling the
> > >>> cli additions until a later release can finish the work.
> > >>>     
> > >>
> > >> Would this be ok to add the missing bits in qemu-options.hx or do you
> > >> expect more ?  
> > 
> > If it cannot be probed via QMP, then libvirt will most likely assume
> > that it does not exist.  I guess we're okay having command line only in
> > 2.9 if you can't get QMP working, because libvirt will just never drive
> > the feature until 2.10 when QMP is available; but then we risk the
> > command line subtly changing and breaking someone else that was using
> > the command line without QMP.  Maybe the safest approach is to just use
> > the 'x-' prefix to the command line portion, until the feature is complete.
> > 
> 
> The semantics here are exactly the same as for block devices. The
> command line options added to -fsdev are the very same already used
> by -drive for years.
> 
> Patch 2/2 in this series even factors them out to a common header file
> to be used by fsdev and blockdev. I really don't expect any modification
> at all on the command line (nor the other people who reviewed that patch
> obviously)... are you suggesting that we should put 2/2 on hold and
> use the 'x-' prefix anyway ?

I see these parameter names as stable.  There is little risk that they
would change.

Stefan
Greg Kurz Feb. 22, 2017, 1:41 p.m. UTC | #10
Eric,

I fully understand your concern about the missing QMP bits, but given the other
comments people made on this series, I'd like to move forward and merge it for
2.9, without the 'x-' prefixed options. Is it okay with you ?

Cheers.

--
Greg

On Tue, 14 Feb 2017 13:21:22 +0000
Stefan Hajnoczi <stefanha@redhat.com> wrote:

> On Tue, Feb 07, 2017 at 05:29:33PM +0100, Greg Kurz wrote:
> > Cc'ing Stefan who reviewed patch 2/2.
> > 
> > On Tue, 7 Feb 2017 09:56:08 -0600
> > Eric Blake <eblake@redhat.com> wrote:
> >   
> > > On 02/07/2017 04:32 AM, Greg Kurz wrote:  
> > > >>
> > > >> I'm not aware of anything related to fsdev in QMP... and libvirt seems to
> > > >> only parse the output of -help to guess fsdev capabilities.    
> > > > 
> > > > Oops, reading some more libvirt code I now see that libvirt doesn't parse
> > > > -help anymore with QEMU >= 1.2.0... sorry for the noise :)
> > > >     
> > > >> And indeed,
> > > >> qemu-options.hx doesn't expose this new feature.
> > > >>    
> > > >>> Please make sure we don't reach 2.9 with only a half-baked feature;
> > > >>> whether that means finishing the QMP work or temporarily disabling the
> > > >>> cli additions until a later release can finish the work.
> > > >>>       
> > > >>
> > > >> Would this be ok to add the missing bits in qemu-options.hx or do you
> > > >> expect more ?    
> > > 
> > > If it cannot be probed via QMP, then libvirt will most likely assume
> > > that it does not exist.  I guess we're okay having command line only in
> > > 2.9 if you can't get QMP working, because libvirt will just never drive
> > > the feature until 2.10 when QMP is available; but then we risk the
> > > command line subtly changing and breaking someone else that was using
> > > the command line without QMP.  Maybe the safest approach is to just use
> > > the 'x-' prefix to the command line portion, until the feature is complete.
> > >   
> > 
> > The semantics here are exactly the same as for block devices. The
> > command line options added to -fsdev are the very same already used
> > by -drive for years.
> > 
> > Patch 2/2 in this series even factors them out to a common header file
> > to be used by fsdev and blockdev. I really don't expect any modification
> > at all on the command line (nor the other people who reviewed that patch
> > obviously)... are you suggesting that we should put 2/2 on hold and
> > use the 'x-' prefix anyway ?  
> 
> I see these parameter names as stable.  There is little risk that they
> would change.
> 
> Stefan
Eric Blake Feb. 22, 2017, 4:01 p.m. UTC | #11
On 02/22/2017 07:41 AM, Greg Kurz wrote:
> Eric,
> 
> I fully understand your concern about the missing QMP bits, but given the other
> comments people made on this series, I'd like to move forward and merge it for
> 2.9, without the 'x-' prefixed options. Is it okay with you ?

Yes, I think we'll be okay. Libvirt will just be unable to recognize the
feature until the QMP bits are in place.


>>>> If it cannot be probed via QMP, then libvirt will most likely assume
>>>> that it does not exist.  I guess we're okay having command line only in
>>>> 2.9 if you can't get QMP working, because libvirt will just never drive
>>>> the feature until 2.10 when QMP is available; but then we risk the
>>>> command line subtly changing and breaking someone else that was using
>>>> the command line without QMP.  Maybe the safest approach is to just use
>>>> the 'x-' prefix to the command line portion, until the feature is complete.
>>>>   
>>>
>>> The semantics here are exactly the same as for block devices. The
>>> command line options added to -fsdev are the very same already used
>>> by -drive for years.
>>>
>>> Patch 2/2 in this series even factors them out to a common header file
>>> to be used by fsdev and blockdev. I really don't expect any modification
>>> at all on the command line (nor the other people who reviewed that patch
>>> obviously)... are you suggesting that we should put 2/2 on hold and
>>> use the 'x-' prefix anyway ?  
>>
>> I see these parameter names as stable.  There is little risk that they
>> would change.

We just need to be sure that when we do add QMP, that it doesn't use
names that differ from the command line (blockdev is an example where we
weren't careful in 2.8, and had to rename things in 2.9 to be
consistent, and I want to avoid repeating that mistake).
Greg Kurz Feb. 22, 2017, 4:59 p.m. UTC | #12
On Wed, 22 Feb 2017 10:01:09 -0600
Eric Blake <eblake@redhat.com> wrote:

> On 02/22/2017 07:41 AM, Greg Kurz wrote:
> > Eric,
> > 
> > I fully understand your concern about the missing QMP bits, but given the other
> > comments people made on this series, I'd like to move forward and merge it for
> > 2.9, without the 'x-' prefixed options. Is it okay with you ?  
> 
> Yes, I think we'll be okay. Libvirt will just be unable to recognize the
> feature until the QMP bits are in place.
> 

Ok. I'll work this out with Pradeep for 2.10.

> 
> >>>> If it cannot be probed via QMP, then libvirt will most likely assume
> >>>> that it does not exist.  I guess we're okay having command line only in
> >>>> 2.9 if you can't get QMP working, because libvirt will just never drive
> >>>> the feature until 2.10 when QMP is available; but then we risk the
> >>>> command line subtly changing and breaking someone else that was using
> >>>> the command line without QMP.  Maybe the safest approach is to just use
> >>>> the 'x-' prefix to the command line portion, until the feature is complete.
> >>>>     
> >>>
> >>> The semantics here are exactly the same as for block devices. The
> >>> command line options added to -fsdev are the very same already used
> >>> by -drive for years.
> >>>
> >>> Patch 2/2 in this series even factors them out to a common header file
> >>> to be used by fsdev and blockdev. I really don't expect any modification
> >>> at all on the command line (nor the other people who reviewed that patch
> >>> obviously)... are you suggesting that we should put 2/2 on hold and
> >>> use the 'x-' prefix anyway ?    
> >>
> >> I see these parameter names as stable.  There is little risk that they
> >> would change.  
> 
> We just need to be sure that when we do add QMP, that it doesn't use
> names that differ from the command line (blockdev is an example where we
> weren't careful in 2.8, and had to rename things in 2.9 to be
> consistent, and I want to avoid repeating that mistake).
> 

Can you provide some pointers on what had to be fixed in blockdev ?

Thanks.

--
Greg
Eric Blake Feb. 22, 2017, 5:04 p.m. UTC | #13
On 02/22/2017 10:59 AM, Greg Kurz wrote:

>>>> I see these parameter names as stable.  There is little risk that they
>>>> would change.  
>>
>> We just need to be sure that when we do add QMP, that it doesn't use
>> names that differ from the command line (blockdev is an example where we
>> weren't careful in 2.8, and had to rename things in 2.9 to be
>> consistent, and I want to avoid repeating that mistake).
>>
> 
> Can you provide some pointers on what had to be fixed in blockdev ?

See for example commits f67409a, 4230e5d, 1a417e4 showing several cases
where we had to fix up inconsistencies.
diff mbox

Patch

diff --git a/fsdev/Makefile.objs b/fsdev/Makefile.objs
index 1b120a4..659df6e 100644
--- a/fsdev/Makefile.objs
+++ b/fsdev/Makefile.objs
@@ -5,7 +5,7 @@  common-obj-y = qemu-fsdev.o 9p-marshal.o 9p-iov-marshal.o
 else
 common-obj-y = qemu-fsdev-dummy.o
 endif
-common-obj-y += qemu-fsdev-opts.o
+common-obj-y += qemu-fsdev-opts.o qemu-fsdev-throttle.o
 
 # Toplevel always builds this; targets without virtio will put it in
 # common-obj-y
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index a56dc84..0844a40 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -17,6 +17,7 @@ 
 #include <dirent.h>
 #include <utime.h>
 #include <sys/vfs.h>
+#include "qemu-fsdev-throttle.h"
 
 #define SM_LOCAL_MODE_BITS    0600
 #define SM_LOCAL_DIR_MODE_BITS    0700
@@ -74,6 +75,7 @@  typedef struct FsDriverEntry {
     char *path;
     int export_flags;
     FileOperations *ops;
+    FsThrottle fst;
 } FsDriverEntry;
 
 typedef struct FsContext
@@ -83,6 +85,7 @@  typedef struct FsContext
     int export_flags;
     struct xattr_operations **xops;
     struct extended_ops exops;
+    FsThrottle *fst;
     /* fs driver specific data */
     void *private;
 } FsContext;
diff --git a/fsdev/qemu-fsdev-opts.c b/fsdev/qemu-fsdev-opts.c
index 1dd8c7a..385423f0 100644
--- a/fsdev/qemu-fsdev-opts.c
+++ b/fsdev/qemu-fsdev-opts.c
@@ -37,8 +37,83 @@  static QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "throttling.iops-total",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total I/O operations per second",
+        }, {
+            .name = "throttling.iops-read",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read operations per second",
+        }, {
+            .name = "throttling.iops-write",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write operations per second",
+        }, {
+            .name = "throttling.bps-total",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit total bytes per second",
+        }, {
+            .name = "throttling.bps-read",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit read bytes per second",
+        }, {
+            .name = "throttling.bps-write",
+            .type = QEMU_OPT_NUMBER,
+            .help = "limit write bytes per second",
+        }, {
+            .name = "throttling.iops-total-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations burst",
+        }, {
+            .name = "throttling.iops-read-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations read burst",
+        }, {
+            .name = "throttling.iops-write-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "I/O operations write burst",
+        }, {
+            .name = "throttling.bps-total-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes burst",
+        }, {
+            .name = "throttling.bps-read-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes read burst",
+        }, {
+            .name = "throttling.bps-write-max",
+            .type = QEMU_OPT_NUMBER,
+            .help = "total bytes write burst",
+        }, {
+            .name = "throttling.iops-total-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the iops-total-max burst period, in seconds",
+        }, {
+            .name = "throttling.iops-read-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the iops-read-max burst period, in seconds",
+        }, {
+            .name = "throttling.iops-write-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the iops-write-max burst period, in seconds",
+        }, {
+            .name = "throttling.bps-total-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the bps-total-max burst period, in seconds",
+        }, {
+            .name = "throttling.bps-read-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the bps-read-max burst period, in seconds",
+        }, {
+            .name = "throttling.bps-write-max-length",
+            .type = QEMU_OPT_NUMBER,
+            .help = "length of the bps-write-max burst period, in seconds",
+        }, {
+            .name = "throttling.iops-size",
+            .type = QEMU_OPT_NUMBER,
+            .help = "when limiting by iops max size of an I/O in bytes",
         },
-
         { /*End of list */ }
     },
 };
diff --git a/fsdev/qemu-fsdev-throttle.c b/fsdev/qemu-fsdev-throttle.c
new file mode 100644
index 0000000..feb9af3
--- /dev/null
+++ b/fsdev/qemu-fsdev-throttle.c
@@ -0,0 +1,118 @@ 
+/*
+ * Fsdev Throttle
+ *
+ * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu-fsdev-throttle.h"
+#include "qemu/iov.h"
+
+static void fsdev_throttle_read_timer_cb(void *opaque)
+{
+    FsThrottle *fst = opaque;
+    qemu_co_enter_next(&fst->throttled_reqs[false]);
+}
+
+static void fsdev_throttle_write_timer_cb(void *opaque)
+{
+    FsThrottle *fst = opaque;
+    qemu_co_enter_next(&fst->throttled_reqs[true]);
+}
+
+void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
+{
+    throttle_config_init(&fst->cfg);
+    fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
+        qemu_opt_get_number(opts, "throttling.bps-total", 0);
+    fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
+        qemu_opt_get_number(opts, "throttling.bps-read", 0);
+    fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
+        qemu_opt_get_number(opts, "throttling.bps-write", 0);
+    fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
+        qemu_opt_get_number(opts, "throttling.iops-total", 0);
+    fst->cfg.buckets[THROTTLE_OPS_READ].avg =
+        qemu_opt_get_number(opts, "throttling.iops-read", 0);
+    fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
+        qemu_opt_get_number(opts, "throttling.iops-write", 0);
+
+    fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
+        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
+    fst->cfg.buckets[THROTTLE_BPS_READ].max  =
+        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
+    fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
+        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
+    fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
+        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
+    fst->cfg.buckets[THROTTLE_OPS_READ].max =
+        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
+    fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
+        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
+
+    fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
+        qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
+    fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
+        qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
+    fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
+        qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
+    fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
+        qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
+    fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
+        qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
+    fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
+        qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
+    fst->cfg.op_size =
+        qemu_opt_get_number(opts, "throttling.iops-size", 0);
+
+    throttle_is_valid(&fst->cfg, errp);
+}
+
+void fsdev_throttle_init(FsThrottle *fst)
+{
+    if (throttle_enabled(&fst->cfg)) {
+        throttle_init(&fst->ts);
+        throttle_timers_init(&fst->tt,
+                             qemu_get_aio_context(),
+                             QEMU_CLOCK_REALTIME,
+                             fsdev_throttle_read_timer_cb,
+                             fsdev_throttle_write_timer_cb,
+                             fst);
+        throttle_config(&fst->ts, &fst->tt, &fst->cfg);
+        qemu_co_queue_init(&fst->throttled_reqs[0]);
+        qemu_co_queue_init(&fst->throttled_reqs[1]);
+    }
+}
+
+void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
+                                            struct iovec *iov, int iovcnt)
+{
+    if (throttle_enabled(&fst->cfg)) {
+        if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
+            !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
+            qemu_co_queue_wait(&fst->throttled_reqs[is_write]);
+        }
+
+        throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
+
+        if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
+            !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
+            qemu_co_queue_next(&fst->throttled_reqs[is_write]);
+        }
+    }
+}
+
+void fsdev_throttle_cleanup(FsThrottle *fst)
+{
+    if (throttle_enabled(&fst->cfg)) {
+        throttle_timers_destroy(&fst->tt);
+    }
+}
diff --git a/fsdev/qemu-fsdev-throttle.h b/fsdev/qemu-fsdev-throttle.h
new file mode 100644
index 0000000..e418643
--- /dev/null
+++ b/fsdev/qemu-fsdev-throttle.h
@@ -0,0 +1,39 @@ 
+/*
+ * Fsdev Throttle
+ *
+ * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version.
+ *
+ * See the COPYING file in the top-level directory for details.
+ *
+ */
+
+#ifndef _FSDEV_THROTTLE_H
+#define _FSDEV_THROTTLE_H
+
+#include "block/aio.h"
+#include "qemu/main-loop.h"
+#include "qemu/coroutine.h"
+#include "qapi/error.h"
+#include "qemu/throttle.h"
+
+typedef struct FsThrottle {
+    ThrottleState ts;
+    ThrottleTimers tt;
+    ThrottleConfig cfg;
+    CoQueue      throttled_reqs[2];
+} FsThrottle;
+
+void fsdev_throttle_parse_opts(QemuOpts *, FsThrottle *, Error **);
+
+void fsdev_throttle_init(FsThrottle *);
+
+void coroutine_fn fsdev_co_throttle_request(FsThrottle *, bool ,
+                                            struct iovec *, int);
+
+void fsdev_throttle_cleanup(FsThrottle *);
+#endif /* _FSDEV_THROTTLE_H */
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 845675e..828348d 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1209,6 +1209,7 @@  static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
 {
     const char *sec_model = qemu_opt_get(opts, "security_model");
     const char *path = qemu_opt_get(opts, "path");
+    Error *err = NULL;
 
     if (!sec_model) {
         error_report("Security model not specified, local fs needs security model");
@@ -1237,6 +1238,13 @@  static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
         error_report("fsdev: No path specified");
         return -1;
     }
+
+    fsdev_throttle_parse_opts(opts, &fse->fst, &err);
+    if (err) {
+        error_reportf_err(err, "Throttle configuration is not valid: ");
+        return -1;
+    }
+
     fse->path = g_strdup(path);
 
     return 0;
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index fa58877..22a6a99 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3520,6 +3520,10 @@  int v9fs_device_realize_common(V9fsState *s, Error **errp)
         error_setg(errp, "share path %s is not a directory", fse->path);
         goto out;
     }
+
+    s->ctx.fst = &fse->fst;
+    fsdev_throttle_init(s->ctx.fst);
+
     v9fs_path_free(&path);
 
     rc = 0;
@@ -3540,6 +3544,7 @@  void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
     if (s->ops->cleanup) {
         s->ops->cleanup(&s->ctx);
     }
+    fsdev_throttle_cleanup(s->ctx.fst);
     g_free(s->tag);
     g_free(s->ctx.fs_root);
 }
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 120e267..88791bc 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -247,6 +247,7 @@  int coroutine_fn v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp,
     if (v9fs_request_cancelled(pdu)) {
         return -EINTR;
     }
+    fsdev_co_throttle_request(s->ctx.fst, true, iov, iovcnt);
     v9fs_co_run_in_worker(
         {
             err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset);
@@ -266,6 +267,7 @@  int coroutine_fn v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp,
     if (v9fs_request_cancelled(pdu)) {
         return -EINTR;
     }
+    fsdev_co_throttle_request(s->ctx.fst, false, iov, iovcnt);
     v9fs_co_run_in_worker(
         {
             err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset);