Pradeep Jagadeesh | b8bbdb8 | 2017-02-28 10:31:46 +0100 | [diff] [blame] | 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 | |
| 20 | static void fsdev_throttle_read_timer_cb(void *opaque) |
| 21 | { |
| 22 | FsThrottle *fst = opaque; |
| 23 | qemu_co_enter_next(&fst->throttled_reqs[false]); |
| 24 | } |
| 25 | |
| 26 | static void fsdev_throttle_write_timer_cb(void *opaque) |
| 27 | { |
| 28 | FsThrottle *fst = opaque; |
| 29 | qemu_co_enter_next(&fst->throttled_reqs[true]); |
| 30 | } |
| 31 | |
| 32 | void 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 | |
| 79 | void 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); |
Manos Pitsidianakis | dbe824c | 2017-07-02 13:06:45 +0300 | [diff] [blame^] | 89 | throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->tt, &fst->cfg); |
Pradeep Jagadeesh | b8bbdb8 | 2017-02-28 10:31:46 +0100 | [diff] [blame] | 90 | qemu_co_queue_init(&fst->throttled_reqs[0]); |
| 91 | qemu_co_queue_init(&fst->throttled_reqs[1]); |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | void 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 | |
| 113 | void fsdev_throttle_cleanup(FsThrottle *fst) |
| 114 | { |
| 115 | if (throttle_enabled(&fst->cfg)) { |
| 116 | throttle_timers_destroy(&fst->tt); |
| 117 | } |
| 118 | } |