diff options
author | Alberto Garcia <berto@igalia.com> | 2015-06-08 18:17:44 +0200 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2015-06-12 14:00:00 +0100 |
commit | 76f4afb40fa076ed23fe0ab42c7a768ddb71123f (patch) | |
tree | 38d8b57c8c56a457a060866197d03d537653c2a3 /block/io.c | |
parent | 1fee955f9cc5903b3c7f79bbd90929aefad583a6 (diff) |
throttle: Add throttle group support
The throttle group support use a cooperative round robin scheduling
algorithm.
The principles of the algorithm are simple:
- Each BDS of the group is used as a token in a circular way.
- The active BDS computes if a wait must be done and arms the right
timer.
- If a wait must be done the token timer will be armed so the token
will become the next active BDS.
Signed-off-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: f0082a86f3ac01c46170f7eafe2101a92e8fde39.1433779731.git.berto@igalia.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'block/io.c')
-rw-r--r-- | block/io.c | 75 |
1 files changed, 16 insertions, 59 deletions
diff --git a/block/io.c b/block/io.c index 61a9d1da28..bb4f78784e 100644 --- a/block/io.c +++ b/block/io.c @@ -23,9 +23,9 @@ */ #include "trace.h" -#include "sysemu/qtest.h" #include "block/blockjob.h" #include "block/block_int.h" +#include "block/throttle-groups.h" #define NOT_DONE 0x7fffffff /* used while emulated sync operation in progress */ @@ -65,7 +65,7 @@ void bdrv_set_io_limits(BlockDriverState *bs, { int i; - throttle_config(&bs->throttle_state, &bs->throttle_timers, cfg); + throttle_group_config(bs, cfg); for (i = 0; i < 2; i++) { qemu_co_enter_next(&bs->throttled_reqs[i]); @@ -95,76 +95,33 @@ static bool bdrv_start_throttled_reqs(BlockDriverState *bs) void bdrv_io_limits_disable(BlockDriverState *bs) { bs->io_limits_enabled = false; - bdrv_start_throttled_reqs(bs); - - throttle_timers_destroy(&bs->throttle_timers); -} - -static void bdrv_throttle_read_timer_cb(void *opaque) -{ - BlockDriverState *bs = opaque; - qemu_co_enter_next(&bs->throttled_reqs[0]); -} - -static void bdrv_throttle_write_timer_cb(void *opaque) -{ - BlockDriverState *bs = opaque; - qemu_co_enter_next(&bs->throttled_reqs[1]); + throttle_group_unregister_bs(bs); } /* should be called before bdrv_set_io_limits if a limit is set */ -void bdrv_io_limits_enable(BlockDriverState *bs) +void bdrv_io_limits_enable(BlockDriverState *bs, const char *group) { - int clock_type = QEMU_CLOCK_REALTIME; - - if (qtest_enabled()) { - /* For testing block IO throttling only */ - clock_type = QEMU_CLOCK_VIRTUAL; - } assert(!bs->io_limits_enabled); - throttle_init(&bs->throttle_state); - throttle_timers_init(&bs->throttle_timers, - bdrv_get_aio_context(bs), - clock_type, - bdrv_throttle_read_timer_cb, - bdrv_throttle_write_timer_cb, - bs); + throttle_group_register_bs(bs, group); bs->io_limits_enabled = true; } -/* This function makes an IO wait if needed - * - * @nb_sectors: the number of sectors of the IO - * @is_write: is the IO a write - */ -static void bdrv_io_limits_intercept(BlockDriverState *bs, - unsigned int bytes, - bool is_write) +void bdrv_io_limits_update_group(BlockDriverState *bs, const char *group) { - /* does this io must wait */ - bool must_wait = throttle_schedule_timer(&bs->throttle_state, - &bs->throttle_timers, - is_write); - - /* if must wait or any request of this type throttled queue the IO */ - if (must_wait || - !qemu_co_queue_empty(&bs->throttled_reqs[is_write])) { - qemu_co_queue_wait(&bs->throttled_reqs[is_write]); + /* this bs is not part of any group */ + if (!bs->throttle_state) { + return; } - /* the IO will be executed, do the accounting */ - throttle_account(&bs->throttle_state, is_write, bytes); - - - /* if the next request must wait -> do nothing */ - if (throttle_schedule_timer(&bs->throttle_state, &bs->throttle_timers, - is_write)) { + /* this bs is a part of the same group than the one we want */ + if (!g_strcmp0(throttle_group_get_name(bs), group)) { return; } - /* else queue next request for execution */ - qemu_co_queue_next(&bs->throttled_reqs[is_write]); + /* need to change the group this bs belong to */ + bdrv_io_limits_disable(bs); + bdrv_io_limits_enable(bs, group); } void bdrv_setup_io_funcs(BlockDriver *bdrv) @@ -971,7 +928,7 @@ static int coroutine_fn bdrv_co_do_preadv(BlockDriverState *bs, /* throttling disk I/O */ if (bs->io_limits_enabled) { - bdrv_io_limits_intercept(bs, bytes, false); + throttle_group_co_io_limits_intercept(bs, bytes, false); } /* Align read if necessary by padding qiov */ @@ -1301,7 +1258,7 @@ static int coroutine_fn bdrv_co_do_pwritev(BlockDriverState *bs, /* throttling disk I/O */ if (bs->io_limits_enabled) { - bdrv_io_limits_intercept(bs, bytes, true); + throttle_group_co_io_limits_intercept(bs, bytes, true); } /* |