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/option.h"
21 static void fsdev_throttle_read_timer_cb(void *opaque
)
23 FsThrottle
*fst
= opaque
;
24 qemu_co_enter_next(&fst
->throttled_reqs
[false], NULL
);
27 static void fsdev_throttle_write_timer_cb(void *opaque
)
29 FsThrottle
*fst
= opaque
;
30 qemu_co_enter_next(&fst
->throttled_reqs
[true], NULL
);
33 void fsdev_throttle_parse_opts(QemuOpts
*opts
, FsThrottle
*fst
, Error
**errp
)
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);
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);
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);
75 qemu_opt_get_number(opts
, "throttling.iops-size", 0);
77 throttle_is_valid(&fst
->cfg
, errp
);
80 void fsdev_throttle_init(FsThrottle
*fst
)
82 if (throttle_enabled(&fst
->cfg
)) {
83 throttle_init(&fst
->ts
);
84 throttle_timers_init(&fst
->tt
,
85 qemu_get_aio_context(),
87 fsdev_throttle_read_timer_cb
,
88 fsdev_throttle_write_timer_cb
,
90 throttle_config(&fst
->ts
, QEMU_CLOCK_REALTIME
, &fst
->cfg
);
91 qemu_co_queue_init(&fst
->throttled_reqs
[0]);
92 qemu_co_queue_init(&fst
->throttled_reqs
[1]);
96 void coroutine_fn
fsdev_co_throttle_request(FsThrottle
*fst
, bool is_write
,
97 struct iovec
*iov
, int iovcnt
)
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
);
105 throttle_account(&fst
->ts
, is_write
, iov_size(iov
, iovcnt
));
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
]);
114 void fsdev_throttle_cleanup(FsThrottle
*fst
)
116 if (throttle_enabled(&fst
->cfg
)) {
117 throttle_timers_destroy(&fst
->tt
);