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