qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH V11 1/1] fsdev: add IO throttle support to fsdev


From: Greg Kurz
Subject: Re: [Qemu-devel] [PATCH V11 1/1] fsdev: add IO throttle support to fsdev devices
Date: Tue, 15 Nov 2016 10:58:23 +0100

On Tue, 15 Nov 2016 10:13:59 +0100
Pradeep Jagadeesh <address@hidden> wrote:

> On 11/14/2016 6:57 PM, Greg Kurz wrote:
> > On Mon, 14 Nov 2016 10:03:40 +0100
> > Pradeep Jagadeesh <address@hidden> wrote:
> >  
> >> On 11/12/2016 3:13 PM, Greg Kurz wrote:  
> >>> On Fri, 11 Nov 2016 03:54:27 -0500
> >>> Pradeep Jagadeesh <address@hidden> wrote:
> >>>  
> >>>> Uses throttling APIs to limit I/O bandwidth and number of operations on 
> >>>> the
> >>>> devices which use 9p-local driver.
> >>>>
> >>>> Signed-off-by: Pradeep Jagadeesh <address@hidden>
> >>>> Reviewed-by: Alberto Garcia" <address@hidden>
> >>>> ---  
> >>>
> >>> Hi Pradeep,
> >>>
> >>> I'll have a look next week but I'm not sure this can go to 2.8 since we're
> >>> already in soft feature freeze (only bug fixes are accepted).  
> >>
> >> Hi Greg,
> >>
> >> It is ok even if it does not make it to 2.8.I just want to complete this
> >> work from my side.
> >>  
> >
> > Hi Pradeep,
> >
> > The patch looks good to me now. Since we're no more in a hurry to get this
> > merged, maybe you can now try to address the code duplication issue with
> > the command line options ? Ideally this should be done in a preparatory
> > patch.
> >  
> 
> OK,I will start that work in couple of weeks. As I am busy with some 
> other work.
> 

Ok. It looks like we can factor two things:
- the set of common throttle options in the QemuOptsList (I already have patch
  for that I can send to be part of your patchset)
- the initialization of the throttle config

BTW, looking at extract_common_blockdev_options(), I have the impression
that a call to throttle_config_init() is missing...

> Cheers,
> Pradeep
[...]
> >>>> +void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error 
> >>>> **errp)
> >>>> +{

... here.

> >>>> +    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 <address@hidden>
> >>>> + *
> >>>> + * 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 e88cf25..8d46a91 100644
> >>>> --- a/hw/9pfs/9p.c
> >>>> +++ b/hw/9pfs/9p.c
> >>>> @@ -3506,6 +3506,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;
> >>>> @@ -3520,6 +3524,7 @@ out:
> >>>>
> >>>>  void v9fs_device_unrealize_common(V9fsState *s, Error **errp)
> >>>>  {
> >>>> +    fsdev_throttle_cleanup(s->ctx.fst);
> >>>>      g_free(s->ctx.fs_root);
> >>>>      g_free(s->tag);
> >>>>  }
> >>>> 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);  
> >>>  
> >>  
> >  
> 
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]