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