4 * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
6 * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or
9 * (at your option) any later version.
11 * See the COPYING file in the top-level directory for details.
15 #include "qemu/osdep.h"
16 #include "qemu/error-report.h"
17 #include "qemu-fsdev-throttle.h"
19 #include "qemu/main-loop.h"
20 #include "qemu/option.h"
22 static void fsdev_throttle_read_timer_cb(void *opaque
)
24 FsThrottle
*fst
= opaque
;
25 qemu_co_enter_next(&fst
->throttled_reqs
[false], NULL
);
28 static void fsdev_throttle_write_timer_cb(void *opaque
)
30 FsThrottle
*fst
= opaque
;
31 qemu_co_enter_next(&fst
->throttled_reqs
[true], NULL
);
34 int fsdev_throttle_parse_opts(QemuOpts
*opts
, FsThrottle
*fst
, Error
**errp
)
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);
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);
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);
76 qemu_opt_get_number(opts
, "throttling.iops-size", 0);
78 return throttle_is_valid(&fst
->cfg
, errp
) ? 0 : -1;
81 void fsdev_throttle_init(FsThrottle
*fst
)
83 if (throttle_enabled(&fst
->cfg
)) {
84 throttle_init(&fst
->ts
);
85 throttle_timers_init(&fst
->tt
,
86 qemu_get_aio_context(),
88 fsdev_throttle_read_timer_cb
,
89 fsdev_throttle_write_timer_cb
,
91 throttle_config(&fst
->ts
, QEMU_CLOCK_REALTIME
, &fst
->cfg
);
92 qemu_co_queue_init(&fst
->throttled_reqs
[0]);
93 qemu_co_queue_init(&fst
->throttled_reqs
[1]);
97 void coroutine_fn
fsdev_co_throttle_request(FsThrottle
*fst
,
98 ThrottleDirection direction
,
99 struct iovec
*iov
, int iovcnt
)
101 assert(direction
< THROTTLE_MAX
);
102 if (throttle_enabled(&fst
->cfg
)) {
103 if (throttle_schedule_timer(&fst
->ts
, &fst
->tt
, direction
) ||
104 !qemu_co_queue_empty(&fst
->throttled_reqs
[direction
])) {
105 qemu_co_queue_wait(&fst
->throttled_reqs
[direction
], NULL
);
108 throttle_account(&fst
->ts
, direction
, iov_size(iov
, iovcnt
));
110 if (!qemu_co_queue_empty(&fst
->throttled_reqs
[direction
]) &&
111 !throttle_schedule_timer(&fst
->ts
, &fst
->tt
, direction
)) {
112 qemu_co_queue_next(&fst
->throttled_reqs
[direction
]);
117 void fsdev_throttle_cleanup(FsThrottle
*fst
)
119 if (throttle_enabled(&fst
->cfg
)) {
120 throttle_timers_destroy(&fst
->tt
);