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/main-loop.h"
  20#include "qemu/option.h"
  21
  22static void fsdev_throttle_read_timer_cb(void *opaque)
  23{
  24    FsThrottle *fst = opaque;
  25    qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
  26}
  27
  28static void fsdev_throttle_write_timer_cb(void *opaque)
  29{
  30    FsThrottle *fst = opaque;
  31    qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
  32}
  33
  34int fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
  35{
  36    throttle_config_init(&fst->cfg);
  37    fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
  38        qemu_opt_get_number(opts, "throttling.bps-total", 0);
  39    fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
  40        qemu_opt_get_number(opts, "throttling.bps-read", 0);
  41    fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
  42        qemu_opt_get_number(opts, "throttling.bps-write", 0);
  43    fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
  44        qemu_opt_get_number(opts, "throttling.iops-total", 0);
  45    fst->cfg.buckets[THROTTLE_OPS_READ].avg =
  46        qemu_opt_get_number(opts, "throttling.iops-read", 0);
  47    fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
  48        qemu_opt_get_number(opts, "throttling.iops-write", 0);
  49
  50    fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
  51        qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
  52    fst->cfg.buckets[THROTTLE_BPS_READ].max  =
  53        qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
  54    fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
  55        qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
  56    fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
  57        qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
  58    fst->cfg.buckets[THROTTLE_OPS_READ].max =
  59        qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
  60    fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
  61        qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
  62
  63    fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
  64        qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
  65    fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
  66        qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
  67    fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
  68        qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
  69    fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
  70        qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
  71    fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
  72        qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
  73    fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
  74        qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
  75    fst->cfg.op_size =
  76        qemu_opt_get_number(opts, "throttling.iops-size", 0);
  77
  78    return throttle_is_valid(&fst->cfg, errp) ? 0 : -1;
  79}
  80
  81void fsdev_throttle_init(FsThrottle *fst)
  82{
  83    if (throttle_enabled(&fst->cfg)) {
  84        throttle_init(&fst->ts);
  85        throttle_timers_init(&fst->tt,
  86                             qemu_get_aio_context(),
  87                             QEMU_CLOCK_REALTIME,
  88                             fsdev_throttle_read_timer_cb,
  89                             fsdev_throttle_write_timer_cb,
  90                             fst);
  91        throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
  92        qemu_co_queue_init(&fst->throttled_reqs[0]);
  93        qemu_co_queue_init(&fst->throttled_reqs[1]);
  94    }
  95}
  96
  97void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
  98                                            struct iovec *iov, int iovcnt)
  99{
 100    if (throttle_enabled(&fst->cfg)) {
 101        if (throttle_schedule_timer(&fst->ts, &fst->tt, is_write) ||
 102            !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
 103            qemu_co_queue_wait(&fst->throttled_reqs[is_write], NULL);
 104        }
 105
 106        throttle_account(&fst->ts, is_write, iov_size(iov, iovcnt));
 107
 108        if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
 109            !throttle_schedule_timer(&fst->ts, &fst->tt, is_write)) {
 110            qemu_co_queue_next(&fst->throttled_reqs[is_write]);
 111        }
 112    }
 113}
 114
 115void fsdev_throttle_cleanup(FsThrottle *fst)
 116{
 117    if (throttle_enabled(&fst->cfg)) {
 118        throttle_timers_destroy(&fst->tt);
 119    }
 120}
 121