123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /*
- * 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"
- #include "qemu/main-loop.h"
- #include "qemu/option.h"
- static void fsdev_throttle_read_timer_cb(void *opaque)
- {
- FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
- }
- static void fsdev_throttle_write_timer_cb(void *opaque)
- {
- FsThrottle *fst = opaque;
- qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
- }
- int 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);
- return throttle_is_valid(&fst->cfg, errp) ? 0 : -1;
- }
- 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, QEMU_CLOCK_REALTIME, &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,
- ThrottleDirection direction,
- struct iovec *iov, int iovcnt)
- {
- assert(direction < THROTTLE_MAX);
- if (throttle_enabled(&fst->cfg)) {
- if (throttle_schedule_timer(&fst->ts, &fst->tt, direction) ||
- !qemu_co_queue_empty(&fst->throttled_reqs[direction])) {
- qemu_co_queue_wait(&fst->throttled_reqs[direction], NULL);
- }
- throttle_account(&fst->ts, direction, iov_size(iov, iovcnt));
- if (!qemu_co_queue_empty(&fst->throttled_reqs[direction]) &&
- !throttle_schedule_timer(&fst->ts, &fst->tt, direction)) {
- qemu_co_queue_next(&fst->throttled_reqs[direction]);
- }
- }
- }
- void fsdev_throttle_cleanup(FsThrottle *fst)
- {
- if (throttle_enabled(&fst->cfg)) {
- throttle_timers_destroy(&fst->tt);
- }
- }
|