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:
parent
8543c27414
commit
5c438bc68c
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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:
|
||||||
|
@ -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);
|
||||||
/*
|
/*
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user