qemu-fsdev-throttle.c (4596B)
1/* 2 * Fsdev Throttle 3 * 4 * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH 5 * 6 * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com> 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" 19#include "qemu/main-loop.h" 20#include "qemu/option.h" 21 22static void fsdev_throttle_read_timer_cb(void *opaque) 23{ 24 FsThrottle *fst = opaque; 25 qemu_co_enter_next(&fst->throttled_reqs[false], NULL); 26} 27 28static void fsdev_throttle_write_timer_cb(void *opaque) 29{ 30 FsThrottle *fst = opaque; 31 qemu_co_enter_next(&fst->throttled_reqs[true], NULL); 32} 33 34int 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 return throttle_is_valid(&fst->cfg, errp) ? 0 : -1; 79} 80 81void 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); 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]); 94 } 95} 96 97void 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 115void fsdev_throttle_cleanup(FsThrottle *fst) 116{ 117 if (throttle_enabled(&fst->cfg)) { 118 throttle_timers_destroy(&fst->tt); 119 } 120}