From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 35/39] block/mirror: Fix target backing BDS
Date: Thu, 16 Jun 2016 16:08:24 +0200 [thread overview]
Message-ID: <1466086108-24868-36-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1466086108-24868-1-git-send-email-kwolf@redhat.com>
From: Max Reitz <mreitz@redhat.com>
Currently, we are trying to move the backing BDS from the source to the
target in bdrv_replace_in_backing_chain() which is called from
mirror_exit(). However, mirror_complete() already tries to open the
target's backing chain with a call to bdrv_open_backing_file().
First, we should only set the target's backing BDS once. Second, the
mirroring block job has a better idea of what to set it to than the
generic code in bdrv_replace_in_backing_chain() (in fact, the latter's
conditions on when to move the backing BDS from source to target are not
really correct).
Therefore, remove that code from bdrv_replace_in_backing_chain() and
leave it to mirror_complete().
Depending on what kind of mirroring is performed, we furthermore want to
use different strategies to open the target's backing chain:
- If blockdev-mirror is used, we can assume the user made sure that the
target already has the correct backing chain. In particular, we should
not try to open a backing file if the target does not have any yet.
- If drive-mirror with mode=absolute-paths is used, we can and should
reuse the already existing chain of nodes that the source BDS is in.
In case of sync=full, no backing BDS is required; with sync=top, we
just link the source's backing BDS to the target, and with sync=none,
we use the source BDS as the target's backing BDS.
We should not try to open these backing files anew because this would
lead to two BDSs existing per physical file in the backing chain, and
we would like to avoid such concurrent access.
- If drive-mirror with mode=existing is used, we have to use the
information provided in the physical image file which means opening
the target's backing chain completely anew, just as it has been done
already.
If the target's backing chain shares images with the source, this may
lead to multiple BDSs per physical image file. But since we cannot
reliably ascertain this case, there is nothing we can do about it.
Signed-off-by: Max Reitz <mreitz@redhat.com>
Message-id: 20160610185750.30956-3-mreitz@redhat.com
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
block.c | 8 --------
block/mirror.c | 39 ++++++++++++++++++++++++++++-----------
blockdev.c | 15 ++++++++++++---
include/block/block_int.h | 18 +++++++++++++++++-
4 files changed, 57 insertions(+), 23 deletions(-)
diff --git a/block.c b/block.c
index d090324..b331eb9 100644
--- a/block.c
+++ b/block.c
@@ -2291,14 +2291,6 @@ void bdrv_replace_in_backing_chain(BlockDriverState *old, BlockDriverState *new)
change_parent_backing_link(old, new);
- /* Change backing files if a previously independent node is added to the
- * chain. For active commit, we replace top by its own (indirect) backing
- * file and don't do anything here so we don't build a loop. */
- if (new->backing == NULL && !bdrv_chain_contains(backing_bs(old), new)) {
- bdrv_set_backing_hd(new, backing_bs(old));
- bdrv_set_backing_hd(old, NULL);
- }
-
bdrv_unref(old);
}
diff --git a/block/mirror.c b/block/mirror.c
index 41848b2..075384a 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -44,6 +44,7 @@ typedef struct MirrorBlockJob {
/* Used to block operations on the drive-mirror-replace target */
Error *replace_blocker;
bool is_none_mode;
+ BlockMirrorBackingMode backing_mode;
BlockdevOnError on_source_error, on_target_error;
bool synced;
bool should_complete;
@@ -742,20 +743,26 @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
static void mirror_complete(BlockJob *job, Error **errp)
{
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
- Error *local_err = NULL;
- int ret;
+ BlockDriverState *src, *target;
+
+ src = blk_bs(job->blk);
+ target = blk_bs(s->target);
- ret = bdrv_open_backing_file(blk_bs(s->target), NULL, "backing",
- &local_err);
- if (ret < 0) {
- error_propagate(errp, local_err);
- return;
- }
if (!s->synced) {
error_setg(errp, QERR_BLOCK_JOB_NOT_READY, job->id);
return;
}
+ if (s->backing_mode == MIRROR_OPEN_BACKING_CHAIN) {
+ int ret;
+
+ assert(!target->backing);
+ ret = bdrv_open_backing_file(target, NULL, "backing", errp);
+ if (ret < 0) {
+ return;
+ }
+ }
+
/* check the target bs is not blocked and block all operations on it */
if (s->replaces) {
AioContext *replace_aio_context;
@@ -777,6 +784,13 @@ static void mirror_complete(BlockJob *job, Error **errp)
aio_context_release(replace_aio_context);
}
+ if (s->backing_mode == MIRROR_SOURCE_BACKING_CHAIN) {
+ BlockDriverState *backing = s->is_none_mode ? src : s->base;
+ if (backing_bs(target) != backing) {
+ bdrv_set_backing_hd(target, backing);
+ }
+ }
+
s->should_complete = true;
block_job_enter(&s->common);
}
@@ -799,6 +813,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
const char *replaces,
int64_t speed, uint32_t granularity,
int64_t buf_size,
+ BlockMirrorBackingMode backing_mode,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
@@ -836,6 +851,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
s->on_source_error = on_source_error;
s->on_target_error = on_target_error;
s->is_none_mode = is_none_mode;
+ s->backing_mode = backing_mode;
s->base = base;
s->granularity = granularity;
s->buf_size = ROUND_UP(buf_size, granularity);
@@ -859,7 +875,8 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
void mirror_start(BlockDriverState *bs, BlockDriverState *target,
const char *replaces,
int64_t speed, uint32_t granularity, int64_t buf_size,
- MirrorSyncMode mode, BlockdevOnError on_source_error,
+ MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
+ BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb,
@@ -875,7 +892,7 @@ void mirror_start(BlockDriverState *bs, BlockDriverState *target,
is_none_mode = mode == MIRROR_SYNC_MODE_NONE;
base = mode == MIRROR_SYNC_MODE_TOP ? backing_bs(bs) : NULL;
mirror_start_job(bs, target, replaces,
- speed, granularity, buf_size,
+ speed, granularity, buf_size, backing_mode,
on_source_error, on_target_error, unmap, cb, opaque, errp,
&mirror_job_driver, is_none_mode, base);
}
@@ -922,7 +939,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
}
}
- mirror_start_job(bs, base, NULL, speed, 0, 0,
+ mirror_start_job(bs, base, NULL, speed, 0, 0, MIRROR_LEAVE_BACKING_CHAIN,
on_error, on_error, false, cb, opaque, &local_err,
&commit_active_job_driver, false, base);
if (local_err) {
diff --git a/blockdev.c b/blockdev.c
index 1d498c7..c9a0068 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3426,6 +3426,7 @@ static void blockdev_mirror_common(BlockDriverState *bs,
BlockDriverState *target,
bool has_replaces, const char *replaces,
enum MirrorSyncMode sync,
+ BlockMirrorBackingMode backing_mode,
bool has_speed, int64_t speed,
bool has_granularity, uint32_t granularity,
bool has_buf_size, int64_t buf_size,
@@ -3483,7 +3484,7 @@ static void blockdev_mirror_common(BlockDriverState *bs,
*/
mirror_start(bs, target,
has_replaces ? replaces : NULL,
- speed, granularity, buf_size, sync,
+ speed, granularity, buf_size, sync, backing_mode,
on_source_error, on_target_error, unmap,
block_job_cb, bs, errp);
}
@@ -3506,6 +3507,7 @@ void qmp_drive_mirror(const char *device, const char *target,
BlockBackend *blk;
BlockDriverState *source, *target_bs;
AioContext *aio_context;
+ BlockMirrorBackingMode backing_mode;
Error *local_err = NULL;
QDict *options = NULL;
int flags;
@@ -3579,6 +3581,12 @@ void qmp_drive_mirror(const char *device, const char *target,
}
}
+ if (mode == NEW_IMAGE_MODE_ABSOLUTE_PATHS) {
+ backing_mode = MIRROR_SOURCE_BACKING_CHAIN;
+ } else {
+ backing_mode = MIRROR_OPEN_BACKING_CHAIN;
+ }
+
if ((sync == MIRROR_SYNC_MODE_FULL || !source)
&& mode != NEW_IMAGE_MODE_EXISTING)
{
@@ -3627,7 +3635,7 @@ void qmp_drive_mirror(const char *device, const char *target,
bdrv_set_aio_context(target_bs, aio_context);
blockdev_mirror_common(bs, target_bs,
- has_replaces, replaces, sync,
+ has_replaces, replaces, sync, backing_mode,
has_speed, speed,
has_granularity, granularity,
has_buf_size, buf_size,
@@ -3659,6 +3667,7 @@ void qmp_blockdev_mirror(const char *device, const char *target,
BlockBackend *blk;
BlockDriverState *target_bs;
AioContext *aio_context;
+ BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
Error *local_err = NULL;
blk = blk_by_name(device);
@@ -3684,7 +3693,7 @@ void qmp_blockdev_mirror(const char *device, const char *target,
bdrv_set_aio_context(target_bs, aio_context);
blockdev_mirror_common(bs, target_bs,
- has_replaces, replaces, sync,
+ has_replaces, replaces, sync, 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 16c43e2..688c6be 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -509,6 +509,20 @@ struct BlockBackendRootState {
BlockdevDetectZeroesOptions detect_zeroes;
};
+typedef enum BlockMirrorBackingMode {
+ /* Reuse the existing backing chain from the source for the target.
+ * - sync=full: Set backing BDS to NULL.
+ * - sync=top: Use source's backing BDS.
+ * - sync=none: Use source as the backing BDS. */
+ MIRROR_SOURCE_BACKING_CHAIN,
+
+ /* Open the target's backing chain completely anew */
+ MIRROR_OPEN_BACKING_CHAIN,
+
+ /* Do not change the target's backing BDS after job completion */
+ MIRROR_LEAVE_BACKING_CHAIN,
+} BlockMirrorBackingMode;
+
static inline BlockDriverState *backing_bs(BlockDriverState *bs)
{
return bs->backing ? bs->backing->bs : NULL;
@@ -671,6 +685,7 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
* @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.
+ * @backing_mode: How to establish the target's backing chain after completion.
* @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.
* @unmap: Whether to unmap target where source sectors only contain zeroes.
@@ -686,7 +701,8 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
void mirror_start(BlockDriverState *bs, BlockDriverState *target,
const char *replaces,
int64_t speed, uint32_t granularity, int64_t buf_size,
- MirrorSyncMode mode, BlockdevOnError on_source_error,
+ MirrorSyncMode mode, BlockMirrorBackingMode backing_mode,
+ BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
bool unmap,
BlockCompletionFunc *cb,
--
1.8.3.1
next prev parent reply other threads:[~2016-06-16 14:09 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-16 14:07 [Qemu-devel] [PULL 00/39] Block layer patches Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 01/39] qcow2: Work with bytes in qcow2_get_cluster_offset() Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 02/39] qcow2: Implement .bdrv_co_preadv() Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 03/39] qcow2: Make copy_sectors() byte based Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 04/39] qcow2: Use bytes instead of sectors for QCowL2Meta Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 05/39] qcow2: Implement .bdrv_co_pwritev() Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 06/39] blockdev: clarify error on attempt to open locked tray Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 07/39] hmp: acquire aio_context in hmp_qemu_io Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 08/39] m25p80: fix test on blk_pread() return value Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 09/39] qemu-img bench: Fix uninitialised writethrough mode Kevin Wolf
2016-06-16 14:07 ` [Qemu-devel] [PULL 10/39] block: Avoid bogus flags during mirroring Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 11/39] block: Assert that flags are in range Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 12/39] block: drop support for using qcow[2] encryption with system emulators Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 13/39] block: Byte-based bdrv_co_do_copy_on_readv() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 14/39] block: Prepare bdrv_aligned_preadv() for byte-aligned requests Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 15/39] block: Prepare bdrv_aligned_pwritev() " Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 16/39] raw-posix: Switch to bdrv_co_* interfaces Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 17/39] raw-posix: Implement .bdrv_co_preadv/pwritev Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 18/39] block: Don't enforce 512 byte minimum alignment Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 19/39] linux-aio: Cancel BH if not needed Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 20/39] doc: Fix mailing list address in tests/qemu-iotests/README Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 21/39] block: Introduce bdrv_preadv() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 22/39] block: Make .bdrv_load_vmstate() vectored Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 23/39] block: Allow .bdrv_load/save_vmstate() to return 0/-errno Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 24/39] block: Make bdrv_load/save_vmstate coroutine_fns Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 25/39] qcow2: Let vmstate call qcow2_co_preadv/pwrite directly Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 26/39] block: Remove bs->zero_beyond_eof Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 27/39] block: Fix snapshot=on with aio=native Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 28/39] block: use the block job list in bdrv_drain_all() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 29/39] block: use the block job list in qmp_query_block_jobs() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 30/39] block: Prevent sleeping jobs from resuming if they have been paused Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 31/39] block: Create the commit block job before reopening any image Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 32/39] iotests: 095: Clean up QEMU before showing image info Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 33/39] rbd:change error_setg() to error_setg_errno() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 34/39] block: Allow replacement of a BDS by its overlay Kevin Wolf
2016-06-16 14:08 ` Kevin Wolf [this message]
2016-06-16 14:08 ` [Qemu-devel] [PULL 36/39] block/null: Implement bdrv_refresh_filename() Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 37/39] iotests: Add test for post-mirror backing chains Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 38/39] iotests: Add test for oVirt-like storage migration Kevin Wolf
2016-06-16 14:08 ` [Qemu-devel] [PULL 39/39] hbitmap: add 'pos < size' asserts Kevin Wolf
2016-06-16 15:06 ` [Qemu-devel] [PULL 00/39] Block layer patches Peter Maydell
2016-06-16 17:04 ` Eric Blake
2016-06-16 17:08 ` Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1466086108-24868-36-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).