 e76f201f69
			
		
	
	
		e76f201f69
		
	
	
	
	
		
			
			enum ThrottleDirection is already there, use ThrottleDirection instead of 'bool is_write' for throttle API, also modify related codes from block, fsdev, cryptodev and tests. Reviewed-by: Hanna Czenczek <hreitz@redhat.com> Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> Message-Id: <20230728022006.1098509-7-pizhenwei@bytedance.com> Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
		
			
				
	
	
		
			123 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Fsdev Throttle
 | |
|  *
 | |
|  * Copyright (C) 2016 Huawei Technologies Duesseldorf GmbH
 | |
|  *
 | |
|  * Author: Pradeep Jagadeesh <pradeep.jagadeesh@huawei.com>
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL, version 2 or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * See the COPYING file in the top-level directory for details.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu/error-report.h"
 | |
| #include "qemu-fsdev-throttle.h"
 | |
| #include "qemu/iov.h"
 | |
| #include "qemu/main-loop.h"
 | |
| #include "qemu/option.h"
 | |
| 
 | |
| static void fsdev_throttle_read_timer_cb(void *opaque)
 | |
| {
 | |
|     FsThrottle *fst = opaque;
 | |
|     qemu_co_enter_next(&fst->throttled_reqs[false], NULL);
 | |
| }
 | |
| 
 | |
| static void fsdev_throttle_write_timer_cb(void *opaque)
 | |
| {
 | |
|     FsThrottle *fst = opaque;
 | |
|     qemu_co_enter_next(&fst->throttled_reqs[true], NULL);
 | |
| }
 | |
| 
 | |
| int fsdev_throttle_parse_opts(QemuOpts *opts, FsThrottle *fst, Error **errp)
 | |
| {
 | |
|     throttle_config_init(&fst->cfg);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_TOTAL].avg =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-total", 0);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_READ].avg  =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-read", 0);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_WRITE].avg =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-write", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_TOTAL].avg =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-total", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_READ].avg =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-read", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_WRITE].avg =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-write", 0);
 | |
| 
 | |
|     fst->cfg.buckets[THROTTLE_BPS_TOTAL].max =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-total-max", 0);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_READ].max  =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-read-max", 0);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_WRITE].max =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-write-max", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_TOTAL].max =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-total-max", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_READ].max =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-read-max", 0);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_WRITE].max =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-write-max", 0);
 | |
| 
 | |
|     fst->cfg.buckets[THROTTLE_BPS_TOTAL].burst_length =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-total-max-length", 1);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_READ].burst_length  =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-read-max-length", 1);
 | |
|     fst->cfg.buckets[THROTTLE_BPS_WRITE].burst_length =
 | |
|         qemu_opt_get_number(opts, "throttling.bps-write-max-length", 1);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_TOTAL].burst_length =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-total-max-length", 1);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_READ].burst_length =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-read-max-length", 1);
 | |
|     fst->cfg.buckets[THROTTLE_OPS_WRITE].burst_length =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-write-max-length", 1);
 | |
|     fst->cfg.op_size =
 | |
|         qemu_opt_get_number(opts, "throttling.iops-size", 0);
 | |
| 
 | |
|     return throttle_is_valid(&fst->cfg, errp) ? 0 : -1;
 | |
| }
 | |
| 
 | |
| void fsdev_throttle_init(FsThrottle *fst)
 | |
| {
 | |
|     if (throttle_enabled(&fst->cfg)) {
 | |
|         throttle_init(&fst->ts);
 | |
|         throttle_timers_init(&fst->tt,
 | |
|                              qemu_get_aio_context(),
 | |
|                              QEMU_CLOCK_REALTIME,
 | |
|                              fsdev_throttle_read_timer_cb,
 | |
|                              fsdev_throttle_write_timer_cb,
 | |
|                              fst);
 | |
|         throttle_config(&fst->ts, QEMU_CLOCK_REALTIME, &fst->cfg);
 | |
|         qemu_co_queue_init(&fst->throttled_reqs[0]);
 | |
|         qemu_co_queue_init(&fst->throttled_reqs[1]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void coroutine_fn fsdev_co_throttle_request(FsThrottle *fst, bool is_write,
 | |
|                                             struct iovec *iov, int iovcnt)
 | |
| {
 | |
|     ThrottleDirection direction = is_write ? THROTTLE_WRITE : THROTTLE_READ;
 | |
| 
 | |
|     if (throttle_enabled(&fst->cfg)) {
 | |
|         if (throttle_schedule_timer(&fst->ts, &fst->tt, direction) ||
 | |
|             !qemu_co_queue_empty(&fst->throttled_reqs[is_write])) {
 | |
|             qemu_co_queue_wait(&fst->throttled_reqs[is_write], NULL);
 | |
|         }
 | |
| 
 | |
|         throttle_account(&fst->ts, direction, iov_size(iov, iovcnt));
 | |
| 
 | |
|         if (!qemu_co_queue_empty(&fst->throttled_reqs[is_write]) &&
 | |
|             !throttle_schedule_timer(&fst->ts, &fst->tt, direction)) {
 | |
|             qemu_co_queue_next(&fst->throttled_reqs[is_write]);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void fsdev_throttle_cleanup(FsThrottle *fst)
 | |
| {
 | |
|     if (throttle_enabled(&fst->cfg)) {
 | |
|         throttle_timers_destroy(&fst->tt);
 | |
|     }
 | |
| }
 |