So, this fleecing-filter should be above fleecing image, the whole
picture of fleecing looks like this:
+-------+ +------------+
| | | |
| guest | | NBD client +<------+
| | | | |
++-----++ +------------+ |only read
| ^ |
| IO | |
v | +-----+------+
++-----+---------+ | |
| | | internal |
| active image +----+ | NBD server |
| | | | |
+-+--------------+ |backup +-+----------+
^ |sync=none ^
|backing | |only read
| | |
+-+--------------+ | +------+----------+
| | | | |
| fleecing image +<---+ | fleecing filter |
| | | |
+--------+-------+ +-----+-----------+
^ |
| |
+--------------------------+
file
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com>
---
qapi/block-core.json | 6 ++--
block/fleecing-filter.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
block/Makefile.objs | 1 +
3 files changed, 85 insertions(+), 2 deletions(-)
create mode 100644 block/fleecing-filter.c
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 577ce5e999..43872c3d79 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2542,7 +2542,8 @@
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', 'qcow2',
'qed',
'quorum', 'raw', 'rbd', 'replication', 'sheepdog', 'ssh',
- 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs' ] }
+ 'throttle', 'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat', 'vxhs',
+ 'fleecing-filter' ] }
##
# @BlockdevOptionsFile:
@@ -3594,7 +3595,8 @@
'vmdk': 'BlockdevOptionsGenericCOWFormat',
'vpc': 'BlockdevOptionsGenericFormat',
'vvfat': 'BlockdevOptionsVVFAT',
- 'vxhs': 'BlockdevOptionsVxHS'
+ 'vxhs': 'BlockdevOptionsVxHS',
+ 'fleecing-filter': 'BlockdevOptionsGenericFormat'
} }
##
diff --git a/block/fleecing-filter.c b/block/fleecing-filter.c
new file mode 100644
index 0000000000..b501887c10
--- /dev/null
+++ b/block/fleecing-filter.c
@@ -0,0 +1,80 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "block/blockjob.h"
+#include "block/block_int.h"
+#include "block/block_backup.h"
+
+static int64_t fleecing_getlength(BlockDriverState *bs)
+{
+ return bdrv_getlength(bs->file->bs);
+}
+
+static coroutine_fn int fleecing_co_preadv(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, int flags)
+{
+ int ret;
+ BlockJob *job = bs->file->bs->backing->bs->job;
+ CowRequest req;
+
+ backup_wait_for_overlapping_requests(job, offset, bytes);
+ backup_cow_request_begin(&req, job, offset, bytes);
+
+ ret = bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
+
+ backup_cow_request_end(&req);
+
+ return ret;
+}
+
+static coroutine_fn int fleecing_co_pwritev(BlockDriverState *bs,
+ uint64_t offset, uint64_t bytes,
+ QEMUIOVector *qiov, int flags)
+{
+ return -EINVAL;
+}
+
+static bool fleecing_recurse_is_first_non_filter(BlockDriverState *bs,
+ BlockDriverState *candidate)
+{
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
+}
+
+static int fleecing_open(BlockDriverState *bs, QDict *options,
+ int flags, Error **errp)
+{
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
+ errp);
+
+ return bs->file ? 0 : -EINVAL;
+}
+
+static void fleecing_close(BlockDriverState *bs)
+{
+ /* Do nothing, we have to add .bdrv_close, because bdrv_close() don't check
+ * it, just call. */
+}
+
+BlockDriver bdrv_fleecing_filter = {
+ .format_name = "fleecing-filter",
+ .protocol_name = "fleecing-filter",
+ .instance_size = 0,
+
+ .bdrv_open = fleecing_open,
+ .bdrv_close = fleecing_close,
+
+ .bdrv_getlength = fleecing_getlength,
+ .bdrv_co_preadv = fleecing_co_preadv,
+ .bdrv_co_pwritev = fleecing_co_pwritev,
+
+ .is_filter = true,
+ .bdrv_recurse_is_first_non_filter = fleecing_recurse_is_first_non_filter,
+ .bdrv_child_perm = bdrv_filter_default_perms,
+};
+
+static void bdrv_fleecing_init(void)
+{
+ bdrv_register(&bdrv_fleecing_filter);
+}
+
+block_init(bdrv_fleecing_init);
diff --git a/block/Makefile.objs b/block/Makefile.objs
index 899bfb5e2c..aa0a6dd971 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -27,6 +27,7 @@ block-obj-y += write-threshold.o
block-obj-y += backup.o
block-obj-$(CONFIG_REPLICATION) += replication.o
block-obj-y += throttle.o copy-on-read.o
+block-obj-y += fleecing-filter.o
block-obj-y += crypto.o