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