Signed-off-by: Wen Congyang <we...@cn.fujitsu.com> Signed-off-by: zhanghailiang <zhang.zhanghaili...@huawei.com> Signed-off-by: Gonglei <arei.gong...@huawei.com> --- Makefile.objs | 2 +- block/backup.c | 52 ++++----------------------------------------------- blockcow.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/block/block.h | 17 +++++++++++++++++ 4 files changed, 74 insertions(+), 49 deletions(-) create mode 100644 blockcow.c
diff --git a/Makefile.objs b/Makefile.objs index 28999d3..91bba07 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -7,7 +7,7 @@ util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o qapi-event.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = async.o thread-pool.o -block-obj-y += nbd.o block.o blockjob.o +block-obj-y += nbd.o block.o blockjob.o blockcow.o block-obj-y += main-loop.o iohandler.o qemu-timer.o block-obj-$(CONFIG_POSIX) += aio-posix.o block-obj-$(CONFIG_WIN32) += aio-win32.o diff --git a/block/backup.c b/block/backup.c index 1c535b1..2816b9a 100644 --- a/block/backup.c +++ b/block/backup.c @@ -27,13 +27,6 @@ #define SLICE_TIME 100000000ULL /* ns */ -typedef struct CowRequest { - int64_t start; - int64_t end; - QLIST_ENTRY(CowRequest) list; - CoQueue wait_queue; /* coroutines blocked on this request */ -} CowRequest; - typedef struct BackupBlockJob { BlockJob common; BlockDriverState *target; @@ -44,46 +37,9 @@ typedef struct BackupBlockJob { CoRwlock flush_rwlock; uint64_t sectors_read; HBitmap *bitmap; - QLIST_HEAD(, CowRequest) inflight_reqs; + CowJob cow_job; } BackupBlockJob; -/* See if in-flight requests overlap and wait for them to complete */ -static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job, - int64_t start, - int64_t end) -{ - CowRequest *req; - bool retry; - - do { - retry = false; - QLIST_FOREACH(req, &job->inflight_reqs, list) { - if (end > req->start && start < req->end) { - qemu_co_queue_wait(&req->wait_queue); - retry = true; - break; - } - } - } while (retry); -} - -/* Keep track of an in-flight request */ -static void cow_request_begin(CowRequest *req, BackupBlockJob *job, - int64_t start, int64_t end) -{ - req->start = start; - req->end = end; - qemu_co_queue_init(&req->wait_queue); - QLIST_INSERT_HEAD(&job->inflight_reqs, req, list); -} - -/* Forget about a completed request */ -static void cow_request_end(CowRequest *req) -{ - QLIST_REMOVE(req, list); - qemu_co_queue_restart_all(&req->wait_queue); -} - static int coroutine_fn backup_do_cow(BlockDriverState *bs, int64_t sector_num, int nb_sectors, bool *error_is_read) @@ -104,8 +60,8 @@ static int coroutine_fn backup_do_cow(BlockDriverState *bs, trace_backup_do_cow_enter(job, start, sector_num, nb_sectors); - wait_for_overlapping_requests(job, start, end); - cow_request_begin(&cow_request, job, start, end); + wait_for_overlapping_requests(&job->cow_job, start, end); + cow_request_begin(&cow_request, &job->cow_job, start, end); for (; start < end; start++) { if (hbitmap_get(job->bitmap, start)) { @@ -255,7 +211,7 @@ static void coroutine_fn backup_run(void *opaque) int64_t start, end; int ret = 0; - QLIST_INIT(&job->inflight_reqs); + QLIST_INIT(&job->cow_job.inflight_reqs); qemu_co_rwlock_init(&job->flush_rwlock); start = 0; diff --git a/blockcow.c b/blockcow.c new file mode 100644 index 0000000..c070a62 --- /dev/null +++ b/blockcow.c @@ -0,0 +1,52 @@ +/* + * QEMU block WAW + * + * Copyright Fujitsu, Corp. 2015 + * Copyright (c) 2015 Intel Corporation + * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD. + * + * Authors: + * Wen Congyang (we...@cn.fujitsu.com) + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "block/block.h" + +/* See if in-flight requests overlap and wait for them to complete */ +void coroutine_fn +wait_for_overlapping_requests(CowJob *job, int64_t start, int64_t end) +{ + CowRequest *req; + bool retry; + + do { + retry = false; + QLIST_FOREACH(req, &job->inflight_reqs, list) { + if (end > req->start && start < req->end) { + qemu_co_queue_wait(&req->wait_queue); + retry = true; + break; + } + } + } while (retry); +} + +/* Keep track of an in-flight request */ +void cow_request_begin(CowRequest *req, CowJob *job, + int64_t start, int64_t end) +{ + req->start = start; + req->end = end; + qemu_co_queue_init(&req->wait_queue); + QLIST_INSERT_HEAD(&job->inflight_reqs, req, list); +} + +/* Forget about a completed request */ +void cow_request_end(CowRequest *req) +{ + QLIST_REMOVE(req, list); + qemu_co_queue_restart_all(&req->wait_queue); +} diff --git a/include/block/block.h b/include/block/block.h index 632b9fc..0a55373 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -567,4 +567,21 @@ int bdrv_start_replication(BlockDriverState *bs, int mode); int bdrv_do_checkpoint(BlockDriverState *bs); int bdrv_stop_replication(BlockDriverState *bs); +typedef struct CowRequest { + int64_t start; + int64_t end; + QLIST_ENTRY(CowRequest) list; + CoQueue wait_queue; /* coroutines blocked on this request */ +} CowRequest; + +typedef struct CowJob { + QLIST_HEAD(, CowRequest) inflight_reqs; +} CowJob; + +void coroutine_fn +wait_for_overlapping_requests(CowJob *job, int64_t start, int64_t end); +void cow_request_begin(CowRequest *req, CowJob *job, + int64_t start, int64_t end); +void cow_request_end(CowRequest *req); + #endif -- 2.1.0