From nobody Sun May 5 15:12:38 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; dkim=fail spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1493895473437277.597301952286; Thu, 4 May 2017 03:57:53 -0700 (PDT) Received: from localhost ([::1]:41011 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d6ESE-0007NM-S4 for importer@patchew.org; Thu, 04 May 2017 06:57:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33400) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d6EPU-0004hp-NF for qemu-devel@nongnu.org; Thu, 04 May 2017 06:55:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d6EPP-0001OW-Q1 for qemu-devel@nongnu.org; Thu, 04 May 2017 06:55:00 -0400 Received: from mail-wm0-x244.google.com ([2a00:1450:400c:c09::244]:33571) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1d6EPP-0001O8-GB; Thu, 04 May 2017 06:54:55 -0400 Received: by mail-wm0-x244.google.com with SMTP id y10so2473176wmh.0; Thu, 04 May 2017 03:54:55 -0700 (PDT) Received: from localhost.localdomain ([82.113.48.145]) by smtp.googlemail.com with ESMTPSA id 31sm2865019wrt.35.2017.05.04.03.54.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 04 May 2017 03:54:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=tkRYdTV+0gPzlcvHUd1JKiyLedlm1uJpPHfuTLSDVjs=; b=WRszMRxpqE6h5ZAi8HTHprlwqXQRmhMLINIe0msCczM8Xxi2AWhj/Ur7RwVuluQuQy mjOIerCSsXn9z1y/5Zf6Dai/BEEwLul9YmsDD2//bSaUyEusvKR9EU8T8cZElXcFCYFL OBFuqZMnFYtzVrZ9kPURXKwTrPw5eM5zr9WTrBtmDZQYv0umUibDe9YYxQZPlksTw5AF Mjx0cLDFmZLVETkc3Bx6AJoqylfMW4P6Wb4pW4j0JwNg2owgqec3df32buWKicoosc/Q hxtLXCE9sG5e45HF5zMvItMo7hzK+a8K2SnmGJA+R02MMIO8yVQPtsSunhFJr7zOSTG4 NMwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=tkRYdTV+0gPzlcvHUd1JKiyLedlm1uJpPHfuTLSDVjs=; b=t1xs4ifVeN3X/3r2NYaKudiHJsZ2AF6jV1/M+cF2qRS4G0LNJi0yhufND6jsd61iQA wQSJZ33VzRDPb1MsVLIxy0Hf4obFK9sClByNJFwod32vqAcIcLWktc5RQd/YWRZXtuaL qVdOmpg8l2zj7k4YA2d0TYB+7ZcVMXlmrI5lPRHUBfj8yeQV2NUZm+JoXeRYC3NLRrjp WY7X/R04Hj/FW0Fy9uyZOnMoraD6TylLhUfB7JX+ox2rshUpVcDcMKZ8yH5F4sDYGSxt 9MrLZfFHFNMIAmFY13dgXGsh9AB2AT90uqevjafDI2mWTMsdXOI1+X1Yl9do9K4j6rzb DuTg== X-Gm-Message-State: AODbwcAAcDoGcHvZ24umFYbYQRhXb36v3opM+rvZofIv1VBaA2w5GwVl lZIhn+M3Yx7stg== X-Received: by 10.28.61.215 with SMTP id k206mr1360129wma.133.1493895294263; Thu, 04 May 2017 03:54:54 -0700 (PDT) From: Daniel Kucera To: qemu-devel@nongnu.org Date: Thu, 4 May 2017 12:54:40 +0200 Message-Id: <20170504105444.8940-1-daniel.kucera@gmail.com> X-Mailer: git-send-email 2.9.3 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::244 Subject: [Qemu-devel] [PATCH] mirror: add sync mode incremental to drive-mirror and blockdev-mirror 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: Kevin Wolf , "open list:Block Jobs" , Daniel Kucera , Jeff Cody , Markus Armbruster , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" parameter bitmap chooses existing dirtymap instead of newly created in mirror_start_job Signed-off-by: Daniel Kucera --- block/mirror.c | 47 ++++++++++++++++++++++++++++++-------------= ---- blockdev.c | 16 +++++++++++++++- include/block/block_int.h | 4 +++- qapi/block-core.json | 12 ++++++++++-- 4 files changed, 58 insertions(+), 21 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 9f5eb69..1bfbe2e 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -49,7 +49,7 @@ typedef struct MirrorBlockJob { BlockDriverState *to_replace; /* Used to block operations on the drive-mirror-replace target */ Error *replace_blocker; - bool is_none_mode; + MirrorSyncMode sync_mode; BlockMirrorBackingMode backing_mode; BlockdevOnError on_source_error, on_target_error; bool synced; @@ -523,7 +523,9 @@ static void mirror_exit(BlockJob *job, void *opaque) bdrv_child_try_set_perm(mirror_top_bs->backing, 0, BLK_PERM_ALL, &error_abort); if (s->backing_mode =3D=3D MIRROR_SOURCE_BACKING_CHAIN) { - BlockDriverState *backing =3D s->is_none_mode ? src : s->base; + BlockDriverState *backing =3D + (s->sync_mode =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) || + (s->sync_mode =3D=3D MIRROR_SYNC_MODE_NONE) ? src : s->base; if (backing_bs(target_bs) !=3D backing) { bdrv_set_backing_hd(target_bs, backing, &local_err); if (local_err) { @@ -771,7 +773,8 @@ static void coroutine_fn mirror_run(void *opaque) mirror_free_init(s); =20 s->last_pause_ns =3D qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - if (!s->is_none_mode) { + if ((s->sync_mode !=3D MIRROR_SYNC_MODE_INCREMENTAL) && + (s->sync_mode !=3D MIRROR_SYNC_MODE_NONE)) { ret =3D mirror_dirty_init(s); if (ret < 0 || block_job_is_cancelled(&s->common)) { goto immediate_exit; @@ -1114,7 +1117,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, + MirrorSyncMode sync_mode, const char *bitmap, + BlockDriverState *base, bool auto_complete, const char *filter_node_n= ame, Error **errp) { @@ -1203,7 +1207,7 @@ static void mirror_start_job(const char *job_id, Bloc= kDriverState *bs, s->replaces =3D g_strdup(replaces); 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->sync_mode =3D sync_mode; s->backing_mode =3D backing_mode; s->base =3D base; s->granularity =3D granularity; @@ -1213,9 +1217,21 @@ static void mirror_start_job(const char *job_id, Blo= ckDriverState *bs, s->should_complete =3D true; } =20 - s->dirty_bitmap =3D bdrv_create_dirty_bitmap(bs, granularity, NULL, er= rp); - if (!s->dirty_bitmap) { - goto fail; + if (s->sync_mode =3D=3D MIRROR_SYNC_MODE_INCREMENTAL) { + if (bitmap =3D=3D NULL) { + error_setg(errp, "Mode incremental requires parameter 'bitmap'= "); + goto fail; + } + s->dirty_bitmap =3D bdrv_find_dirty_bitmap(bs, bitmap); + if (!s->dirty_bitmap) { + error_setg(errp, "Bitmap '%s' not found", bitmap); + goto fail; + } + } else { + s->dirty_bitmap =3D bdrv_create_dirty_bitmap(bs, granularity, NULL= , errp); + if (!s->dirty_bitmap) { + goto fail; + } } =20 /* Required permissions are already taken with blk_new() */ @@ -1265,24 +1281,20 @@ fail: void mirror_start(const char *job_id, BlockDriverState *bs, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, + MirrorSyncMode mode, const char *bitmap, + BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, Error **errp) { - 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, BLOCK_JOB_DEFAULT, 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, + &mirror_job_driver, mode, bitmap, base, false, filter_node_name, errp); } =20 @@ -1305,7 +1317,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, MIRROR_SYNC_MODE_FULL, + NULL, base, auto_complete, filter_node_name, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/blockdev.c b/blockdev.c index 6428206..a25e7a8 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3379,6 +3379,7 @@ static void blockdev_mirror_common(const char *job_id= , BlockDriverState *bs, enum MirrorSyncMode sync, BlockMirrorBackingMode backing_mode, bool has_speed, int64_t speed, + bool has_bitmap, const char *bitmap, bool has_granularity, uint32_t granular= ity, bool has_buf_size, int64_t buf_size, bool has_on_source_error, @@ -3435,12 +3436,22 @@ static void blockdev_mirror_common(const char *job_= id, BlockDriverState *bs, sync =3D MIRROR_SYNC_MODE_FULL; } =20 + if (sync =3D=3D MIRROR_SYNC_MODE_INCREMENTAL && !has_bitmap) { + error_setg(errp, "Mode incremental requires parameter 'bitmap'"); + return; + } + + if (has_bitmap && sync !=3D MIRROR_SYNC_MODE_INCREMENTAL) { + error_setg(errp, "Bitmap set but mode is not incremental"); + return; + } + /* pass the node name to replace to mirror start since it's loose coup= ling * and will allow to check whether the node still exist at mirror comp= letion */ mirror_start(job_id, bs, target, has_replaces ? replaces : NULL, - speed, granularity, buf_size, sync, backing_mode, + speed, granularity, buf_size, sync, bitmap, backing_mode, on_source_error, on_target_error, unmap, filter_node_name, errp); } @@ -3575,6 +3586,7 @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp) blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, targe= t_bs, arg->has_replaces, arg->replaces, arg->sync, backing_mode, arg->has_speed, arg->speed, + arg->has_bitmap, arg->bitmap, arg->has_granularity, arg->granularity, arg->has_buf_size, arg->buf_size, arg->has_on_source_error, arg->on_source_error, @@ -3593,6 +3605,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char = *job_id, bool has_replaces, const char *replaces, MirrorSyncMode sync, bool has_speed, int64_t speed, + bool has_bitmap, const char *bitmap, bool has_granularity, uint32_t granularity, bool has_buf_size, int64_t buf_size, bool has_on_source_error, @@ -3627,6 +3640,7 @@ void qmp_blockdev_mirror(bool has_job_id, const char = *job_id, blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs, has_replaces, replaces, sync, backing_mode, has_speed, speed, + has_bitmap, bitmap, has_granularity, granularity, has_buf_size, buf_size, has_on_source_error, on_source_error, diff --git a/include/block/block_int.h b/include/block/block_int.h index 4f8cd29..3c59d69 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -827,6 +827,7 @@ void commit_active_start(const char *job_id, BlockDrive= rState *bs, * @granularity: The chosen granularity for the dirty bitmap. * @buf_size: The amount of data that can be in flight at one time. * @mode: Whether to collapse all images in the chain to the target. + * @bitmap: The dirty bitmap if sync_mode is MIRROR_SYNC_MODE_INCREMENTAL. * @backing_mode: How to establish the target's backing chain after comple= tion. * @on_source_error: The action to take upon error reading from the source. * @on_target_error: The action to take upon error writing to the target. @@ -844,7 +845,8 @@ void commit_active_start(const char *job_id, BlockDrive= rState *bs, void mirror_start(const char *job_id, BlockDriverState *bs, BlockDriverState *target, const char *replaces, int64_t speed, uint32_t granularity, int64_t buf_size, - MirrorSyncMode mode, BlockMirrorBackingMode backing_mode, + MirrorSyncMode mode, const char *bitmap, + BlockMirrorBackingMode backing_mode, BlockdevOnError on_source_error, BlockdevOnError on_target_error, bool unmap, const char *filter_node_name, Error **errp); diff --git a/qapi/block-core.json b/qapi/block-core.json index 87fb747..8e3d9b2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1502,6 +1502,10 @@ # # @speed: the maximum speed, in bytes per second # +# @bitmap: the name of dirty bitmap if sync is "incremental". +# Must be present if sync is "incremental", must NOT be present +# otherwise. (Since 2.10) +# # @sync: what parts of the disk image should be copied to the destination # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). @@ -1533,7 +1537,7 @@ 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', '*format': 'str', '*node-name': 'str', '*replaces': 'str', 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', - '*speed': 'int', '*granularity': 'uint32', + '*speed': 'int', '*bitmap': 'str', '*granularity': 'uint32', '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', '*on-target-error': 'BlockdevOnError', '*unmap': 'bool' } } @@ -1652,6 +1656,10 @@ # # @speed: the maximum speed, in bytes per second # +# @bitmap: the name of dirty bitmap if sync is "incremental". +# Must be present if sync is "incremental", must NOT be present +# otherwise. (Since 2.10) +# # @sync: what parts of the disk image should be copied to the destination # (all the disk, only the sectors allocated in the topmost image, or # only new I/O). @@ -1694,7 +1702,7 @@ 'data': { '*job-id': 'str', 'device': 'str', 'target': 'str', '*replaces': 'str', 'sync': 'MirrorSyncMode', - '*speed': 'int', '*granularity': 'uint32', + '*speed': 'int', '*bitmap': 'str', '*granularity': 'uint32', '*buf-size': 'int', '*on-source-error': 'BlockdevOnError', '*on-target-error': 'BlockdevOnError', '*filter-node-name': 'str' } } --=20 2.9.3