 801625e69d
			
		
	
	
		801625e69d
		
	
	
	
	
		
			
			The function is called from 64bit io handlers, and bytes is just passed
to throttle_account() which is 64bit too (unsigned though). So, let's
convert intermediate argument to 64bit too.
This patch is a first in the 64-bit-blocklayer series, so we are
generally moving to int64_t for both offset and bytes parameters on all
io paths. Main motivation is realization of 64-bit write_zeroes
operation for fast zeroing large disk chunks, up to the whole disk.
We chose signed type, to be consistent with off_t (which is signed) and
with possibility for signed return type (where negative value means
error).
Patch-correctness audit by Eric Blake:
  Caller has 32-bit, this patch now causes widening which is safe:
  block/block-backend.c: blk_do_preadv() passes 'unsigned int'
  block/block-backend.c: blk_do_pwritev_part() passes 'unsigned int'
  block/throttle.c: throttle_co_pwrite_zeroes() passes 'int'
  block/throttle.c: throttle_co_pdiscard() passes 'int'
  Caller has 64-bit, this patch fixes potential bug where pre-patch
  could narrow, except it's easy enough to trace that callers are still
  capped at 2G actions:
  block/throttle.c: throttle_co_preadv() passes 'uint64_t'
  block/throttle.c: throttle_co_pwritev() passes 'uint64_t'
  Implementation in question: block/throttle-groups.c
  throttle_group_co_io_limits_intercept() takes 'unsigned int bytes'
  and uses it: argument to util/throttle.c throttle_account(uint64_t)
  All safe: it patches a latent bug, and does not introduce any 64-bit
  gotchas once throttle_co_p{read,write}v are relaxed, and assuming
  throttle_account() is not buggy.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Message-Id: <20201211183934.169161-7-vsementsov@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
		
	
			
		
			
				
	
	
		
			92 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * QEMU block throttling group infrastructure
 | |
|  *
 | |
|  * Copyright (C) Nodalink, EURL. 2014
 | |
|  * Copyright (C) Igalia, S.L. 2015
 | |
|  *
 | |
|  * Authors:
 | |
|  *   Benoît Canet <benoit.canet@nodalink.com>
 | |
|  *   Alberto Garcia <berto@igalia.com>
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License as
 | |
|  * published by the Free Software Foundation; either version 2 or
 | |
|  * (at your option) version 3 of the License.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| #ifndef THROTTLE_GROUPS_H
 | |
| #define THROTTLE_GROUPS_H
 | |
| 
 | |
| #include "qemu/throttle.h"
 | |
| #include "block/block_int.h"
 | |
| #include "qom/object.h"
 | |
| 
 | |
| /* The ThrottleGroupMember structure indicates membership in a ThrottleGroup
 | |
|  * and holds related data.
 | |
|  */
 | |
| 
 | |
| typedef struct ThrottleGroupMember {
 | |
|     AioContext   *aio_context;
 | |
|     /* throttled_reqs_lock protects the CoQueues for throttled requests.  */
 | |
|     CoMutex      throttled_reqs_lock;
 | |
|     CoQueue      throttled_reqs[2];
 | |
| 
 | |
|     /* Nonzero if the I/O limits are currently being ignored; generally
 | |
|      * it is zero.  Accessed with atomic operations.
 | |
|      */
 | |
|     unsigned int io_limits_disabled;
 | |
| 
 | |
|     /* Number of pending throttle_group_restart_queue_entry() coroutines.
 | |
|      * Accessed with atomic operations.
 | |
|      */
 | |
|     unsigned int restart_pending;
 | |
| 
 | |
|     /* The following fields are protected by the ThrottleGroup lock.
 | |
|      * See the ThrottleGroup documentation for details.
 | |
|      * throttle_state tells us if I/O limits are configured. */
 | |
|     ThrottleState *throttle_state;
 | |
|     ThrottleTimers throttle_timers;
 | |
|     unsigned       pending_reqs[2];
 | |
|     QLIST_ENTRY(ThrottleGroupMember) round_robin;
 | |
| 
 | |
| } ThrottleGroupMember;
 | |
| 
 | |
| #define TYPE_THROTTLE_GROUP "throttle-group"
 | |
| OBJECT_DECLARE_SIMPLE_TYPE(ThrottleGroup, THROTTLE_GROUP)
 | |
| 
 | |
| const char *throttle_group_get_name(ThrottleGroupMember *tgm);
 | |
| 
 | |
| ThrottleState *throttle_group_incref(const char *name);
 | |
| void throttle_group_unref(ThrottleState *ts);
 | |
| 
 | |
| void throttle_group_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
 | |
| void throttle_group_get_config(ThrottleGroupMember *tgm, ThrottleConfig *cfg);
 | |
| 
 | |
| void throttle_group_register_tgm(ThrottleGroupMember *tgm,
 | |
|                                 const char *groupname,
 | |
|                                 AioContext *ctx);
 | |
| void throttle_group_unregister_tgm(ThrottleGroupMember *tgm);
 | |
| void throttle_group_restart_tgm(ThrottleGroupMember *tgm);
 | |
| 
 | |
| void coroutine_fn throttle_group_co_io_limits_intercept(ThrottleGroupMember *tgm,
 | |
|                                                         int64_t bytes,
 | |
|                                                         bool is_write);
 | |
| void throttle_group_attach_aio_context(ThrottleGroupMember *tgm,
 | |
|                                        AioContext *new_context);
 | |
| void throttle_group_detach_aio_context(ThrottleGroupMember *tgm);
 | |
| /*
 | |
|  * throttle_group_exists() must be called under the global
 | |
|  * mutex.
 | |
|  */
 | |
| bool throttle_group_exists(const char *name);
 | |
| 
 | |
| #endif
 |