backup: Use BlockBackend for I/O

This changes the backup block job to use the job's BlockBackend for
performing its I/O. job->bs isn't used by the backup 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 8543c27414
commit 5c438bc68c
5 changed files with 22 additions and 40 deletions

View File

@ -36,7 +36,7 @@ typedef struct CowRequest {
typedef struct BackupBlockJob { typedef struct BackupBlockJob {
BlockJob common; BlockJob common;
BlockDriverState *target; BlockBackend *target;
/* bitmap for sync=incremental */ /* bitmap for sync=incremental */
BdrvDirtyBitmap *sync_bitmap; BdrvDirtyBitmap *sync_bitmap;
MirrorSyncMode sync_mode; MirrorSyncMode sync_mode;
@ -99,7 +99,7 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
bool *error_is_read, bool *error_is_read,
bool is_write_notifier) bool is_write_notifier)
{ {
BlockDriverState *bs = job->common.bs; BlockBackend *blk = job->common.blk;
CowRequest cow_request; CowRequest cow_request;
struct iovec iov; struct iovec iov;
QEMUIOVector bounce_qiov; QEMUIOVector bounce_qiov;
@ -132,20 +132,15 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
start * sectors_per_cluster); start * sectors_per_cluster);
if (!bounce_buffer) { if (!bounce_buffer) {
bounce_buffer = qemu_blockalign(bs, job->cluster_size); bounce_buffer = blk_blockalign(blk, job->cluster_size);
} }
iov.iov_base = bounce_buffer; iov.iov_base = bounce_buffer;
iov.iov_len = n * BDRV_SECTOR_SIZE; iov.iov_len = n * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&bounce_qiov, &iov, 1); qemu_iovec_init_external(&bounce_qiov, &iov, 1);
if (is_write_notifier) { ret = blk_co_preadv(blk, start * job->cluster_size,
ret = bdrv_co_readv_no_serialising(bs, bounce_qiov.size, &bounce_qiov,
start * sectors_per_cluster, is_write_notifier ? BDRV_REQ_NO_SERIALISING : 0);
n, &bounce_qiov);
} else {
ret = bdrv_co_readv(bs, start * sectors_per_cluster, n,
&bounce_qiov);
}
if (ret < 0) { if (ret < 0) {
trace_backup_do_cow_read_fail(job, start, ret); trace_backup_do_cow_read_fail(job, start, ret);
if (error_is_read) { if (error_is_read) {
@ -155,13 +150,11 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
} }
if (buffer_is_zero(iov.iov_base, iov.iov_len)) { if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
ret = bdrv_co_write_zeroes(job->target, ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
start * sectors_per_cluster, bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
n, BDRV_REQ_MAY_UNMAP);
} else { } else {
ret = bdrv_co_writev(job->target, ret = blk_co_pwritev(job->target, start * job->cluster_size,
start * sectors_per_cluster, n, bounce_qiov.size, &bounce_qiov, 0);
&bounce_qiov);
} }
if (ret < 0) { if (ret < 0) {
trace_backup_do_cow_write_fail(job, start, ret); trace_backup_do_cow_write_fail(job, start, ret);
@ -203,7 +196,7 @@ static int coroutine_fn backup_before_write_notify(
int64_t sector_num = req->offset >> BDRV_SECTOR_BITS; int64_t sector_num = req->offset >> BDRV_SECTOR_BITS;
int nb_sectors = req->bytes >> BDRV_SECTOR_BITS; int nb_sectors = req->bytes >> BDRV_SECTOR_BITS;
assert(req->bs == job->common.bs); assert(req->bs == blk_bs(job->common.blk));
assert((req->offset & (BDRV_SECTOR_SIZE - 1)) == 0); assert((req->offset & (BDRV_SECTOR_SIZE - 1)) == 0);
assert((req->bytes & (BDRV_SECTOR_SIZE - 1)) == 0); assert((req->bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
@ -224,7 +217,7 @@ static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp)
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret) static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
{ {
BdrvDirtyBitmap *bm; BdrvDirtyBitmap *bm;
BlockDriverState *bs = job->common.bs; BlockDriverState *bs = blk_bs(job->common.blk);
if (ret < 0 || block_job_is_cancelled(&job->common)) { if (ret < 0 || block_job_is_cancelled(&job->common)) {
/* Merge the successor back into the parent, delete nothing. */ /* Merge the successor back into the parent, delete nothing. */
@ -282,7 +275,7 @@ static void backup_complete(BlockJob *job, void *opaque)
BackupBlockJob *s = container_of(job, BackupBlockJob, common); BackupBlockJob *s = container_of(job, BackupBlockJob, common);
BackupCompleteData *data = opaque; BackupCompleteData *data = opaque;
bdrv_unref(s->target); blk_unref(s->target);
block_job_completed(job, data->ret); block_job_completed(job, data->ret);
g_free(data); g_free(data);
@ -378,8 +371,8 @@ static void coroutine_fn backup_run(void *opaque)
{ {
BackupBlockJob *job = opaque; BackupBlockJob *job = opaque;
BackupCompleteData *data; BackupCompleteData *data;
BlockDriverState *bs = job->common.bs; BlockDriverState *bs = blk_bs(job->common.blk);
BlockDriverState *target = job->target; BlockBackend *target = job->target;
int64_t start, end; int64_t start, end;
int64_t sectors_per_cluster = cluster_size_sectors(job); int64_t sectors_per_cluster = cluster_size_sectors(job);
int ret = 0; int ret = 0;
@ -468,7 +461,7 @@ static void coroutine_fn backup_run(void *opaque)
qemu_co_rwlock_unlock(&job->flush_rwlock); qemu_co_rwlock_unlock(&job->flush_rwlock);
g_free(job->done_bitmap); g_free(job->done_bitmap);
bdrv_op_unblock_all(target, job->common.blocker); bdrv_op_unblock_all(blk_bs(target), job->common.blocker);
data = g_malloc(sizeof(*data)); data = g_malloc(sizeof(*data));
data->ret = ret; data->ret = ret;
@ -548,9 +541,11 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
goto error; goto error;
} }
job->target = blk_new();
blk_insert_bs(job->target, target);
job->on_source_error = on_source_error; job->on_source_error = on_source_error;
job->on_target_error = on_target_error; job->on_target_error = on_target_error;
job->target = target;
job->sync_mode = sync_mode; job->sync_mode = sync_mode;
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ? job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
sync_bitmap : NULL; sync_bitmap : NULL;
@ -558,7 +553,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
/* If there is no backing file on the target, we cannot rely on COW if our /* If there is no backing file on the target, we cannot rely on COW if our
* backup cluster size is smaller than the target cluster size. Even for * backup cluster size is smaller than the target cluster size. Even for
* targets with a backing file, try to avoid COW if possible. */ * targets with a backing file, try to avoid COW if possible. */
ret = bdrv_get_info(job->target, &bdi); ret = bdrv_get_info(target, &bdi);
if (ret < 0 && !target->backing) { if (ret < 0 && !target->backing) {
error_setg_errno(errp, -ret, error_setg_errno(errp, -ret,
"Couldn't determine the cluster size of the target image, " "Couldn't determine the cluster size of the target image, "
@ -585,6 +580,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL); bdrv_reclaim_dirty_bitmap(bs, sync_bitmap, NULL);
} }
if (job) { if (job) {
blk_unref(job->target);
block_job_unref(&job->common); block_job_unref(&job->common);
} }
} }

View File

@ -1108,15 +1108,6 @@ int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, 0); return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov, 0);
} }
int coroutine_fn bdrv_co_readv_no_serialising(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
{
trace_bdrv_co_readv_no_serialising(bs, sector_num, nb_sectors);
return bdrv_co_do_readv(bs, sector_num, nb_sectors, qiov,
BDRV_REQ_NO_SERIALISING);
}
#define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768 #define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs, static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,

View File

@ -3293,8 +3293,8 @@ static void do_drive_backup(const char *device, const char *target,
backup_start(bs, target_bs, speed, sync, bmap, backup_start(bs, target_bs, speed, sync, bmap,
on_source_error, on_target_error, on_source_error, on_target_error,
block_job_cb, bs, txn, &local_err); block_job_cb, bs, txn, &local_err);
bdrv_unref(target_bs);
if (local_err != NULL) { if (local_err != NULL) {
bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto out; goto out;
} }
@ -3378,12 +3378,10 @@ void do_blockdev_backup(const char *device, const char *target,
} }
target_bs = blk_bs(target_blk); target_bs = blk_bs(target_blk);
bdrv_ref(target_bs);
bdrv_set_aio_context(target_bs, aio_context); bdrv_set_aio_context(target_bs, aio_context);
backup_start(bs, target_bs, speed, sync, NULL, on_source_error, backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
on_target_error, block_job_cb, bs, txn, &local_err); on_target_error, block_job_cb, bs, txn, &local_err);
if (local_err != NULL) { if (local_err != NULL) {
bdrv_unref(target_bs);
error_propagate(errp, local_err); error_propagate(errp, local_err);
} }
out: out:

View File

@ -242,8 +242,6 @@ int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
const void *buf, int count); const void *buf, int count);
int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num, int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, QEMUIOVector *qiov); int nb_sectors, QEMUIOVector *qiov);
int coroutine_fn bdrv_co_readv_no_serialising(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num, int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, QEMUIOVector *qiov); int nb_sectors, QEMUIOVector *qiov);
/* /*

View File

@ -72,7 +72,6 @@ bdrv_aio_readv(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %
bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p" bdrv_aio_writev(void *bs, int64_t sector_num, int nb_sectors, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d opaque %p"
bdrv_aio_write_zeroes(void *bs, int64_t sector_num, int nb_sectors, int flags, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x opaque %p" bdrv_aio_write_zeroes(void *bs, int64_t sector_num, int nb_sectors, int flags, void *opaque) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x opaque %p"
bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_readv(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
bdrv_co_readv_no_serialising(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d" bdrv_co_writev(void *bs, int64_t sector_num, int nb_sector) "bs %p sector_num %"PRId64" nb_sectors %d"
bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector, int flags) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x" bdrv_co_write_zeroes(void *bs, int64_t sector_num, int nb_sector, int flags) "bs %p sector_num %"PRId64" nb_sectors %d flags %#x"
bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d" bdrv_co_do_copy_on_readv(void *bs, int64_t sector_num, int nb_sectors, int64_t cluster_sector_num, int cluster_nb_sectors) "bs %p sector_num %"PRId64" nb_sectors %d cluster_sector_num %"PRId64" cluster_nb_sectors %d"