pve-qemu/debian/patches/pve/0014-backup-modify-job-api....

237 lines
9.2 KiB
Diff

From 1078c0f6acc1bfba04b7d5cdfdeb02b161b5f7c4 Mon Sep 17 00:00:00 2001
From: Wolfgang Bumiller <w.bumiller@proxmox.com>
Date: Wed, 9 Dec 2015 15:04:57 +0100
Subject: [PATCH 14/47] backup: modify job api
Introduces a BackupDump function callback and a pause_count
for backup_start. For a dump-backup the target parameter
can now be NULL so access to target needs to be guarded now.
---
block/backup.c | 82 +++++++++++++++++++++++++++++++----------------
blockdev.c | 6 ++--
include/block/block_int.h | 5 +++
3 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/block/backup.c b/block/backup.c
index 2c05323..f3c0ba3 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -41,6 +41,7 @@ typedef struct BackupBlockJob {
BdrvDirtyBitmap *sync_bitmap;
MirrorSyncMode sync_mode;
RateLimit limit;
+ BackupDumpFunc *dump_cb;
BlockdevOnError on_source_error;
BlockdevOnError on_target_error;
CoRwlock flush_rwlock;
@@ -149,12 +150,23 @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
goto out;
}
+ int64_t start_sec = start * sectors_per_cluster;
if (buffer_is_zero(iov.iov_base, iov.iov_len)) {
- ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
- bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
+ if (job->dump_cb) {
+ ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, NULL);
+ }
+ if (job->target) {
+ ret = blk_co_pwrite_zeroes(job->target, start * job->cluster_size,
+ bounce_qiov.size, BDRV_REQ_MAY_UNMAP);
+ }
} else {
- ret = blk_co_pwritev(job->target, start * job->cluster_size,
- bounce_qiov.size, &bounce_qiov, 0);
+ if (job->dump_cb) {
+ ret = job->dump_cb(job->common.opaque, job->target, start_sec, n, bounce_buffer);
+ }
+ if (job->target) {
+ ret = blk_co_pwritev(job->target, start * job->cluster_size,
+ bounce_qiov.size, &bounce_qiov, 0);
+ }
}
if (ret < 0) {
trace_backup_do_cow_write_fail(job, start, ret);
@@ -268,9 +280,11 @@ static BlockErrorAction backup_error_action(BackupBlockJob *job,
if (read) {
return block_job_error_action(&job->common, job->on_source_error,
true, error);
- } else {
+ } else if (job->target) {
return block_job_error_action(&job->common, job->on_target_error,
false, error);
+ } else {
+ return BLOCK_ERROR_ACTION_REPORT;
}
}
@@ -393,6 +407,7 @@ static void coroutine_fn backup_run(void *opaque)
job->done_bitmap = bitmap_new(end);
+
job->before_write.notify = backup_before_write_notify;
bdrv_add_before_write_notifier(bs, &job->before_write);
@@ -467,7 +482,9 @@ static void coroutine_fn backup_run(void *opaque)
qemu_co_rwlock_unlock(&job->flush_rwlock);
g_free(job->done_bitmap);
- bdrv_op_unblock_all(blk_bs(target), job->common.blocker);
+ if (target) {
+ bdrv_op_unblock_all(blk_bs(target), job->common.blocker);
+ }
data = g_malloc(sizeof(*data));
data->ret = ret;
@@ -479,7 +496,9 @@ void backup_start(const char *job_id, BlockDriverState *bs,
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
+ BackupDumpFunc *dump_cb,
BlockCompletionFunc *cb, void *opaque,
+ int pause_count,
BlockJobTxn *txn, Error **errp)
{
int64_t len;
@@ -488,7 +507,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
int ret;
assert(bs);
- assert(target);
+ assert(target || dump_cb);
if (bs == target) {
error_setg(errp, "Source and target cannot be the same");
@@ -501,7 +520,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
return;
}
- if (!bdrv_is_inserted(target)) {
+ if (target && !bdrv_is_inserted(target)) {
error_setg(errp, "Device is not inserted: %s",
bdrv_get_device_name(target));
return;
@@ -511,7 +530,7 @@ void backup_start(const char *job_id, BlockDriverState *bs,
return;
}
- if (bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
+ if (target && bdrv_op_is_blocked(target, BLOCK_OP_TYPE_BACKUP_TARGET, errp)) {
return;
}
@@ -547,34 +566,43 @@ void backup_start(const char *job_id, BlockDriverState *bs,
goto error;
}
- job->target = blk_new();
- blk_insert_bs(job->target, target);
+ if (target) {
+ job->target = blk_new();
+ blk_insert_bs(job->target, target);
+ }
+ job->dump_cb = dump_cb;
job->on_source_error = on_source_error;
job->on_target_error = on_target_error;
job->sync_mode = sync_mode;
job->sync_bitmap = sync_mode == MIRROR_SYNC_MODE_INCREMENTAL ?
sync_bitmap : NULL;
- /* 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
- * targets with a backing file, try to avoid COW if possible. */
- ret = bdrv_get_info(target, &bdi);
- if (ret < 0 && !target->backing) {
- error_setg_errno(errp, -ret,
- "Couldn't determine the cluster size of the target image, "
- "which has no backing file");
- error_append_hint(errp,
- "Aborting, since this may create an unusable destination image\n");
- goto error;
- } else if (ret < 0 && target->backing) {
- /* Not fatal; just trudge on ahead. */
- job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
+ if (target) {
+ /* 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
+ * targets with a backing file, try to avoid COW if possible. */
+ ret = bdrv_get_info(target, &bdi);
+ if (ret < 0 && !target->backing) {
+ error_setg_errno(errp, -ret,
+ "Couldn't determine the cluster size of the target image, "
+ "which has no backing file");
+ error_append_hint(errp,
+ "Aborting, since this may create an unusable destination image\n");
+ goto error;
+ } else if (ret < 0 && target->backing) {
+ /* Not fatal; just trudge on ahead. */
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
+ } else {
+ job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
+ }
+
+ bdrv_op_block_all(target, job->common.blocker);
} else {
- job->cluster_size = MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
+ job->cluster_size = BACKUP_CLUSTER_SIZE_DEFAULT;
}
- bdrv_op_block_all(target, job->common.blocker);
+ job->common.pause_count = pause_count;
job->common.len = len;
job->common.co = qemu_coroutine_create(backup_run, job);
block_job_txn_add_job(txn, &job->common);
diff --git a/blockdev.c b/blockdev.c
index 2161400..5e3707d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3277,8 +3277,8 @@ static void do_drive_backup(const char *job_id, const char *device,
}
backup_start(job_id, bs, target_bs, speed, sync, bmap,
- on_source_error, on_target_error,
- block_job_cb, bs, txn, &local_err);
+ on_source_error, on_target_error, NULL,
+ block_job_cb, bs, 0, txn, &local_err);
bdrv_unref(target_bs);
if (local_err != NULL) {
error_propagate(errp, local_err);
@@ -3371,7 +3371,7 @@ void do_blockdev_backup(const char *job_id, const char *device,
}
}
backup_start(job_id, bs, target_bs, speed, sync, NULL, on_source_error,
- on_target_error, block_job_cb, bs, txn, &local_err);
+ on_target_error, NULL, block_job_cb, bs, 0, txn, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
}
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 1e939de..db4650e 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -59,6 +59,9 @@
#define BLOCK_PROBE_BUF_SIZE 512
+typedef int BackupDumpFunc(void *opaque, BlockDriverState *bs,
+ int64_t sector_num, int n_sectors, unsigned char *buf);
+
enum BdrvTrackedRequestType {
BDRV_TRACKED_READ,
BDRV_TRACKED_WRITE,
@@ -767,7 +770,9 @@ void backup_start(const char *job_id, BlockDriverState *bs,
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
+ BackupDumpFunc *dump_cb,
BlockCompletionFunc *cb, void *opaque,
+ int pause_count,
BlockJobTxn *txn, Error **errp);
void hmp_drive_add_node(Monitor *mon, const char *optstr);
--
2.1.4