From nobody Sun May 5 17:28:23 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=163.com Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548908370567568.081479021731; Wed, 30 Jan 2019 20:19:30 -0800 (PST) Received: from localhost ([127.0.0.1]:48521 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gp3ow-0004Wl-Qg for importer@patchew.org; Wed, 30 Jan 2019 23:19:22 -0500 Received: from eggs.gnu.org ([209.51.188.92]:36769) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gp3nW-0003oC-Jz for qemu-devel@nongnu.org; Wed, 30 Jan 2019 23:17:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gp3nV-0005R5-3k for qemu-devel@nongnu.org; Wed, 30 Jan 2019 23:17:54 -0500 Received: from m50-133.163.com ([123.125.50.133]:37089) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gp3nN-0005F4-Mt; Wed, 30 Jan 2019 23:17:47 -0500 Received: from localhost.localdomain (unknown [111.202.166.3]) by smtp3 (Coremail) with SMTP id DdGowAA3RDA5c1JcswwTAA--.182S4; Thu, 31 Jan 2019 12:02:16 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-Id; bh=PXf40nJYT54ZxtwsEe tOJ+2p3a4KN/qpFQ75LYxmEaI=; b=f8KntfU5MsFBazT3mbTg4m0/OSnBj6o397 y6rMLFof0XgkrBrluAhf4i5ds/mQdmK5A5I/CxnnR2qnPAxNNLFccedDOJ6cfK/3 ARY+rP5lZvGhbduU2MF/8AeA6Q6771FuBbnWHQ5qwN1jgk38ihffsWHV8dl+2jBa M+9KQcvVc= From: mahaocong To: qemu-block@nongnu.org Date: Thu, 31 Jan 2019 12:01:54 +0800 Message-Id: <20190131040154.3770-2-mahaocong_work@163.com> X-Mailer: git-send-email 2.14.3 (Apple Git-98) In-Reply-To: <20190131040154.3770-1-mahaocong_work@163.com> References: <20190131040154.3770-1-mahaocong_work@163.com> X-CM-TRANSID: DdGowAA3RDA5c1JcswwTAA--.182S4 X-Coremail-Antispam: 1Uf129KBjvJXoW3Jr4DKrykurW8KF1fCw1kGrg_yoWDGw43pF W3G3s3Ar15Xr93XFn7Jry7JF1aqw4kJayUtryfXa4xGFsxZr9rAr4vkF4Y9a4UJwsxZr4q qF4vq34kCa17ZFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jSuWLUUUUU= X-Originating-IP: [111.202.166.3] X-CM-SenderInfo: 5pdkt05frqwspzruyqqrwthudrp/1tbiRAhNClSIZih5XAAAs8 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 123.125.50.133 Subject: [Qemu-devel] [PATCH v3 1/1] drive-mirror: add incremental mode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, jcody@redhat.com, mahaocong , qemu-devel@nongnu.org, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: mahaocong Signed-off-by: mahaocong --- block/mirror.c | 46 ++++++++++++++++++++++++++++++++++---------= --- blockdev.c | 37 +++++++++++++++++++++++++++++++++++-- include/block/block_int.h | 3 ++- qapi/block-core.json | 7 ++++++- 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index ab59ad77e8..c59aefe9f0 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -50,6 +50,7 @@ typedef struct MirrorBlockJob { /* Used to block operations on the drive-mirror-replace target */ Error *replace_blocker; bool is_none_mode; + BdrvDirtyBitmap *src_bitmap; BlockMirrorBackingMode backing_mode; MirrorCopyMode copy_mode; BlockdevOnError on_source_error, on_target_error; @@ -814,6 +815,15 @@ static int coroutine_fn mirror_dirty_init(MirrorBlockJ= ob *s) return 0; } =20 +/* + * init dirty bitmap by using user bitmap. usr->hbitmap will be copy to + * mirror bitmap->hbitmap instead of reuse it. + */ +static void coroutine_fn mirror_dirty_init_incremental(MirrorBlockJob *s, = Error **errp) +{ + bdrv_merge_dirty_bitmap(s->dirty_bitmap, s->src_bitmap, NULL, errp); +} + /* Called when going out of the streaming phase to flush the bulk of the * data to the medium, or just before completing. */ @@ -839,6 +849,7 @@ static int coroutine_fn mirror_run(Job *job, Error **er= rp) char backing_filename[2]; /* we only need 2 characters because we are = only checking for a NULL string */ int ret =3D 0; + Error *local_err =3D NULL; =20 if (job_is_cancelled(&s->common.job)) { goto immediate_exit; @@ -913,9 +924,19 @@ static int coroutine_fn mirror_run(Job *job, Error **e= rrp) =20 s->last_pause_ns =3D qemu_clock_get_ns(QEMU_CLOCK_REALTIME); if (!s->is_none_mode) { - ret =3D mirror_dirty_init(s); - if (ret < 0 || job_is_cancelled(&s->common.job)) { - goto immediate_exit; + /* incremental mode */ + if (s->src_bitmap) { + mirror_dirty_init_incremental(s, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -1; + goto immediate_exit; + } + } else { + ret =3D mirror_dirty_init(s); + if (ret < 0 || job_is_cancelled(&s->common.job)) { + goto immediate_exit; + } } } =20 @@ -1484,7 +1505,8 @@ static void mirror_start_job(const char *job_id, Bloc= kDriverState *bs, BlockCompletionFunc *cb, void *opaque, const BlockJobDriver *driver, - bool is_none_mode, BlockDriverState *base, + bool is_none_mode, BdrvDirtyBitmap *src_bitma= p, + BlockDriverState *base, bool auto_complete, const char *filter_node_n= ame, bool is_mirror, MirrorCopyMode copy_mode, Error **errp) @@ -1598,6 +1620,7 @@ static void mirror_start_job(const char *job_id, Bloc= kDriverState *bs, s->on_source_error =3D on_source_error; s->on_target_error =3D on_target_error; s->is_none_mode =3D is_none_mode; + s->src_bitmap =3D src_bitmap; s->backing_mode =3D backing_mode; s->copy_mode =3D copy_mode; s->base =3D base; @@ -1664,7 +1687,8 @@ void mirror_start(const char *job_id, BlockDriverStat= e *bs, BlockDriverState *target, const char *replaces, int creation_flags, int64_t speed, uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, + MirrorSyncMode mode, BdrvDirtyBitmap *src_bitmap, + BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, @@ -1673,17 +1697,14 @@ void mirror_start(const char *job_id, BlockDriverSt= ate *bs, bool is_none_mode; BlockDriverState *base; =20 - if (mode =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) { - error_setg(errp, "Sync mode 'incremental' not supported"); - return; - } is_none_mode =3D mode =3D=3D MIRROR_SYNC_MODE_NONE; base =3D mode =3D=3D MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL; mirror_start_job(job_id, bs, creation_flags, target, replaces, speed, granularity, buf_size, backing_mode, on_source_error, on_target_error, unmap, NULL, NULL, - &mirror_job_driver, is_none_mode, base, false, - filter_node_name, true, copy_mode, errp); + &mirror_job_driver, is_none_mode, + src_bitmap, base, false, filter_node_name, true, + copy_mode, errp); } =20 void commit_active_start(const char *job_id, BlockDriverState *bs, @@ -1707,7 +1728,8 @@ void commit_active_start(const char *job_id, BlockDri= verState *bs, mirror_start_job(job_id, bs, creation_flags, base, NULL, speed, 0, 0, MIRROR_LEAVE_BACKING_CHAIN, on_error, on_error, true, cb, opaque, - &commit_active_job_driver, false, base, auto_complete, + &commit_active_job_driver, false, + NULL, base, auto_complete, filter_node_name, false, MIRROR_COPY_MODE_BACKGROUND, &local_err); if (local_err) { diff --git a/blockdev.c b/blockdev.c index a6f71f9d83..969362d36a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3661,6 +3661,8 @@ static void blockdev_mirror_common(const char *job_id= , BlockDriverState *bs, BlockDriverState *target, bool has_replaces, const char *replaces, enum MirrorSyncMode sync, + bool has_bitmap, + const char *bitmap_name, BlockMirrorBackingMode backing_mode, bool has_speed, int64_t speed, bool has_granularity, uint32_t granular= ity, @@ -3678,6 +3680,7 @@ static void blockdev_mirror_common(const char *job_id= , BlockDriverState *bs, Error **errp) { int job_flags =3D JOB_DEFAULT; + BdrvDirtyBitmap *src_bitmap =3D NULL; =20 if (!has_speed) { speed =3D 0; @@ -3700,6 +3703,24 @@ static void blockdev_mirror_common(const char *job_i= d, BlockDriverState *bs, if (!has_filter_node_name) { filter_node_name =3D NULL; } + if (!has_bitmap) { + bitmap_name =3D NULL; + } + /* + * In incremental mode, we should create null name bitmap by + * using user bitmap's granularity. + */ + if (sync =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) { + assert(bitmap_name); + src_bitmap =3D bdrv_find_dirty_bitmap(bs, bitmap_name); + if (!src_bitmap) { + error_setg(errp, "Error: can't find dirty bitmap " + "before start incremental drive-mirror"); + return; + } + granularity =3D bdrv_dirty_bitmap_granularity(src_bitmap); + } + if (!has_copy_mode) { copy_mode =3D MIRROR_COPY_MODE_BACKGROUND; } @@ -3737,7 +3758,7 @@ static void blockdev_mirror_common(const char *job_id= , BlockDriverState *bs, */ mirror_start(job_id, bs, target, has_replaces ? replaces : NULL, job_flags, - speed, granularity, buf_size, sync, backing_mode, + speed, granularity, buf_size, sync, src_bitmap, backing_m= ode, on_source_error, on_target_error, unmap, filter_node_name, copy_mode, errp); } @@ -3784,6 +3805,16 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) if (arg->sync =3D=3D MIRROR_SYNC_MODE_NONE) { source =3D bs; } + if ((arg->sync =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) && + (!arg->has_bitmap)) { + error_setg(errp, "incremental mode must specify the bitmap name"); + goto out; + } + if ((arg->sync =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) && + (arg->has_granularity)) { + error_setg(errp, "incremental mode can not set bitmap granularity"= ); + goto out; + } =20 size =3D bdrv_getlength(bs); if (size < 0) { @@ -3878,6 +3909,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) =20 blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, targe= t_bs, arg->has_replaces, arg->replaces, arg->sync, + arg->has_bitmap, arg->bitmap, backing_mode, arg->has_speed, arg->speed, arg->has_granularity, arg->granularity, arg->has_buf_size, arg->buf_size, @@ -3935,7 +3967,8 @@ void qmp_blockdev_mirror(bool has_job_id, const char = *job_id, bdrv_set_aio_context(target_bs, aio_context); =20 blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, - has_replaces, replaces, sync, backing_mode, + has_replaces, replaces, sync, false, NULL, + backing_mode, has_speed, speed, has_granularity, granularity, has_buf_size, buf_size, diff --git a/include/block/block_int.h b/include/block/block_int.h index f605622216..57a441f992 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -1054,7 +1054,8 @@ void mirror_start(const char *job_id, BlockDriverStat= e *bs, BlockDriverState *target, const char *replaces, int creation_flags, int64_t speed, uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, + MirrorSyncMode mode, BdrvDirtyBitmap *src_bitmap, + BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, diff --git a/qapi/block-core.json b/qapi/block-core.json index 762000f31f..058bafca65 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1727,6 +1727,11 @@ # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). # +# @bitmap: the name of user-created-bitmap which is used on incremental mo= de +# drive-mirror. If user select incremental mode, bitmap should no= t be +# null, and can not set granularity, because the mirror bitmap sh= ould +# have the same granularity with user-created-bitmap. +# # @granularity: granularity of the dirty bitmap, default is 64K # if the image format doesn't have clusters, 4K if the clust= ers # are smaller than that, else the cluster size. Must be a @@ -1768,7 +1773,7 @@ { 'struct': 'DriveMirror', 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', '*format': 'str', '*node-name': 'str', '*replaces': 'str', - 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', + 'sync': 'MirrorSyncMode', '*bitmap': 'str', '*mode': 'NewImage= Mode', '*speed': 'int', '*granularity': 'uint32', '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', '*on-target-error': 'BlockdevOnError', --=20 2.14.1