From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, mreitz@redhat.com, berto@igalia.com,
jcody@redhat.com, jsnow@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH v2 08/14] mirror: Use BlockBackend for I/O
Date: Tue, 24 May 2016 15:47:28 +0200 [thread overview]
Message-ID: <1464097654-12977-9-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1464097654-12977-1-git-send-email-kwolf@redhat.com>
This changes the mirror block job to use the job's BlockBackend for
performing its I/O. job->bs isn't used by the mirroring code any more
afterwards.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/mirror.c | 74 ++++++++++++++++++++++++++++++++--------------------------
blockdev.c | 4 +---
2 files changed, 42 insertions(+), 36 deletions(-)
diff --git a/block/mirror.c b/block/mirror.c
index 23aa10e..d596660 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -35,7 +35,7 @@ typedef struct MirrorBuffer {
typedef struct MirrorBlockJob {
BlockJob common;
RateLimit limit;
- BlockDriverState *target;
+ BlockBackend *target;
BlockDriverState *base;
/* The name of the graph node to replace */
char *replaces;
@@ -156,7 +156,8 @@ static void mirror_read_complete(void *opaque, int ret)
mirror_iteration_done(op, ret);
return;
}
- bdrv_aio_writev(s->target, op->sector_num, &op->qiov, op->nb_sectors,
+ blk_aio_pwritev(s->target, op->sector_num * BDRV_SECTOR_SIZE, &op->qiov,
+ op->nb_sectors * BDRV_SECTOR_SIZE,
mirror_write_complete, op);
}
@@ -185,7 +186,7 @@ static int mirror_cow_align(MirrorBlockJob *s,
need_cow |= !test_bit((*sector_num + *nb_sectors - 1) / chunk_sectors,
s->cow_bitmap);
if (need_cow) {
- bdrv_round_to_clusters(s->target, *sector_num, *nb_sectors,
+ bdrv_round_to_clusters(blk_bs(s->target), *sector_num, *nb_sectors,
&align_sector_num, &align_nb_sectors);
}
@@ -223,7 +224,7 @@ static inline void mirror_wait_for_io(MirrorBlockJob *s)
static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
int nb_sectors)
{
- BlockDriverState *source = s->common.bs;
+ BlockBackend *source = s->common.blk;
int sectors_per_chunk, nb_chunks;
int ret = nb_sectors;
MirrorOp *op;
@@ -273,7 +274,8 @@ static int mirror_do_read(MirrorBlockJob *s, int64_t sector_num,
s->sectors_in_flight += nb_sectors;
trace_mirror_one_iteration(s, sector_num, nb_sectors);
- bdrv_aio_readv(source, sector_num, &op->qiov, nb_sectors,
+ blk_aio_preadv(source, sector_num * BDRV_SECTOR_SIZE, &op->qiov,
+ nb_sectors * BDRV_SECTOR_SIZE,
mirror_read_complete, op);
return ret;
}
@@ -295,18 +297,19 @@ static void mirror_do_zero_or_discard(MirrorBlockJob *s,
s->in_flight++;
s->sectors_in_flight += nb_sectors;
if (is_discard) {
- bdrv_aio_discard(s->target, sector_num, op->nb_sectors,
- mirror_write_complete, op);
+ blk_aio_discard(s->target, sector_num, op->nb_sectors,
+ mirror_write_complete, op);
} else {
- bdrv_aio_write_zeroes(s->target, sector_num, op->nb_sectors,
- s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
- mirror_write_complete, op);
+ blk_aio_write_zeroes(s->target, sector_num * BDRV_SECTOR_SIZE,
+ op->nb_sectors * BDRV_SECTOR_SIZE,
+ s->unmap ? BDRV_REQ_MAY_UNMAP : 0,
+ mirror_write_complete, op);
}
}
static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
{
- BlockDriverState *source = s->common.bs;
+ BlockDriverState *source = blk_bs(s->common.blk);
int64_t sector_num, first_chunk;
uint64_t delay_ns = 0;
/* At least the first dirty chunk is mirrored in one iteration. */
@@ -383,7 +386,7 @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
int64_t target_sector_num;
int target_nb_sectors;
- bdrv_round_to_clusters(s->target, sector_num, io_sectors,
+ bdrv_round_to_clusters(blk_bs(s->target), sector_num, io_sectors,
&target_sector_num, &target_nb_sectors);
if (target_sector_num == sector_num &&
target_nb_sectors == io_sectors) {
@@ -448,7 +451,8 @@ static void mirror_exit(BlockJob *job, void *opaque)
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
MirrorExitData *data = opaque;
AioContext *replace_aio_context = NULL;
- BlockDriverState *src = s->common.bs;
+ BlockDriverState *src = blk_bs(s->common.blk);
+ BlockDriverState *target_bs = blk_bs(s->target);
/* Make sure that the source BDS doesn't go away before we called
* block_job_completed(). */
@@ -460,20 +464,20 @@ static void mirror_exit(BlockJob *job, void *opaque)
}
if (s->should_complete && data->ret == 0) {
- BlockDriverState *to_replace = s->common.bs;
+ BlockDriverState *to_replace = src;
if (s->to_replace) {
to_replace = s->to_replace;
}
- if (bdrv_get_flags(s->target) != bdrv_get_flags(to_replace)) {
- bdrv_reopen(s->target, bdrv_get_flags(to_replace), NULL);
+ if (bdrv_get_flags(target_bs) != bdrv_get_flags(to_replace)) {
+ bdrv_reopen(target_bs, bdrv_get_flags(to_replace), NULL);
}
/* The mirror job has no requests in flight any more, but we need to
* drain potential other users of the BDS before changing the graph. */
- bdrv_drained_begin(s->target);
- bdrv_replace_in_backing_chain(to_replace, s->target);
- bdrv_drained_end(s->target);
+ bdrv_drained_begin(target_bs);
+ bdrv_replace_in_backing_chain(to_replace, target_bs);
+ bdrv_drained_end(target_bs);
/* We just changed the BDS the job BB refers to */
blk_remove_bs(job->blk);
@@ -488,8 +492,8 @@ static void mirror_exit(BlockJob *job, void *opaque)
aio_context_release(replace_aio_context);
}
g_free(s->replaces);
- bdrv_op_unblock_all(s->target, s->common.blocker);
- bdrv_unref(s->target);
+ bdrv_op_unblock_all(target_bs, s->common.blocker);
+ blk_unref(s->target);
block_job_completed(&s->common, data->ret);
g_free(data);
bdrv_drained_end(src);
@@ -503,7 +507,8 @@ static void coroutine_fn mirror_run(void *opaque)
{
MirrorBlockJob *s = opaque;
MirrorExitData *data;
- BlockDriverState *bs = s->common.bs;
+ BlockDriverState *bs = blk_bs(s->common.blk);
+ BlockDriverState *target_bs = blk_bs(s->target);
int64_t sector_num, end, length;
uint64_t last_pause_ns;
BlockDriverInfo bdi;
@@ -539,18 +544,18 @@ static void coroutine_fn mirror_run(void *opaque)
* the destination do COW. Instead, we copy sectors around the
* dirty data if needed. We need a bitmap to do that.
*/
- bdrv_get_backing_filename(s->target, backing_filename,
+ bdrv_get_backing_filename(target_bs, backing_filename,
sizeof(backing_filename));
- if (!bdrv_get_info(s->target, &bdi) && bdi.cluster_size) {
+ if (!bdrv_get_info(target_bs, &bdi) && bdi.cluster_size) {
target_cluster_size = bdi.cluster_size;
}
- if (backing_filename[0] && !s->target->backing
+ if (backing_filename[0] && !target_bs->backing
&& s->granularity < target_cluster_size) {
s->buf_size = MAX(s->buf_size, target_cluster_size);
s->cow_bitmap = bitmap_new(length);
}
s->target_cluster_sectors = target_cluster_size >> BDRV_SECTOR_BITS;
- s->max_iov = MIN(s->common.bs->bl.max_iov, s->target->bl.max_iov);
+ s->max_iov = MIN(bs->bl.max_iov, target_bs->bl.max_iov);
end = s->bdev_length / BDRV_SECTOR_SIZE;
s->buf = qemu_try_blockalign(bs, s->buf_size);
@@ -565,7 +570,7 @@ static void coroutine_fn mirror_run(void *opaque)
if (!s->is_none_mode) {
/* First part, loop on the sectors and initialize the dirty bitmap. */
BlockDriverState *base = s->base;
- bool mark_all_dirty = s->base == NULL && !bdrv_has_zero_init(s->target);
+ bool mark_all_dirty = s->base == NULL && !bdrv_has_zero_init(target_bs);
for (sector_num = 0; sector_num < end; ) {
/* Just to make sure we are not exceeding int limit. */
@@ -635,7 +640,7 @@ static void coroutine_fn mirror_run(void *opaque)
should_complete = false;
if (s->in_flight == 0 && cnt == 0) {
trace_mirror_before_flush(s);
- ret = bdrv_flush(s->target);
+ ret = blk_flush(s->target);
if (ret < 0) {
if (mirror_error_action(s, false, -ret) ==
BLOCK_ERROR_ACTION_REPORT) {
@@ -713,7 +718,7 @@ immediate_exit:
data->ret = ret;
/* Before we switch to target in mirror_exit, make sure data doesn't
* change. */
- bdrv_drained_begin(s->common.bs);
+ bdrv_drained_begin(bs);
if (qemu_get_aio_context() == bdrv_get_aio_context(bs)) {
/* FIXME: virtio host notifiers run on iohandler_ctx, therefore the
* above bdrv_drained_end isn't enough to quiesce it. This is ugly, we
@@ -740,7 +745,8 @@ static void mirror_complete(BlockJob *job, Error **errp)
Error *local_err = NULL;
int ret;
- ret = bdrv_open_backing_file(s->target, NULL, "backing", &local_err);
+ ret = bdrv_open_backing_file(blk_bs(s->target), NULL, "backing",
+ &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return;
@@ -823,10 +829,12 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
return;
}
+ s->target = blk_new();
+ blk_insert_bs(s->target, target);
+
s->replaces = g_strdup(replaces);
s->on_source_error = on_source_error;
s->on_target_error = on_target_error;
- s->target = target;
s->is_none_mode = is_none_mode;
s->base = base;
s->granularity = granularity;
@@ -836,11 +844,12 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
if (!s->dirty_bitmap) {
g_free(s->replaces);
+ blk_unref(s->target);
block_job_unref(&s->common);
return;
}
- bdrv_op_block_all(s->target, s->common.blocker);
+ bdrv_op_block_all(target, s->common.blocker);
s->common.co = qemu_coroutine_create(mirror_run);
trace_mirror_start(bs, s, s->common.co, opaque);
@@ -913,7 +922,6 @@ void commit_active_start(BlockDriverState *bs, BlockDriverState *base,
}
}
- bdrv_ref(base);
mirror_start_job(bs, base, NULL, speed, 0, 0,
on_error, on_error, false, cb, opaque, &local_err,
&commit_active_job_driver, false, base);
diff --git a/blockdev.c b/blockdev.c
index 3c06746..66477ff 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3621,9 +3621,9 @@ void qmp_drive_mirror(const char *device, const char *target,
has_on_target_error, on_target_error,
has_unmap, unmap,
&local_err);
+ bdrv_unref(target_bs);
if (local_err) {
error_propagate(errp, local_err);
- bdrv_unref(target_bs);
}
out:
aio_context_release(aio_context);
@@ -3667,7 +3667,6 @@ void qmp_blockdev_mirror(const char *device, const char *target,
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
- bdrv_ref(target_bs);
bdrv_set_aio_context(target_bs, aio_context);
blockdev_mirror_common(bs, target_bs,
@@ -3681,7 +3680,6 @@ void qmp_blockdev_mirror(const char *device, const char *target,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
- bdrv_unref(target_bs);
}
aio_context_release(aio_context);
--
1.8.3.1
next prev parent reply other threads:[~2016-05-24 13:48 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-24 13:47 [Qemu-devel] [PATCH v2 00/14] block jobs: Convert I/O to BlockBackend Kevin Wolf
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 01/14] block: keep a list of block jobs Kevin Wolf
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 02/14] block: Cancel jobs first in bdrv_close_all() Kevin Wolf
2016-05-24 22:29 ` Eric Blake
2016-05-25 11:31 ` Alberto Garcia
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 03/14] block: Default to enabled write cache in blk_new() Kevin Wolf
2016-05-25 11:32 ` Alberto Garcia
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 04/14] block: Convert block job core to BlockBackend Kevin Wolf
2016-05-25 0:17 ` Eric Blake
2016-05-25 3:50 ` Changlong Xie
2016-05-25 11:40 ` Alberto Garcia
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 05/14] block: Make blk_co_preadv/pwritev() public Kevin Wolf
2016-05-25 0:24 ` Eric Blake
2016-05-25 9:07 ` Kevin Wolf
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 06/14] stream: Use BlockBackend for I/O Kevin Wolf
2016-05-25 0:27 ` Eric Blake
2016-05-25 11:59 ` Alberto Garcia
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 07/14] mirror: Allow target that already has a BlockBackend Kevin Wolf
2016-05-24 13:47 ` Kevin Wolf [this message]
2016-05-25 1:48 ` [Qemu-devel] [PATCH v2 08/14] mirror: Use BlockBackend for I/O Eric Blake
2016-05-25 3:51 ` Changlong Xie
2016-05-25 4:01 ` Eric Blake
2016-05-25 4:12 ` Changlong Xie
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 09/14] backup: Don't leak BackupBlockJob in error path Kevin Wolf
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 10/14] backup: Pack Notifier within BackupBlockJob Kevin Wolf
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 11/14] backup: Remove bs parameter from backup_do_cow() Kevin Wolf
2016-05-25 12:05 ` Alberto Garcia
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 12/14] backup: Use BlockBackend for I/O Kevin Wolf
2016-05-25 1:53 ` Eric Blake
2016-05-25 3:51 ` Changlong Xie
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 13/14] commit: " Kevin Wolf
2016-05-25 1:56 ` Eric Blake
2016-05-25 3:51 ` Changlong Xie
2016-05-25 4:04 ` Eric Blake
2016-05-24 13:47 ` [Qemu-devel] [PATCH v2 14/14] blockjob: Remove BlockJob.bs Kevin Wolf
2016-05-25 6:29 ` Changlong Xie
2016-05-25 11:10 ` Kevin Wolf
2016-05-25 12:05 ` Alberto Garcia
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=1464097654-12977-9-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=berto@igalia.com \
--cc=jcody@redhat.com \
--cc=jsnow@redhat.com \
--cc=mreitz@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.