Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2017-03-16' into staging
[qemu.git] / fsdev / qemu-fsdev-throttle.c
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);
89 throttle_config(&fst->ts, &fst->tt, &fst->cfg);
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 }