We are on the way to implement internal-backup with fleecing scheme,
which includes backup job copying from fleecing block driver node
(which is target of copy-before-write filter) to final target of
backup. This job doesn't need own filter, as fleecing block driver node
is a kind of snapshot, it's immutable from reader point of view.
Let's add a parameter for backup to not insert filter but instead
unshare writes on source. This way backup job becomes a simple copying
process.
Signed-off-by: Vladimir Sementsov-Ogievskiy
---
qapi/block-core.json | 11 ++-
include/block/block_int.h | 1 +
block/backup.c| 61 +++
block/replication.c | 2 +-
blockdev.c| 1 +
5 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a904755e98..30d44683bf 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1436,6 +1436,15 @@
#above node specified by @drive. If this option is not
given,
#a node name is autogenerated. (Since: 4.2)
#
+# @immutable-source: If true, assume source is immutable, and don't insert
filter
+#as no copy-before-write operations are needed. It will
+#fail if there are existing writers on source node.
+#Any attempt to add writer to source node during backup
will
+#also fail. @filter-node-name must not be set.
+#If false, insert copy-before-write filter above source
node
+#(see also @filter-node-name parameter).
+#Default is false. (Since 6.2)
+#
# @x-perf: Performance options. (Since 6.0)
#
# Features:
@@ -1455,7 +1464,7 @@
'*on-source-error': 'BlockdevOnError',
'*on-target-error': 'BlockdevOnError',
'*auto-finalize': 'bool', '*auto-dismiss': 'bool',
-'*filter-node-name': 'str',
+'*filter-node-name': 'str', '*immutable-source': 'bool',
'*x-perf': { 'type': 'BackupPerf',
'features': [ 'unstable' ] } } }
diff --git a/include/block/block_int.h b/include/block/block_int.h
index c43315ae6e..0270af29ae 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -1348,6 +1348,7 @@ BlockJob *backup_job_create(const char *job_id,
BlockDriverState *bs,
BitmapSyncMode bitmap_mode,
bool compress,
const char *filter_node_name,
+bool immutable_source,
BackupPerf *perf,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
diff --git a/block/backup.c b/block/backup.c
index 21d5983779..104f8fd835 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -34,6 +34,14 @@ typedef struct BackupBlockJob {
BlockDriverState *cbw;
BlockDriverState *source_bs;
BlockDriverState *target_bs;
+BlockBackend *source_blk;
+BlockBackend *target_blk;
+/*
+ * Note that if backup runs with filter (immutable-source parameter is
+ * false), @cbw is set but @source_blk and @target_blk are NULL.
+ * Otherwise if backup runs without filter (immutable-source paramter is
+ * true), @cbw is NULL but @source_blk and @target_blk are set.
+ */
BdrvDirtyBitmap *sync_bitmap;
@@ -102,7 +110,17 @@ static void backup_clean(Job *job)
{
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
block_job_remove_all_bdrv(>common);
-bdrv_cbw_drop(s->cbw);
+if (s->cbw) {
+assert(!s->source_blk && !s->target_blk);
+bdrv_cbw_drop(s->cbw);
+} else {
+block_copy_state_free(s->bcs);
+s->bcs = NULL;
+blk_unref(s->source_blk);
+s->source_blk = NULL;
+blk_unref(s->target_blk);
+s->target_blk = NULL;
+}
}
void backup_do_checkpoint(BlockJob *job, Error **errp)
@@ -357,6 +375,7 @@ BlockJob *backup_job_create(const char *job_id,
BlockDriverState *bs,
BitmapSyncMode bitmap_mode,
bool compress,
const char *filter_node_name,
+ bool immutable_source,
BackupPerf *perf,
BlockdevOnError on_source_error,
BlockdevOnError on_target_error,
@@ -369,6 +388,7 @@ BlockJob *backup_job_create(const char *job_id,
BlockDriverState *bs,
int64_t cluster_size;
BlockDriverState *cbw = NULL;
BlockCopyState *bcs = NULL;
+BlockBackend *source_blk = NULL, *target_blk = NULL;
assert(bs);
assert(target);
@@ -377,6 +397,12 @@ BlockJob *backup_job_create(const char *job_id,
BlockDriverState *bs,
assert(sync_mode != MIRROR_SYNC_MODE_INCREMENTAL);
assert(sync_bitmap || sync_mode != MIRROR_SYNC_MODE_BITMAP);
+if