--- /dev/null
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Fiona Ebner <f.ebner@proxmox.com>
+Date: Thu, 11 Apr 2024 11:29:27 +0200
+Subject: [PATCH] backup: add minimum cluster size to performance options
+
+Useful to make discard-source work in the context of backup fleecing
+when the fleecing image has a larger granularity than the backup
+target.
+
+Backup/block-copy will use at least this granularity for copy operations
+and in particular, discard requests to the backup source will too. If
+the granularity is too small, they will just be aligned down in
+cbw_co_pdiscard_snapshot() and thus effectively ignored.
+
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ block/backup.c | 2 +-
+ block/copy-before-write.c | 2 ++
+ block/copy-before-write.h | 1 +
+ blockdev.c | 3 +++
+ qapi/block-core.json | 9 +++++++--
+ 5 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/block/backup.c b/block/backup.c
+index 3dc955f625..ac5bd81338 100644
+--- a/block/backup.c
++++ b/block/backup.c
+@@ -430,7 +430,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
+ }
+
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, discard_source,
+- &bcs, errp);
++ perf->min_cluster_size, &bcs, errp);
+ if (!cbw) {
+ goto error;
+ }
+diff --git a/block/copy-before-write.c b/block/copy-before-write.c
+index 4a8c5bdb62..9ca5ec5e5c 100644
+--- a/block/copy-before-write.c
++++ b/block/copy-before-write.c
+@@ -555,6 +555,7 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
+ BlockDriverState *target,
+ const char *filter_node_name,
+ bool discard_source,
++ int64_t min_cluster_size,
+ BlockCopyState **bcs,
+ Error **errp)
+ {
+@@ -573,6 +574,7 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
+ }
+ qdict_put_str(opts, "file", bdrv_get_node_name(source));
+ qdict_put_str(opts, "target", bdrv_get_node_name(target));
++ qdict_put_int(opts, "min-cluster-size", min_cluster_size);
+
+ top = bdrv_insert_node(source, opts, flags, errp);
+ if (!top) {
+diff --git a/block/copy-before-write.h b/block/copy-before-write.h
+index 01af0cd3c4..dc6cafe7fa 100644
+--- a/block/copy-before-write.h
++++ b/block/copy-before-write.h
+@@ -40,6 +40,7 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
+ BlockDriverState *target,
+ const char *filter_node_name,
+ bool discard_source,
++ int64_t min_cluster_size,
+ BlockCopyState **bcs,
+ Error **errp);
+ void bdrv_cbw_drop(BlockDriverState *bs);
+diff --git a/blockdev.c b/blockdev.c
+index ce3fef924c..5ae1dde73c 100644
+--- a/blockdev.c
++++ b/blockdev.c
+@@ -2729,6 +2729,9 @@ static BlockJob *do_backup_common(BackupCommon *backup,
+ if (backup->x_perf->has_max_chunk) {
+ perf.max_chunk = backup->x_perf->max_chunk;
+ }
++ if (backup->x_perf->has_min_cluster_size) {
++ perf.min_cluster_size = backup->x_perf->min_cluster_size;
++ }
+ }
+
+ if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
+diff --git a/qapi/block-core.json b/qapi/block-core.json
+index 33e7e3c090..58fd637e86 100644
+--- a/qapi/block-core.json
++++ b/qapi/block-core.json
+@@ -1757,11 +1757,16 @@
+ # it should not be less than job cluster size which is calculated
+ # as maximum of target image cluster size and 64k. Default 0.
+ #
++# @min-cluster-size: Minimum size of blocks used by copy-before-write
++# and background copy operations. Has to be a power of 2. No
++# effect if smaller than the maximum of the target's cluster size
++# and 64 KiB. Default 0. (Since 8.1)
++#
+ # Since: 6.0
+ ##
+ { 'struct': 'BackupPerf',
+- 'data': { '*use-copy-range': 'bool',
+- '*max-workers': 'int', '*max-chunk': 'int64' } }
++ 'data': { '*use-copy-range': 'bool', '*max-workers': 'int',
++ '*max-chunk': 'int64', '*min-cluster-size': 'uint32' } }
+
+ ##
+ # @BackupCommon: