xref: /qemu/fsdev/qemu-fsdev-throttle.c (revision 00ea69f5)
1b8bbdb88SPradeep Jagadeesh /*
2b8bbdb88SPradeep Jagadeesh  * Fsdev Throttle
3b8bbdb88SPradeep Jagadeesh  *
4b8bbdb88SPradeep Jagadeesh  * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
5b8bbdb88SPradeep Jagadeesh  *
6b8bbdb88SPradeep Jagadeesh  * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
7b8bbdb88SPradeep Jagadeesh  *
8b8bbdb88SPradeep Jagadeesh  * This work is licensed under the terms of the GNU GPL, version 2 or
9b8bbdb88SPradeep Jagadeesh  * (at your option) any later version.
10b8bbdb88SPradeep Jagadeesh  *
11b8bbdb88SPradeep Jagadeesh  * See the COPYING file in the top-level directory for details.
12b8bbdb88SPradeep Jagadeesh  *
13b8bbdb88SPradeep Jagadeesh  */
14b8bbdb88SPradeep Jagadeesh 
15b8bbdb88SPradeep Jagadeesh #include "qemu/osdep.h"
16b8bbdb88SPradeep Jagadeesh #include "qemu/error-report.h"
17b8bbdb88SPradeep Jagadeesh #include "qemu-fsdev-throttle.h"
18b8bbdb88SPradeep Jagadeesh #include "qemu/iov.h"
19db725815SMarkus Armbruster #include "qemu/main-loop.h"
20922a01a0SMarkus Armbruster #include "qemu/option.h"
21b8bbdb88SPradeep Jagadeesh 
fsdev_throttle_read_timer_cb(void * opaque)22b8bbdb88SPradeep Jagadeesh static void fsdev_throttle_read_timer_cb(void *opaque)
23b8bbdb88SPradeep Jagadeesh {
24b8bbdb88SPradeep Jagadeesh     FsThrottle *fst = opaque;
255261dd7bSPaolo Bonzini     qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
26b8bbdb88SPradeep Jagadeesh }
27b8bbdb88SPradeep Jagadeesh 
fsdev_throttle_write_timer_cb(void * opaque)28b8bbdb88SPradeep Jagadeesh static void fsdev_throttle_write_timer_cb(void *opaque)
29b8bbdb88SPradeep Jagadeesh {
30b8bbdb88SPradeep Jagadeesh     FsThrottle *fst = opaque;
315261dd7bSPaolo Bonzini     qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
32b8bbdb88SPradeep Jagadeesh }
33b8bbdb88SPradeep Jagadeesh 
fsdev_throttle_parse_opts(QemuOpts * opts,FsThrottle * fst,Error ** errp)34ea52cdd4SGreg Kurz int fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
35b8bbdb88SPradeep Jagadeesh {
36b8bbdb88SPradeep Jagadeesh     throttle_config_init(&fst->cfg);
37b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
38b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-total", 0);
39b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
40b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-read", 0);
41b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
42b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-write", 0);
43b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
44b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-total", 0);
45b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_READ].avg =
46b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-read", 0);
47b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
48b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-write", 0);
49b8bbdb88SPradeep Jagadeesh 
50b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
51b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
52b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_READ].max  =
53b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
54b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
55b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
56b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
57b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
58b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_READ].max =
59b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
60b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
61b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
62b8bbdb88SPradeep Jagadeesh 
63b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
64b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
65b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
66b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
67b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
68b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
69b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
70b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
71b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
72b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
73b8bbdb88SPradeep Jagadeesh     fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
74b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
75b8bbdb88SPradeep Jagadeesh     fst->cfg.op_size =
76b8bbdb88SPradeep Jagadeesh         qemu_opt_get_number(opts, "throttling.iops-size", 0);
77b8bbdb88SPradeep Jagadeesh 
78ea52cdd4SGreg Kurz     return throttle_is_valid(&fst->cfg, errp) ? 0 : -1;
79b8bbdb88SPradeep Jagadeesh }
80b8bbdb88SPradeep Jagadeesh 
fsdev_throttle_init(FsThrottle * fst)81b8bbdb88SPradeep Jagadeesh void fsdev_throttle_init(FsThrottle *fst)
82b8bbdb88SPradeep Jagadeesh {
83b8bbdb88SPradeep Jagadeesh     if (throttle_enabled(&fst->cfg)) {
84b8bbdb88SPradeep Jagadeesh         throttle_init(&fst->ts);
85b8bbdb88SPradeep Jagadeesh         throttle_timers_init(&fst->tt,
86b8bbdb88SPradeep Jagadeesh                              qemu_get_aio_context(),
87b8bbdb88SPradeep Jagadeesh                              QEMU_CLOCK_REALTIME,
88b8bbdb88SPradeep Jagadeesh                              fsdev_throttle_read_timer_cb,
89b8bbdb88SPradeep Jagadeesh                              fsdev_throttle_write_timer_cb,
90b8bbdb88SPradeep Jagadeesh                              fst);
9127e4cf13SManos Pitsidianakis         throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
92b8bbdb88SPradeep Jagadeesh         qemu_co_queue_init(&fst->throttled_reqs[0]);
93b8bbdb88SPradeep Jagadeesh         qemu_co_queue_init(&fst->throttled_reqs[1]);
94b8bbdb88SPradeep Jagadeesh     }
95b8bbdb88SPradeep Jagadeesh }
96b8bbdb88SPradeep Jagadeesh 
fsdev_co_throttle_request(FsThrottle * fst,ThrottleDirection direction,struct iovec * iov,int iovcnt)9700ea69f5Szhenwei pi void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst,
9800ea69f5Szhenwei pi                                             ThrottleDirection direction,
99b8bbdb88SPradeep Jagadeesh                                             struct iovec *iov, int iovcnt)
100b8bbdb88SPradeep Jagadeesh {
10100ea69f5Szhenwei pi     assert(direction < THROTTLE_MAX);
102b8bbdb88SPradeep Jagadeesh     if (throttle_enabled(&fst->cfg)) {
103e76f201fSzhenwei pi         if (throttle_schedule_timer(&fst->ts, &fst->tt, direction) ||
10400ea69f5Szhenwei pi             !qemu_co_queue_empty(&fst->throttled_reqs[direction])) {
10500ea69f5Szhenwei pi             qemu_co_queue_wait(&fst->throttled_reqs[direction], NULL);
106b8bbdb88SPradeep Jagadeesh         }
107b8bbdb88SPradeep Jagadeesh 
108e76f201fSzhenwei pi         throttle_account(&fst->ts, direction, iov_size(iov, iovcnt));
109b8bbdb88SPradeep Jagadeesh 
11000ea69f5Szhenwei pi         if (!qemu_co_queue_empty(&fst->throttled_reqs[direction]) &&
111e76f201fSzhenwei pi             !throttle_schedule_timer(&fst->ts, &fst->tt, direction)) {
11200ea69f5Szhenwei pi             qemu_co_queue_next(&fst->throttled_reqs[direction]);
113b8bbdb88SPradeep Jagadeesh         }
114b8bbdb88SPradeep Jagadeesh     }
115b8bbdb88SPradeep Jagadeesh }
116b8bbdb88SPradeep Jagadeesh 
fsdev_throttle_cleanup(FsThrottle * fst)117b8bbdb88SPradeep Jagadeesh void fsdev_throttle_cleanup(FsThrottle *fst)
118b8bbdb88SPradeep Jagadeesh {
119b8bbdb88SPradeep Jagadeesh     if (throttle_enabled(&fst->cfg)) {
120b8bbdb88SPradeep Jagadeesh         throttle_timers_destroy(&fst->tt);
121b8bbdb88SPradeep Jagadeesh     }
122b8bbdb88SPradeep Jagadeesh }
123