mirror: create mirror_throttle helper

The patch also places last_pause_ns from stack in mirror_run into
MirrorBlockJob structure. This helper will be useful in next patches.

Signed-off-by: Denis V. Lunev <den@openvz.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-id: 1468503209-19498-4-git-send-email-den@openvz.org
CC: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
CC: Eric Blake <eblake@redhat.com>
CC: Stefan Hajnoczi <stefanha@redhat.com>
CC: Fam Zheng <famz@redhat.com>
CC: Kevin Wolf <kwolf@redhat.com>
CC: Max Reitz <mreitz@redhat.com>
CC: Jeff Cody <jcody@redhat.com>
Signed-off-by: Jeff Cody <jcody@redhat.com>
This commit is contained in:
Denis V. Lunev 2016-07-14 16:33:24 +03:00 committed by Jeff Cody
parent 531509ba28
commit 49efb1f5b0
1 changed files with 19 additions and 12 deletions

View File

@ -58,6 +58,7 @@ typedef struct MirrorBlockJob {
QSIMPLEQ_HEAD(, MirrorBuffer) buf_free; QSIMPLEQ_HEAD(, MirrorBuffer) buf_free;
int buf_free_count; int buf_free_count;
uint64_t last_pause_ns;
unsigned long *in_flight_bitmap; unsigned long *in_flight_bitmap;
int in_flight; int in_flight;
int64_t sectors_in_flight; int64_t sectors_in_flight;
@ -514,6 +515,18 @@ static void mirror_exit(BlockJob *job, void *opaque)
bdrv_unref(src); bdrv_unref(src);
} }
static void mirror_throttle(MirrorBlockJob *s)
{
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
if (now - s->last_pause_ns > SLICE_TIME) {
s->last_pause_ns = now;
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, 0);
} else {
block_job_pause_point(&s->common);
}
}
static void coroutine_fn mirror_run(void *opaque) static void coroutine_fn mirror_run(void *opaque)
{ {
MirrorBlockJob *s = opaque; MirrorBlockJob *s = opaque;
@ -521,7 +534,6 @@ static void coroutine_fn mirror_run(void *opaque)
BlockDriverState *bs = blk_bs(s->common.blk); BlockDriverState *bs = blk_bs(s->common.blk);
BlockDriverState *target_bs = blk_bs(s->target); BlockDriverState *target_bs = blk_bs(s->target);
int64_t sector_num, end, length; int64_t sector_num, end, length;
uint64_t last_pause_ns;
BlockDriverInfo bdi; BlockDriverInfo bdi;
char backing_filename[2]; /* we only need 2 characters because we are only char backing_filename[2]; /* we only need 2 characters because we are only
checking for a NULL string */ checking for a NULL string */
@ -577,7 +589,7 @@ static void coroutine_fn mirror_run(void *opaque)
mirror_free_init(s); mirror_free_init(s);
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
if (!s->is_none_mode) { if (!s->is_none_mode) {
/* First part, loop on the sectors and initialize the dirty bitmap. */ /* First part, loop on the sectors and initialize the dirty bitmap. */
BlockDriverState *base = s->base; BlockDriverState *base = s->base;
@ -587,14 +599,8 @@ static void coroutine_fn mirror_run(void *opaque)
/* Just to make sure we are not exceeding int limit. */ /* Just to make sure we are not exceeding int limit. */
int nb_sectors = MIN(INT_MAX >> BDRV_SECTOR_BITS, int nb_sectors = MIN(INT_MAX >> BDRV_SECTOR_BITS,
end - sector_num); end - sector_num);
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
if (now - last_pause_ns > SLICE_TIME) { mirror_throttle(s);
last_pause_ns = now;
block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, 0);
} else {
block_job_pause_point(&s->common);
}
if (block_job_is_cancelled(&s->common)) { if (block_job_is_cancelled(&s->common)) {
goto immediate_exit; goto immediate_exit;
@ -617,7 +623,7 @@ static void coroutine_fn mirror_run(void *opaque)
bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi); bdrv_dirty_iter_init(s->dirty_bitmap, &s->hbi);
for (;;) { for (;;) {
uint64_t delay_ns = 0; uint64_t delay_ns = 0;
int64_t cnt; int64_t cnt, delta;
bool should_complete; bool should_complete;
if (s->ret < 0) { if (s->ret < 0) {
@ -640,7 +646,8 @@ static void coroutine_fn mirror_run(void *opaque)
* We do so every SLICE_TIME nanoseconds, or when there is an error, * We do so every SLICE_TIME nanoseconds, or when there is an error,
* or when the source is clean, whichever comes first. * or when the source is clean, whichever comes first.
*/ */
if (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - last_pause_ns < SLICE_TIME && delta = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->last_pause_ns;
if (delta < SLICE_TIME &&
s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) { s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 || if (s->in_flight == MAX_IN_FLIGHT || s->buf_free_count == 0 ||
(cnt == 0 && s->in_flight > 0)) { (cnt == 0 && s->in_flight > 0)) {
@ -710,7 +717,7 @@ static void coroutine_fn mirror_run(void *opaque)
s->common.cancelled = false; s->common.cancelled = false;
break; break;
} }
last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); s->last_pause_ns = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
} }
immediate_exit: immediate_exit: