ae23c9
From b4442d3284353b0ad54eacbe7e29c8d09dbcf301 Mon Sep 17 00:00:00 2001
ae23c9
From: Max Reitz <mreitz@redhat.com>
ae23c9
Date: Mon, 18 Jun 2018 16:12:04 +0200
ae23c9
Subject: [PATCH 037/268] block: Add COR filter driver
ae23c9
ae23c9
RH-Author: Max Reitz <mreitz@redhat.com>
ae23c9
Message-id: <20180618161212.14444-3-mreitz@redhat.com>
ae23c9
Patchwork-id: 80762
ae23c9
O-Subject: [RHV-7.6 qemu-kvm-rhev PATCH 02/10] block: Add COR filter driver
ae23c9
Bugzilla: 1518738
ae23c9
RH-Acked-by: John Snow <jsnow@redhat.com>
ae23c9
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
ae23c9
This adds a simple copy-on-read filter driver.  It relies on the already
ae23c9
existing COR functionality in the central block layer code, which may be
ae23c9
moved here once we no longer need it there.
ae23c9
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
Message-id: 20180421132929.21610-2-mreitz@redhat.com
ae23c9
Reviewed-by: Alberto Garcia <berto@igalia.com>
ae23c9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
(cherry picked from commit 6c6f24fd84895d03baa898bbc4324dd4ccc97071)
ae23c9
Signed-off-by: Max Reitz <mreitz@redhat.com>
ae23c9
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
ae23c9
---
ae23c9
 block/Makefile.objs  |   2 +-
ae23c9
 block/copy-on-read.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++
ae23c9
 qapi/block-core.json |   5 +-
ae23c9
 3 files changed, 176 insertions(+), 2 deletions(-)
ae23c9
 create mode 100644 block/copy-on-read.c
ae23c9
ae23c9
diff --git a/block/Makefile.objs b/block/Makefile.objs
ae23c9
index c0693fc..be2cda1 100644
ae23c9
--- a/block/Makefile.objs
ae23c9
+++ b/block/Makefile.objs
ae23c9
@@ -26,7 +26,7 @@ block-obj-y += accounting.o dirty-bitmap.o
ae23c9
 block-obj-y += write-threshold.o
ae23c9
 block-obj-y += backup.o
ae23c9
 block-obj-$(CONFIG_REPLICATION) += replication.o
ae23c9
-block-obj-y += throttle.o
ae23c9
+block-obj-y += throttle.o copy-on-read.o
ae23c9
 
ae23c9
 block-obj-y += crypto.o
ae23c9
 
ae23c9
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
ae23c9
new file mode 100644
ae23c9
index 0000000..823ec75
ae23c9
--- /dev/null
ae23c9
+++ b/block/copy-on-read.c
ae23c9
@@ -0,0 +1,171 @@
ae23c9
+/*
ae23c9
+ * Copy-on-read filter block driver
ae23c9
+ *
ae23c9
+ * Copyright (c) 2018 Red Hat, Inc.
ae23c9
+ *
ae23c9
+ * Author:
ae23c9
+ *   Max Reitz <mreitz@redhat.com>
ae23c9
+ *
ae23c9
+ * This program is free software; you can redistribute it and/or
ae23c9
+ * modify it under the terms of the GNU General Public License as
ae23c9
+ * published by the Free Software Foundation; either version 2 or
ae23c9
+ * (at your option) version 3 of the License.
ae23c9
+ *
ae23c9
+ * This program is distributed in the hope that it will be useful,
ae23c9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
ae23c9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ae23c9
+ * GNU General Public License for more details.
ae23c9
+ *
ae23c9
+ * You should have received a copy of the GNU General Public License
ae23c9
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
ae23c9
+ */
ae23c9
+
ae23c9
+#include "qemu/osdep.h"
ae23c9
+#include "block/block_int.h"
ae23c9
+
ae23c9
+
ae23c9
+static int cor_open(BlockDriverState *bs, QDict *options, int flags,
ae23c9
+                    Error **errp)
ae23c9
+{
ae23c9
+    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
ae23c9
+                               errp);
ae23c9
+    if (!bs->file) {
ae23c9
+        return -EINVAL;
ae23c9
+    }
ae23c9
+
ae23c9
+    bs->supported_write_flags = BDRV_REQ_FUA &
ae23c9
+                                    bs->file->bs->supported_write_flags;
ae23c9
+
ae23c9
+    bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
ae23c9
+                                    bs->file->bs->supported_zero_flags;
ae23c9
+
ae23c9
+    return 0;
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static void cor_close(BlockDriverState *bs)
ae23c9
+{
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+#define PERM_PASSTHROUGH (BLK_PERM_CONSISTENT_READ \
ae23c9
+                          | BLK_PERM_WRITE \
ae23c9
+                          | BLK_PERM_RESIZE)
ae23c9
+#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
ae23c9
+
ae23c9
+static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
ae23c9
+                           const BdrvChildRole *role,
ae23c9
+                           BlockReopenQueue *reopen_queue,
ae23c9
+                           uint64_t perm, uint64_t shared,
ae23c9
+                           uint64_t *nperm, uint64_t *nshared)
ae23c9
+{
ae23c9
+    if (c == NULL) {
ae23c9
+        *nperm = (perm & PERM_PASSTHROUGH) | BLK_PERM_WRITE_UNCHANGED;
ae23c9
+        *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
ae23c9
+        return;
ae23c9
+    }
ae23c9
+
ae23c9
+    *nperm = (perm & PERM_PASSTHROUGH) |
ae23c9
+             (c->perm & PERM_UNCHANGED);
ae23c9
+    *nshared = (shared & PERM_PASSTHROUGH) |
ae23c9
+               (c->shared_perm & PERM_UNCHANGED);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int64_t cor_getlength(BlockDriverState *bs)
ae23c9
+{
ae23c9
+    return bdrv_getlength(bs->file->bs);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int cor_truncate(BlockDriverState *bs, int64_t offset,
ae23c9
+                        PreallocMode prealloc, Error **errp)
ae23c9
+{
ae23c9
+    return bdrv_truncate(bs->file, offset, prealloc, errp);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int coroutine_fn cor_co_preadv(BlockDriverState *bs,
ae23c9
+                                      uint64_t offset, uint64_t bytes,
ae23c9
+                                      QEMUIOVector *qiov, int flags)
ae23c9
+{
ae23c9
+    return bdrv_co_preadv(bs->file, offset, bytes, qiov,
ae23c9
+                          flags | BDRV_REQ_COPY_ON_READ);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int coroutine_fn cor_co_pwritev(BlockDriverState *bs,
ae23c9
+                                       uint64_t offset, uint64_t bytes,
ae23c9
+                                       QEMUIOVector *qiov, int flags)
ae23c9
+{
ae23c9
+
ae23c9
+    return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
ae23c9
+                                             int64_t offset, int bytes,
ae23c9
+                                             BdrvRequestFlags flags)
ae23c9
+{
ae23c9
+    return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
ae23c9
+                                        int64_t offset, int bytes)
ae23c9
+{
ae23c9
+    return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static void cor_eject(BlockDriverState *bs, bool eject_flag)
ae23c9
+{
ae23c9
+    bdrv_eject(bs->file->bs, eject_flag);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static void cor_lock_medium(BlockDriverState *bs, bool locked)
ae23c9
+{
ae23c9
+    bdrv_lock_medium(bs->file->bs, locked);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+static bool cor_recurse_is_first_non_filter(BlockDriverState *bs,
ae23c9
+                                            BlockDriverState *candidate)
ae23c9
+{
ae23c9
+    return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
ae23c9
+}
ae23c9
+
ae23c9
+
ae23c9
+BlockDriver bdrv_copy_on_read = {
ae23c9
+    .format_name                        = "copy-on-read",
ae23c9
+
ae23c9
+    .bdrv_open                          = cor_open,
ae23c9
+    .bdrv_close                         = cor_close,
ae23c9
+    .bdrv_child_perm                    = cor_child_perm,
ae23c9
+
ae23c9
+    .bdrv_getlength                     = cor_getlength,
ae23c9
+    .bdrv_truncate                      = cor_truncate,
ae23c9
+
ae23c9
+    .bdrv_co_preadv                     = cor_co_preadv,
ae23c9
+    .bdrv_co_pwritev                    = cor_co_pwritev,
ae23c9
+    .bdrv_co_pwrite_zeroes              = cor_co_pwrite_zeroes,
ae23c9
+    .bdrv_co_pdiscard                   = cor_co_pdiscard,
ae23c9
+
ae23c9
+    .bdrv_eject                         = cor_eject,
ae23c9
+    .bdrv_lock_medium                   = cor_lock_medium,
ae23c9
+
ae23c9
+    .bdrv_co_block_status               = bdrv_co_block_status_from_file,
ae23c9
+
ae23c9
+    .bdrv_recurse_is_first_non_filter   = cor_recurse_is_first_non_filter,
ae23c9
+
ae23c9
+    .has_variable_length                = true,
ae23c9
+    .is_filter                          = true,
ae23c9
+};
ae23c9
+
ae23c9
+static void bdrv_copy_on_read_init(void)
ae23c9
+{
ae23c9
+    bdrv_register(&bdrv_copy_on_read);
ae23c9
+}
ae23c9
+
ae23c9
+block_init(bdrv_copy_on_read_init);
ae23c9
diff --git a/qapi/block-core.json b/qapi/block-core.json
ae23c9
index 51eafdd..9e4f1ac 100644
ae23c9
--- a/qapi/block-core.json
ae23c9
+++ b/qapi/block-core.json
ae23c9
@@ -2506,11 +2506,12 @@
ae23c9
 # @vxhs: Since 2.10
ae23c9
 # @throttle: Since 2.11
ae23c9
 # @nvme: Since 2.12
ae23c9
+# @copy-on-read: Since 2.13
ae23c9
 #
ae23c9
 # Since: 2.9
ae23c9
 ##
ae23c9
 { 'enum': 'BlockdevDriver',
ae23c9
-  'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop',
ae23c9
+  'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop', 'copy-on-read',
ae23c9
             'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
ae23c9
             'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
ae23c9
             'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', 'qcow2', 'qed',
ae23c9
@@ -3541,6 +3542,7 @@
ae23c9
       'blkverify':  'BlockdevOptionsBlkverify',
ae23c9
       'bochs':      'BlockdevOptionsGenericFormat',
ae23c9
       'cloop':      'BlockdevOptionsGenericFormat',
ae23c9
+      'copy-on-read':'BlockdevOptionsGenericFormat',
ae23c9
       'dmg':        'BlockdevOptionsGenericFormat',
ae23c9
       'file':       'BlockdevOptionsFile',
ae23c9
       'ftp':        'BlockdevOptionsCurlFtp',
ae23c9
@@ -4068,6 +4070,7 @@
ae23c9
       'blkverify':      'BlockdevCreateNotSupported',
ae23c9
       'bochs':          'BlockdevCreateNotSupported',
ae23c9
       'cloop':          'BlockdevCreateNotSupported',
ae23c9
+      'copy-on-read':   'BlockdevCreateNotSupported',
ae23c9
       'dmg':            'BlockdevCreateNotSupported',
ae23c9
       'file':           'BlockdevCreateOptionsFile',
ae23c9
       'ftp':            'BlockdevCreateNotSupported',
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9