commit: Use BlockBackend for I/O

This changes the commit block job to use the job's BlockBackend for
performing its I/O. job->bs isn't used by the commit code any more
afterwards.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2016-04-14 13:09:53 +02:00
parent 5c438bc68c
commit 4653456a5f
1 changed files with 33 additions and 20 deletions

View File

@ -36,28 +36,36 @@ typedef struct CommitBlockJob {
BlockJob common; BlockJob common;
RateLimit limit; RateLimit limit;
BlockDriverState *active; BlockDriverState *active;
BlockDriverState *top; BlockBackend *top;
BlockDriverState *base; BlockBackend *base;
BlockdevOnError on_error; BlockdevOnError on_error;
int base_flags; int base_flags;
int orig_overlay_flags; int orig_overlay_flags;
char *backing_file_str; char *backing_file_str;
} CommitBlockJob; } CommitBlockJob;
static int coroutine_fn commit_populate(BlockDriverState *bs, static int coroutine_fn commit_populate(BlockBackend *bs, BlockBackend *base,
BlockDriverState *base,
int64_t sector_num, int nb_sectors, int64_t sector_num, int nb_sectors,
void *buf) void *buf)
{ {
int ret = 0; int ret = 0;
QEMUIOVector qiov;
struct iovec iov = {
.iov_base = buf,
.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
};
ret = bdrv_read(bs, sector_num, buf, nb_sectors); qemu_iovec_init_external(&qiov, &iov, 1);
if (ret) {
ret = blk_co_preadv(bs, sector_num * BDRV_SECTOR_SIZE,
qiov.size, &qiov, 0);
if (ret < 0) {
return ret; return ret;
} }
ret = bdrv_write(base, sector_num, buf, nb_sectors); ret = blk_co_pwritev(base, sector_num * BDRV_SECTOR_SIZE,
if (ret) { qiov.size, &qiov, 0);
if (ret < 0) {
return ret; return ret;
} }
@ -73,8 +81,8 @@ static void commit_complete(BlockJob *job, void *opaque)
CommitBlockJob *s = container_of(job, CommitBlockJob, common); CommitBlockJob *s = container_of(job, CommitBlockJob, common);
CommitCompleteData *data = opaque; CommitCompleteData *data = opaque;
BlockDriverState *active = s->active; BlockDriverState *active = s->active;
BlockDriverState *top = s->top; BlockDriverState *top = blk_bs(s->top);
BlockDriverState *base = s->base; BlockDriverState *base = blk_bs(s->base);
BlockDriverState *overlay_bs; BlockDriverState *overlay_bs;
int ret = data->ret; int ret = data->ret;
@ -94,6 +102,8 @@ static void commit_complete(BlockJob *job, void *opaque)
bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL);
} }
g_free(s->backing_file_str); g_free(s->backing_file_str);
blk_unref(s->top);
blk_unref(s->base);
block_job_completed(&s->common, ret); block_job_completed(&s->common, ret);
g_free(data); g_free(data);
} }
@ -102,8 +112,6 @@ static void coroutine_fn commit_run(void *opaque)
{ {
CommitBlockJob *s = opaque; CommitBlockJob *s = opaque;
CommitCompleteData *data; CommitCompleteData *data;
BlockDriverState *top = s->top;
BlockDriverState *base = s->base;
int64_t sector_num, end; int64_t sector_num, end;
int ret = 0; int ret = 0;
int n = 0; int n = 0;
@ -111,27 +119,27 @@ static void coroutine_fn commit_run(void *opaque)
int bytes_written = 0; int bytes_written = 0;
int64_t base_len; int64_t base_len;
ret = s->common.len = bdrv_getlength(top); ret = s->common.len = blk_getlength(s->top);
if (s->common.len < 0) { if (s->common.len < 0) {
goto out; goto out;
} }
ret = base_len = bdrv_getlength(base); ret = base_len = blk_getlength(s->base);
if (base_len < 0) { if (base_len < 0) {
goto out; goto out;
} }
if (base_len < s->common.len) { if (base_len < s->common.len) {
ret = bdrv_truncate(base, s->common.len); ret = blk_truncate(s->base, s->common.len);
if (ret) { if (ret) {
goto out; goto out;
} }
} }
end = s->common.len >> BDRV_SECTOR_BITS; end = s->common.len >> BDRV_SECTOR_BITS;
buf = qemu_blockalign(top, COMMIT_BUFFER_SIZE); buf = blk_blockalign(s->top, COMMIT_BUFFER_SIZE);
for (sector_num = 0; sector_num < end; sector_num += n) { for (sector_num = 0; sector_num < end; sector_num += n) {
uint64_t delay_ns = 0; uint64_t delay_ns = 0;
@ -146,7 +154,8 @@ wait:
break; break;
} }
/* Copy if allocated above the base */ /* Copy if allocated above the base */
ret = bdrv_is_allocated_above(top, base, sector_num, ret = bdrv_is_allocated_above(blk_bs(s->top), blk_bs(s->base),
sector_num,
COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE, COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE,
&n); &n);
copy = (ret == 1); copy = (ret == 1);
@ -158,7 +167,7 @@ wait:
goto wait; goto wait;
} }
} }
ret = commit_populate(top, base, sector_num, n, buf); ret = commit_populate(s->top, s->base, sector_num, n, buf);
bytes_written += n * BDRV_SECTOR_SIZE; bytes_written += n * BDRV_SECTOR_SIZE;
} }
if (ret < 0) { if (ret < 0) {
@ -253,8 +262,12 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
return; return;
} }
s->base = base; s->base = blk_new();
s->top = top; blk_insert_bs(s->base, base);
s->top = blk_new();
blk_insert_bs(s->top, top);
s->active = bs; s->active = bs;
s->base_flags = orig_base_flags; s->base_flags = orig_base_flags;