qemu/fsdev/qemu-fsdev-throttle.c
<<
>>
Prefs
   1/*
   2 * Fsdev Throttle
   3 *
   4 * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
   5 *
   6 * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or
   9 * (at your option) any later version.
  10 *
  11 * See the COPYING file in the top-level directory for details.
  12 *
  13 */
  14
  15#include "qemu/osdep.h"
  16#include "qemu/error-report.h"
  17#include "qemu-fsdev-throttle.h"
  18#include "qemu/iov.h"
  19#include "qemu/option.h"
  20
  21static void fsdev_throttle_read_timer_cb(void *opaque)
  22{
  23    FsThrottle *fst = opaque;
  24    qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
  25}
  26
  27static void fsdev_throttle_write_timer_cb(void *opaque)
  28{
  29    FsThrottle *fst = opaque;
  30    qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
  31}
  32
  33void fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
  34{
  35    throttle_config_init(&fst->cfg);
  36    fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
  37        qemu_opt_get_number(opts, "throttling.bps-total", 0);
  38    fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
  39        qemu_opt_get_number(opts, "throttling.bps-read", 0);
  40    fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
  41        qemu_opt_get_number(opts, "throttling.bps-write", 0);
  42    fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
  43        qemu_opt_get_number(opts, "throttling.iops-total", 0);
  44    fst->cfg.buckets[THROTTLE_OPS_READ].avg =
  45        qemu_opt_get_number(opts, "throttling.iops-read", 0);
  46    fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
  47        qemu_opt_get_number(opts, "throttling.iops-write", 0);
  48
  49    fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
  50        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
  51    fst->cfg.buckets[THROTTLE_BPS_READ].max  =
  52        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
  53    fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
  54        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
  55    fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
  56        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
  57    fst->cfg.buckets[THROTTLE_OPS_READ].max =
  58        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
  59    fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
  60        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
  61
  62    fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
  63        qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
  64    fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
  65        qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
  66    fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
  67        qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
  68    fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
  69        qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
  70    fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
  71        qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
  72    fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
  73        qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
  74    fst->cfg.op_size =
  75        qemu_opt_get_number(opts, "throttling.iops-size", 0);
  76
  77    throttle_is_valid(&fst->cfg, errp);
  78}
  79
  80void fsdev_throttle_init(FsThrottle *fst)
  81{
  82    if (throttle_enabled(&fst->cfg)) {
  83        throttle_init(&fst->ts);
  84        throttle_timers_init(&fst->tt,
  85                             qemu_get_aio_context(),
  86                             QEMU_CLOCK_REALTIME,
  87                             fsdev_throttle_read_timer_cb,
  88                             fsdev_throttle_write_timer_cb,
  89                             fst);
  90        throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
  91        qemu_co_queue_init(&fst->throttled_reqs[0]);
  92        qemu_co_queue_init(&fst->throttled_reqs[1]);
  93    }
  94}
  95
  96void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
  97                                            struct iovec *iov, int iovcnt)
  98{
  99    if (throttle_enabled(&fst->cfg)) {
 100        if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
 101            !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
 102            qemu_co_queue_wait(&fst->throttled_reqs[is_write], NULL);
 103        }
 104
 105        throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
 106
 107        if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
 108            !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
 109            qemu_co_queue_next(&fst->throttled_reqs[is_write]);
 110        }
 111    }
 112}
 113
 114void fsdev_throttle_cleanup(FsThrottle *fst)
 115{
 116    if (throttle_enabled(&fst->cfg)) {
 117        throttle_timers_destroy(&fst->tt);
 118    }
 119}
 120