1
The following changes since commit ec397e90d21269037280633b6058d1f280e27667:
1
The following changes since commit 417296c8d8588f782018d01a317f88957e9786d6:
2
2
3
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210901-2' into staging (2021-09-01 08:33:02 +0100)
3
tests/qtest/netdev-socket: Raise connection timeout to 60 seconds (2023-02-09 11:23:53 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2021-09-01
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to ebd979c74e2b8a7275090475df36dde4ab858320:
9
for you to fetch changes up to acbc8aee5b09222dc6a5cb88306b67bcbe37e30b:
10
10
11
block/file-win32: add reopen handlers (2021-09-01 14:38:08 +0200)
11
iotests/detect-zeroes-registered-buf: add new test (2023-02-09 10:22:30 -0500)
12
13
14
**Note:** I’ve signed the pull request tag with my new GPG key, which I
15
have uploaded here:
16
17
https://xanclic.moe/A1FA40D098019CDF
18
19
Included in that key should be the signature I made with my old key
20
(F407DB0061D5CF40), and I hope that’s sufficient to establish a
21
reasonable level of trust.
22
23
(I’ve also tried uploading this key to several keyservers, but it
24
appears to me that keyservers are kind of a thing of the past now,
25
especially when it comes to uploading keys with signatures on them...)
26
12
27
----------------------------------------------------------------
13
----------------------------------------------------------------
28
Block patches:
14
Pull request
29
- Make the backup-top filter driver available for user-created block
15
30
nodes (i.e. via blockdev-add)
16
A few fixes that I've picked up.
31
- Allow running iotests with gdb or valgrind being attached to qemu
32
instances
33
- Fix the raw format driver's permissions: There is no metadata, so we
34
only need WRITE or RESIZE when the parent needs it
35
- Basic reopen implementation for win32 files (file-win32.c) so that
36
qemu-img commit can work
37
- uclibc/musl build fix for the FUSE export code
38
- Some iotests delinting
39
- block-hmp-cmds.c refactoring
40
17
41
----------------------------------------------------------------
18
----------------------------------------------------------------
42
Emanuele Giuseppe Esposito (15):
43
python: qemu: add timer parameter for qmp.accept socket
44
python: qemu: pass the wrapper field from QEMUQtestmachine to
45
QEMUMachine
46
docs/devel/testing: add debug section to the QEMU iotests chapter
47
qemu-iotests: add option to attach gdbserver
48
qemu-iotests: delay QMP socket timers
49
qemu_iotests: insert gdbserver command line as wrapper for qemu binary
50
qemu-iotests: add gdbserver option to script tests too
51
docs/devel/testing: add -gdb option to the debugging section of QEMU
52
iotests
53
qemu-iotests: extend the check script to prepare supporting valgrind
54
for python tests
55
qemu-iotests: extend QMP socket timeout when using valgrind
56
qemu-iotests: allow valgrind to read/delete the generated log file
57
qemu-iotests: insert valgrind command line as wrapper for qemu binary
58
docs/devel/testing: add -valgrind option to the debug section of QEMU
59
iotests
60
qemu-iotests: add option to show qemu binary logs on stdout
61
docs/devel/testing: add -p option to the debug section of QEMU iotests
62
19
63
Fabrice Fontaine (1):
20
Akihiko Odaki (1):
64
block/export/fuse.c: fix fuse-lseek on uclibc or musl
21
vhost-user-fs: Back up vqs before cleaning up vhost_dev
65
22
66
John Snow (3):
23
Emanuele Giuseppe Esposito (1):
67
python: Reduce strictness of pylint's duplicate-code check
24
virtio-blk: add missing AioContext lock
68
iotests: use with-statement for open() calls
69
iotests: use subprocess.DEVNULL instead of open("/dev/null")
70
25
71
Mao Zhongyi (1):
26
Stefan Hajnoczi (4):
72
block/monitor: Consolidate hmp_handle_error calls to reduce redundant
27
block: fix detect-zeroes= with BDRV_REQ_REGISTERED_BUF
73
code
28
qemu-io: use BdrvRequestFlags instead of int
29
qemu-io: add -r option to register I/O buffer
30
iotests/detect-zeroes-registered-buf: add new test
74
31
75
Stefan Hajnoczi (1):
32
block/io.c | 3 +
76
raw-format: drop WRITE and RESIZE child perms when possible
33
hw/block/virtio-blk.c | 5 +
77
34
hw/virtio/vhost-user-fs.c | 4 +-
78
Viktor Prutyanov (1):
35
qemu-io-cmds.c | 215 +++++++++++-------
79
block/file-win32: add reopen handlers
36
.../tests/detect-zeroes-registered-buf | 58 +++++
80
37
.../tests/detect-zeroes-registered-buf.out | 7 +
81
Vladimir Sementsov-Ogievskiy (34):
38
6 files changed, 210 insertions(+), 82 deletions(-)
82
block: introduce bdrv_replace_child_bs()
39
create mode 100755 tests/qemu-iotests/tests/detect-zeroes-registered-buf
83
block: introduce blk_replace_bs
40
create mode 100644 tests/qemu-iotests/tests/detect-zeroes-registered-buf.out
84
qdev-properties: PropertyInfo: add realized_set_allowed field
85
qdev: allow setting drive property for realized device
86
block: rename backup-top to copy-before-write
87
block-copy: move detecting fleecing scheme to block-copy
88
block/block-copy: introduce block_copy_set_copy_opts()
89
block/backup: set copy_range and compress after filter insertion
90
block/backup: move cluster size calculation to block-copy
91
block/copy-before-write: relax permission requirements when no parents
92
block/copy-before-write: drop extra bdrv_unref on failure path
93
block/copy-before-write: use file child instead of backing
94
block/copy-before-write: bdrv_cbw_append(): replace child at last
95
block/copy-before-write: introduce cbw_init()
96
block/copy-before-write: cbw_init(): rename variables
97
block/copy-before-write: cbw_init(): use file child after attaching
98
block/copy-before-write: bdrv_cbw_append(): drop unused compress arg
99
block/copy-before-write: cbw_init(): use options
100
block/copy-before-write: initialize block-copy bitmap
101
block/block-copy: make setting progress optional
102
block/copy-before-write: make public block driver
103
qapi: publish copy-before-write filter
104
python/qemu/machine.py: refactor _qemu_args()
105
python/qemu/machine: QEMUMachine: improve qmp() method
106
python:QEMUMachine: template typing for self returning methods
107
iotests/222: fix pylint and mypy complains
108
iotests/222: constantly use single quotes for strings
109
iotests: move 222 to tests/image-fleecing
110
iotests.py: hmp_qemu_io: support qdev
111
iotests/image-fleecing: proper source device
112
iotests/image-fleecing: rename tgt_node
113
iotests/image-fleecing: prepare for adding new test-case
114
iotests/image-fleecing: add test-case for copy-before-write filter
115
block/block-copy: block_copy_state_new(): drop extra arguments
116
117
docs/devel/testing.rst | 29 +++
118
qapi/block-core.json | 25 +-
119
block/{backup-top.h => copy-before-write.h} | 25 +-
120
include/block/block-copy.h | 6 +-
121
include/block/block.h | 2 +
122
include/hw/qdev-properties.h | 1 +
123
include/sysemu/block-backend.h | 1 +
124
block.c | 31 +++
125
block/backup-top.c | 253 -------------------
126
block/backup.c | 116 ++-------
127
block/block-backend.c | 8 +
128
block/block-copy.c | 136 ++++++++---
129
block/copy-before-write.c | 256 ++++++++++++++++++++
130
block/export/fuse.c | 3 +
131
block/file-win32.c | 101 +++++++-
132
block/monitor/block-hmp-cmds.c | 12 +-
133
block/raw-format.c | 21 +-
134
hw/core/qdev-properties-system.c | 43 +++-
135
hw/core/qdev-properties.c | 6 +-
136
.gitlab-ci.d/buildtest.yml | 6 +-
137
MAINTAINERS | 4 +-
138
block/meson.build | 2 +-
139
python/qemu/machine/machine.py | 56 +++--
140
python/qemu/machine/qtest.py | 9 +-
141
python/setup.cfg | 5 +
142
tests/qemu-iotests/222 | 159 ------------
143
tests/qemu-iotests/222.out | 67 -----
144
tests/qemu-iotests/283 | 35 ++-
145
tests/qemu-iotests/283.out | 4 +-
146
tests/qemu-iotests/297 | 2 +-
147
tests/qemu-iotests/check | 15 +-
148
tests/qemu-iotests/common.qemu | 7 +-
149
tests/qemu-iotests/common.rc | 8 +-
150
tests/qemu-iotests/iotests.py | 75 ++++--
151
tests/qemu-iotests/testenv.py | 23 +-
152
tests/qemu-iotests/tests/image-fleecing | 192 +++++++++++++++
153
tests/qemu-iotests/tests/image-fleecing.out | 139 +++++++++++
154
37 files changed, 1172 insertions(+), 711 deletions(-)
155
rename block/{backup-top.h => copy-before-write.h} (56%)
156
delete mode 100644 block/backup-top.c
157
create mode 100644 block/copy-before-write.c
158
delete mode 100755 tests/qemu-iotests/222
159
delete mode 100644 tests/qemu-iotests/222.out
160
create mode 100755 tests/qemu-iotests/tests/image-fleecing
161
create mode 100644 tests/qemu-iotests/tests/image-fleecing.out
162
41
163
--
42
--
164
2.31.1
43
2.39.1
165
166
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Also add a new _qmp_timer field to the QEMUMachine class.
4
5
Let's change the default socket timeout to None, so that if
6
a subclass needs to add a timer, it can be done by modifying
7
this private field.
8
9
At the same time, restore the timer to be 15 seconds in iotests.py, to
10
give an upper bound to the QMP monitor test command execution.
11
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: John Snow <jsnow@redhat.com>
15
Acked-by: John Snow <jsnow@redhat.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <20210809090114.64834-2-eesposit@redhat.com>
18
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
19
---
20
python/qemu/machine/machine.py | 7 +++++--
21
python/qemu/machine/qtest.py | 5 +++--
22
tests/qemu-iotests/iotests.py | 3 ++-
23
3 files changed, 10 insertions(+), 5 deletions(-)
24
25
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
26
index XXXXXXX..XXXXXXX 100644
27
--- a/python/qemu/machine/machine.py
28
+++ b/python/qemu/machine/machine.py
29
@@ -XXX,XX +XXX,XX @@ def __init__(self,
30
sock_dir: Optional[str] = None,
31
drain_console: bool = False,
32
console_log: Optional[str] = None,
33
- log_dir: Optional[str] = None):
34
+ log_dir: Optional[str] = None,
35
+ qmp_timer: Optional[float] = None):
36
'''
37
Initialize a QEMUMachine
38
39
@@ -XXX,XX +XXX,XX @@ def __init__(self,
40
@param drain_console: (optional) True to drain console socket to buffer
41
@param console_log: (optional) path to console log file
42
@param log_dir: where to create and keep log files
43
+ @param qmp_timer: (optional) default QMP socket timeout
44
@note: Qemu process is not started until launch() is used.
45
'''
46
# pylint: disable=too-many-arguments
47
@@ -XXX,XX +XXX,XX @@ def __init__(self,
48
self._binary = binary
49
self._args = list(args)
50
self._wrapper = wrapper
51
+ self._qmp_timer = qmp_timer
52
53
self._name = name or "qemu-%d" % os.getpid()
54
self._base_temp_dir = base_temp_dir
55
@@ -XXX,XX +XXX,XX @@ def _pre_launch(self) -> None:
56
57
def _post_launch(self) -> None:
58
if self._qmp_connection:
59
- self._qmp.accept()
60
+ self._qmp.accept(self._qmp_timer)
61
62
def _post_shutdown(self) -> None:
63
"""
64
diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py
65
index XXXXXXX..XXXXXXX 100644
66
--- a/python/qemu/machine/qtest.py
67
+++ b/python/qemu/machine/qtest.py
68
@@ -XXX,XX +XXX,XX @@ def __init__(self,
69
name: Optional[str] = None,
70
base_temp_dir: str = "/var/tmp",
71
socket_scm_helper: Optional[str] = None,
72
- sock_dir: Optional[str] = None):
73
+ sock_dir: Optional[str] = None,
74
+ qmp_timer: Optional[float] = None):
75
# pylint: disable=too-many-arguments
76
77
if name is None:
78
@@ -XXX,XX +XXX,XX @@ def __init__(self,
79
sock_dir = base_temp_dir
80
super().__init__(binary, args, name=name, base_temp_dir=base_temp_dir,
81
socket_scm_helper=socket_scm_helper,
82
- sock_dir=sock_dir)
83
+ sock_dir=sock_dir, qmp_timer=qmp_timer)
84
self._qtest: Optional[QEMUQtestProtocol] = None
85
self._qtest_path = os.path.join(sock_dir, name + "-qtest.sock")
86
87
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
88
index XXXXXXX..XXXXXXX 100644
89
--- a/tests/qemu-iotests/iotests.py
90
+++ b/tests/qemu-iotests/iotests.py
91
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
92
93
def __init__(self, path_suffix=''):
94
name = "qemu%s-%d" % (path_suffix, os.getpid())
95
+ timer = 15.0
96
super().__init__(qemu_prog, qemu_opts, name=name,
97
base_temp_dir=test_dir,
98
socket_scm_helper=socket_scm_helper,
99
- sock_dir=sock_dir)
100
+ sock_dir=sock_dir, qmp_timer=timer)
101
self._num_drives = 0
102
103
def add_object(self, opts):
104
--
105
2.31.1
106
107
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Pylint prior to 2.8.3 (We pin at >= 2.8.0) includes function and method
4
signatures as part of its duplicate checking algorithm. This check does
5
not listen to pragmas, so the only way to disable it is to turn it off
6
completely or increase the minimum duplicate lines so that it doesn't
7
trigger for functions with long, multi-line signatures.
8
9
When we decide to upgrade to pylint 2.8.3 or greater, we will be able to
10
use 'ignore-signatures = true' to the config instead.
11
12
I'd prefer not to keep us on the very bleeding edge of pylint if I can
13
help it -- 2.8.3 came out only three days ago at time of writing.
14
15
See: https://github.com/PyCQA/pylint/pull/4474
16
Signed-off-by: John Snow <jsnow@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Acked-by: John Snow <jsnow@redhat.com>
19
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Message-Id: <20210809090114.64834-3-eesposit@redhat.com>
21
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
22
---
23
python/setup.cfg | 5 +++++
24
1 file changed, 5 insertions(+)
25
26
diff --git a/python/setup.cfg b/python/setup.cfg
27
index XXXXXXX..XXXXXXX 100644
28
--- a/python/setup.cfg
29
+++ b/python/setup.cfg
30
@@ -XXX,XX +XXX,XX @@ good-names=i,
31
# Ignore imports when computing similarities.
32
ignore-imports=yes
33
34
+# Minimum lines number of a similarity.
35
+# TODO: Remove after we opt in to Pylint 2.8.3. See commit msg.
36
+min-similarity-lines=6
37
+
38
+
39
[isort]
40
force_grid_wrap=4
41
force_sort_within_sections=True
42
--
43
2.31.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Acked-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20210809090114.64834-4-eesposit@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
python/qemu/machine/qtest.py | 4 +++-
12
1 file changed, 3 insertions(+), 1 deletion(-)
13
14
diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/python/qemu/machine/qtest.py
17
+++ b/python/qemu/machine/qtest.py
18
@@ -XXX,XX +XXX,XX @@ class QEMUQtestMachine(QEMUMachine):
19
def __init__(self,
20
binary: str,
21
args: Sequence[str] = (),
22
+ wrapper: Sequence[str] = (),
23
name: Optional[str] = None,
24
base_temp_dir: str = "/var/tmp",
25
socket_scm_helper: Optional[str] = None,
26
@@ -XXX,XX +XXX,XX @@ def __init__(self,
27
name = "qemu-%d" % os.getpid()
28
if sock_dir is None:
29
sock_dir = base_temp_dir
30
- super().__init__(binary, args, name=name, base_temp_dir=base_temp_dir,
31
+ super().__init__(binary, args, wrapper=wrapper, name=name,
32
+ base_temp_dir=base_temp_dir,
33
socket_scm_helper=socket_scm_helper,
34
sock_dir=sock_dir, qmp_timer=qmp_timer)
35
self._qtest: Optional[QEMUQtestProtocol] = None
36
--
37
2.31.1
38
39
diff view generated by jsdifflib
1
From: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
1
From: Akihiko Odaki <akihiko.odaki@daynix.com>
2
2
3
Make 'qemu-img commit' work on Windows.
3
vhost_dev_cleanup() clears vhost_dev so back up its vqs member to free
4
the memory pointed by the member.
4
5
5
Command 'commit' requires reopening backing file in RW mode. So,
6
Fixes: 98fc1ada4c ("virtio: add vhost-user-fs base device")
6
add reopen prepare/commit/abort handlers and change dwShareMode
7
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
7
for CreateFile call in order to allow further read/write reopening.
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-Id: <20230130140225.77964-1-akihiko.odaki@daynix.com>
10
---
11
hw/virtio/vhost-user-fs.c | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
8
13
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/418
14
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
10
11
Suggested-by: Hanna Reitz <hreitz@redhat.com>
12
Signed-off-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
13
Tested-by: Helge Konetzka <hk@zapateado.de>
14
Message-Id: <20210825173625.19415-1-viktor.prutyanov@phystech.edu>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
17
block/file-win32.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
18
1 file changed, 100 insertions(+), 1 deletion(-)
19
20
diff --git a/block/file-win32.c b/block/file-win32.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/block/file-win32.c
16
--- a/hw/virtio/vhost-user-fs.c
23
+++ b/block/file-win32.c
17
+++ b/hw/virtio/vhost-user-fs.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
18
@@ -XXX,XX +XXX,XX @@ static void vuf_device_unrealize(DeviceState *dev)
25
QEMUWin32AIOState *aio;
19
{
26
} BDRVRawState;
20
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
27
21
VHostUserFS *fs = VHOST_USER_FS(dev);
28
+typedef struct BDRVRawReopenState {
22
+ struct vhost_virtqueue *vhost_vqs = fs->vhost_dev.vqs;
29
+ HANDLE hfile;
23
int i;
30
+} BDRVRawReopenState;
24
31
+
25
/* This will stop vhost backend if appropriate. */
32
/*
26
@@ -XXX,XX +XXX,XX @@ static void vuf_device_unrealize(DeviceState *dev)
33
* Read/writes the data to/from a given linear buffer.
34
*
35
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
36
}
27
}
37
28
g_free(fs->req_vqs);
38
s->hfile = CreateFile(filename, access_flags,
29
virtio_cleanup(vdev);
39
- FILE_SHARE_READ, NULL,
30
- g_free(fs->vhost_dev.vqs);
40
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
31
- fs->vhost_dev.vqs = NULL;
41
OPEN_EXISTING, overlapped, NULL);
32
+ g_free(vhost_vqs);
42
if (s->hfile == INVALID_HANDLE_VALUE) {
43
int err = GetLastError();
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
45
return raw_co_create(&options, errp);
46
}
33
}
47
34
48
+static int raw_reopen_prepare(BDRVReopenState *state,
35
static struct vhost_dev *vuf_get_vhost(VirtIODevice *vdev)
49
+ BlockReopenQueue *queue, Error **errp)
50
+{
51
+ BDRVRawState *s = state->bs->opaque;
52
+ BDRVRawReopenState *rs;
53
+ int access_flags;
54
+ DWORD overlapped;
55
+ int ret = 0;
56
+
57
+ if (s->type != FTYPE_FILE) {
58
+ error_setg(errp, "Can only reopen files");
59
+ return -EINVAL;
60
+ }
61
+
62
+ rs = g_new0(BDRVRawReopenState, 1);
63
+
64
+ /*
65
+ * We do not support changing any options (only flags). By leaving
66
+ * all options in state->options, we tell the generic reopen code
67
+ * that we do not support changing any of them, so it will verify
68
+ * that their values did not change.
69
+ */
70
+
71
+ raw_parse_flags(state->flags, s->aio != NULL, &access_flags, &overlapped);
72
+ rs->hfile = CreateFile(state->bs->filename, access_flags,
73
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
74
+ OPEN_EXISTING, overlapped, NULL);
75
+
76
+ if (rs->hfile == INVALID_HANDLE_VALUE) {
77
+ int err = GetLastError();
78
+
79
+ error_setg_win32(errp, err, "Could not reopen '%s'",
80
+ state->bs->filename);
81
+ if (err == ERROR_ACCESS_DENIED) {
82
+ ret = -EACCES;
83
+ } else {
84
+ ret = -EINVAL;
85
+ }
86
+ goto fail;
87
+ }
88
+
89
+ if (s->aio) {
90
+ ret = win32_aio_attach(s->aio, rs->hfile);
91
+ if (ret < 0) {
92
+ error_setg_errno(errp, -ret, "Could not enable AIO");
93
+ CloseHandle(rs->hfile);
94
+ goto fail;
95
+ }
96
+ }
97
+
98
+ state->opaque = rs;
99
+
100
+ return 0;
101
+
102
+fail:
103
+ g_free(rs);
104
+ state->opaque = NULL;
105
+
106
+ return ret;
107
+}
108
+
109
+static void raw_reopen_commit(BDRVReopenState *state)
110
+{
111
+ BDRVRawState *s = state->bs->opaque;
112
+ BDRVRawReopenState *rs = state->opaque;
113
+
114
+ assert(rs != NULL);
115
+
116
+ CloseHandle(s->hfile);
117
+ s->hfile = rs->hfile;
118
+
119
+ g_free(rs);
120
+ state->opaque = NULL;
121
+}
122
+
123
+static void raw_reopen_abort(BDRVReopenState *state)
124
+{
125
+ BDRVRawReopenState *rs = state->opaque;
126
+
127
+ if (!rs) {
128
+ return;
129
+ }
130
+
131
+ if (rs->hfile != INVALID_HANDLE_VALUE) {
132
+ CloseHandle(rs->hfile);
133
+ }
134
+
135
+ g_free(rs);
136
+ state->opaque = NULL;
137
+}
138
+
139
static QemuOptsList raw_create_opts = {
140
.name = "raw-create-opts",
141
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
142
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
143
.bdrv_co_create_opts = raw_co_create_opts,
144
.bdrv_has_zero_init = bdrv_has_zero_init_1,
145
146
+ .bdrv_reopen_prepare = raw_reopen_prepare,
147
+ .bdrv_reopen_commit = raw_reopen_commit,
148
+ .bdrv_reopen_abort = raw_reopen_abort,
149
+
150
.bdrv_aio_preadv = raw_aio_preadv,
151
.bdrv_aio_pwritev = raw_aio_pwritev,
152
.bdrv_aio_flush = raw_aio_flush,
153
--
36
--
154
2.31.1
37
2.39.1
155
156
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Introduce the "Debugging a test case" section, in preparation
3
virtio_blk_update_config() calls blk_get_geometry and blk_getlength,
4
to the additional flags that will be added in the next patches.
4
and both functions eventually end up calling bdrv_poll_co when not
5
running in a coroutine:
6
- blk_getlength is a co_wrapper_mixed function
7
- blk_get_geometry calls bdrv_get_geometry -> bdrv_nb_sectors, a
8
co_wrapper_mixed function too
9
10
Since we are not running in a coroutine, we need to take s->blk
11
AioContext lock, otherwise bdrv_poll_co will inevitably call
12
AIO_WAIT_WHILE and therefore try to un unlock() an AioContext lock
13
that was never acquired.
14
15
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=2167838
16
17
Steps to reproduce the issue: simply boot a VM with
18
-object '{"qom-type":"iothread","id":"iothread1"}' \
19
-blockdev '{"driver":"file","filename":"$QCOW2","aio":"native","node-name":"libvirt-1-storage","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \
20
-blockdev '{"node-name":"libvirt-1-format","read-only":false,"cache":{"direct":true,"no-flush":false},"driver":"qcow2","file":"libvirt-1-storage"}' \
21
-device virtio-blk-pci,iothread=iothread1,drive=libvirt-1-format,id=virtio-disk0,bootindex=1,write-cache=on
22
23
and observe that it will fail not manage to boot with "qemu_mutex_unlock_impl: Operation not permitted"
5
24
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
25
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Acked-by: Michael S. Tsirkin <mst@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
27
Tested-by: Lukáš Doktor <ldoktor@redhat.com>
9
Message-Id: <20210809090114.64834-5-eesposit@redhat.com>
28
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
29
Message-Id: <20230208111148.1040083-1-eesposit@redhat.com>
11
---
30
---
12
docs/devel/testing.rst | 8 ++++++++
31
hw/block/virtio-blk.c | 5 +++++
13
1 file changed, 8 insertions(+)
32
1 file changed, 5 insertions(+)
14
33
15
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
34
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
16
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/testing.rst
36
--- a/hw/block/virtio-blk.c
18
+++ b/docs/devel/testing.rst
37
+++ b/hw/block/virtio-blk.c
19
@@ -XXX,XX +XXX,XX @@ another application on the host may have locked the file, possibly leading to a
38
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
20
test failure. If using such devices are explicitly desired, consider adding
39
uint64_t capacity;
21
``locking=off`` option to disable image locking.
40
int64_t length;
22
41
int blk_size = conf->logical_block_size;
23
+Debugging a test case
42
+ AioContext *ctx;
24
+-----------------------
25
+The following options to the ``check`` script can be useful when debugging
26
+a failing test:
27
+
43
+
28
+* ``-d`` (debug) just increases the logging verbosity, showing
44
+ ctx = blk_get_aio_context(s->blk);
29
+ for example the QMP commands and answers.
45
+ aio_context_acquire(ctx);
30
+
46
31
Test case groups
47
blk_get_geometry(s->blk, &capacity);
32
----------------
48
memset(&blkcfg, 0, sizeof(blkcfg));
33
49
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
50
* per track (cylinder).
51
*/
52
length = blk_getlength(s->blk);
53
+ aio_context_release(ctx);
54
if (length > 0 && length / conf->heads / conf->secs % blk_size) {
55
blkcfg.geometry.sectors = conf->secs & ~s->sector_mask;
56
} else {
34
--
57
--
35
2.31.1
58
2.39.1
36
59
37
60
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Define -gdb flag and GDB_OPTIONS environment variable
4
to python tests to attach a gdbserver to each qemu instance.
5
This patch only adds and parses this flag, it does not yet add
6
the implementation for it.
7
8
if -gdb is not provided but $GDB_OPTIONS is set, ignore the
9
environment variable.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Message-Id: <20210809090114.64834-6-eesposit@redhat.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
17
tests/qemu-iotests/check | 6 +++++-
18
tests/qemu-iotests/iotests.py | 5 +++++
19
tests/qemu-iotests/testenv.py | 17 +++++++++++++++--
20
3 files changed, 25 insertions(+), 3 deletions(-)
21
22
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/check
25
+++ b/tests/qemu-iotests/check
26
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
27
help='pretty print output for make check')
28
29
p.add_argument('-d', dest='debug', action='store_true', help='debug')
30
+ p.add_argument('-gdb', action='store_true',
31
+ help="start gdbserver with $GDB_OPTIONS options \
32
+ ('localhost:12345' if $GDB_OPTIONS is empty)")
33
p.add_argument('-misalign', action='store_true',
34
help='misalign memory allocations')
35
p.add_argument('--color', choices=['on', 'off', 'auto'],
36
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
37
env = TestEnv(imgfmt=args.imgfmt, imgproto=args.imgproto,
38
aiomode=args.aiomode, cachemode=args.cachemode,
39
imgopts=args.imgopts, misalign=args.misalign,
40
- debug=args.debug, valgrind=args.valgrind)
41
+ debug=args.debug, valgrind=args.valgrind,
42
+ gdb=args.gdb)
43
44
if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
45
if not args.tests:
46
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
47
index XXXXXXX..XXXXXXX 100644
48
--- a/tests/qemu-iotests/iotests.py
49
+++ b/tests/qemu-iotests/iotests.py
50
@@ -XXX,XX +XXX,XX @@
51
qemu_prog = os.environ.get('QEMU_PROG', 'qemu')
52
qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')
53
54
+gdb_qemu_env = os.environ.get('GDB_OPTIONS')
55
+qemu_gdb = []
56
+if gdb_qemu_env:
57
+ qemu_gdb = ['gdbserver'] + gdb_qemu_env.strip().split(' ')
58
+
59
imgfmt = os.environ.get('IMGFMT', 'raw')
60
imgproto = os.environ.get('IMGPROTO', 'file')
61
output_dir = os.environ.get('OUTPUT_DIR', '.')
62
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/testenv.py
65
+++ b/tests/qemu-iotests/testenv.py
66
@@ -XXX,XX +XXX,XX @@
67
import glob
68
from typing import List, Dict, Any, Optional, ContextManager
69
70
+DEF_GDB_OPTIONS = 'localhost:12345'
71
72
def isxfile(path: str) -> bool:
73
return os.path.isfile(path) and os.access(path, os.X_OK)
74
@@ -XXX,XX +XXX,XX @@ class TestEnv(ContextManager['TestEnv']):
75
'QEMU_NBD_OPTIONS', 'IMGOPTS', 'IMGFMT', 'IMGPROTO',
76
'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU',
77
'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
78
- 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_']
79
+ 'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_',
80
+ 'GDB_OPTIONS']
81
82
def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
83
if self.debug:
84
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
85
imgopts: Optional[str] = None,
86
misalign: bool = False,
87
debug: bool = False,
88
- valgrind: bool = False) -> None:
89
+ valgrind: bool = False,
90
+ gdb: bool = False) -> None:
91
self.imgfmt = imgfmt
92
self.imgproto = imgproto
93
self.aiomode = aiomode
94
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
95
self.misalign = misalign
96
self.debug = debug
97
98
+ if gdb:
99
+ self.gdb_options = os.getenv('GDB_OPTIONS', DEF_GDB_OPTIONS)
100
+ if not self.gdb_options:
101
+ # cover the case 'export GDB_OPTIONS='
102
+ self.gdb_options = DEF_GDB_OPTIONS
103
+ elif 'GDB_OPTIONS' in os.environ:
104
+ # to not propagate it in prepare_subprocess()
105
+ del os.environ['GDB_OPTIONS']
106
+
107
if valgrind:
108
self.valgrind_qemu = 'y'
109
110
@@ -XXX,XX +XXX,XX @@ def print_env(self) -> None:
111
TEST_DIR -- {TEST_DIR}
112
SOCK_DIR -- {SOCK_DIR}
113
SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
114
+GDB_OPTIONS -- {GDB_OPTIONS}
115
"""
116
117
args = collections.defaultdict(str, self.get_env())
118
--
119
2.31.1
120
121
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Attaching gdbserver implies that the qmp socket
4
should wait indefinitely for an answer from QEMU.
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210809090114.64834-7-eesposit@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
tests/qemu-iotests/iotests.py | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/iotests.py
17
+++ b/tests/qemu-iotests/iotests.py
18
@@ -XXX,XX +XXX,XX @@ def __init__(self, seconds, errmsg="Timeout"):
19
self.seconds = seconds
20
self.errmsg = errmsg
21
def __enter__(self):
22
+ if qemu_gdb:
23
+ return self
24
signal.signal(signal.SIGALRM, self.timeout)
25
signal.setitimer(signal.ITIMER_REAL, self.seconds)
26
return self
27
def __exit__(self, exc_type, value, traceback):
28
+ if qemu_gdb:
29
+ return False
30
signal.setitimer(signal.ITIMER_REAL, 0)
31
return False
32
def timeout(self, signum, frame):
33
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
34
35
def __init__(self, path_suffix=''):
36
name = "qemu%s-%d" % (path_suffix, os.getpid())
37
- timer = 15.0
38
+ timer = 15.0 if not qemu_gdb else None
39
super().__init__(qemu_prog, qemu_opts, name=name,
40
base_temp_dir=test_dir,
41
socket_scm_helper=socket_scm_helper,
42
--
43
2.31.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-Id: <20210809090114.64834-8-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
tests/qemu-iotests/iotests.py | 3 ++-
10
1 file changed, 2 insertions(+), 1 deletion(-)
11
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/iotests.py
16
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
17
def __init__(self, path_suffix=''):
18
name = "qemu%s-%d" % (path_suffix, os.getpid())
19
timer = 15.0 if not qemu_gdb else None
20
- super().__init__(qemu_prog, qemu_opts, name=name,
21
+ super().__init__(qemu_prog, qemu_opts, wrapper=qemu_gdb,
22
+ name=name,
23
base_temp_dir=test_dir,
24
socket_scm_helper=socket_scm_helper,
25
sock_dir=sock_dir, qmp_timer=timer)
26
--
27
2.31.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Remove read timer in test script when GDB_OPTIONS are set,
4
so that the bash tests won't timeout while running gdb.
5
6
The only limitation here is that running a script with gdbserver
7
will make the test output mismatch with the expected
8
results, making the test fail.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Message-Id: <20210809090114.64834-9-eesposit@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/common.qemu | 7 ++++++-
15
tests/qemu-iotests/common.rc | 8 +++++++-
16
2 files changed, 13 insertions(+), 2 deletions(-)
17
18
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/qemu-iotests/common.qemu
21
+++ b/tests/qemu-iotests/common.qemu
22
@@ -XXX,XX +XXX,XX @@ _timed_wait_for()
23
timeout=yes
24
25
QEMU_STATUS[$h]=0
26
- while IFS= read -t ${QEMU_COMM_TIMEOUT} resp <&${QEMU_OUT[$h]}
27
+ read_timeout="-t ${QEMU_COMM_TIMEOUT}"
28
+ if [ -n "${GDB_OPTIONS}" ]; then
29
+ read_timeout=
30
+ fi
31
+
32
+ while IFS= read ${read_timeout} resp <&${QEMU_OUT[$h]}
33
do
34
if [ -n "$capture_events" ]; then
35
capture=0
36
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
37
index XXXXXXX..XXXXXXX 100644
38
--- a/tests/qemu-iotests/common.rc
39
+++ b/tests/qemu-iotests/common.rc
40
@@ -XXX,XX +XXX,XX @@ _qemu_wrapper()
41
if [ -n "${QEMU_NEED_PID}" ]; then
42
echo $BASHPID > "${QEMU_TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"
43
fi
44
+
45
+ GDB=""
46
+ if [ -n "${GDB_OPTIONS}" ]; then
47
+ GDB="gdbserver ${GDB_OPTIONS}"
48
+ fi
49
+
50
VALGRIND_QEMU="${VALGRIND_QEMU_VM}" _qemu_proc_exec "${VALGRIND_LOGFILE}" \
51
- "$QEMU_PROG" $QEMU_OPTIONS "$@"
52
+ $GDB "$QEMU_PROG" $QEMU_OPTIONS "$@"
53
)
54
RETVAL=$?
55
_qemu_proc_valgrind_log "${VALGRIND_LOGFILE}" $RETVAL
56
--
57
2.31.1
58
59
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-Id: <20210809090114.64834-10-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
docs/devel/testing.rst | 11 +++++++++++
10
1 file changed, 11 insertions(+)
11
12
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/testing.rst
15
+++ b/docs/devel/testing.rst
16
@@ -XXX,XX +XXX,XX @@ Debugging a test case
17
The following options to the ``check`` script can be useful when debugging
18
a failing test:
19
20
+* ``-gdb`` wraps every QEMU invocation in a ``gdbserver``, which waits for a
21
+ connection from a gdb client. The options given to ``gdbserver`` (e.g. the
22
+ address on which to listen for connections) are taken from the ``$GDB_OPTIONS``
23
+ environment variable. By default (if ``$GDB_OPTIONS`` is empty), it listens on
24
+ ``localhost:12345``.
25
+ It is possible to connect to it for example with
26
+ ``gdb -iex "target remote $addr"``, where ``$addr`` is the address
27
+ ``gdbserver`` listens on.
28
+ If the ``-gdb`` option is not used, ``$GDB_OPTIONS`` is ignored,
29
+ regardless of whether it is set or not.
30
+
31
* ``-d`` (debug) just increases the logging verbosity, showing
32
for example the QMP commands and answers.
33
34
--
35
2.31.1
36
37
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Currently, the check script only parses the option and sets the
4
VALGRIND_QEMU environmental variable to "y".
5
Add another local python variable that prepares the command line,
6
identical to the one provided in the test scripts.
7
8
Because the python script does not know in advance the valgrind
9
PID to assign to the log file name, use the "%p" flag in valgrind
10
log file name that automatically puts the process PID at runtime.
11
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <20210809090114.64834-11-eesposit@redhat.com>
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
---
18
tests/qemu-iotests/check | 7 ++++---
19
tests/qemu-iotests/iotests.py | 11 +++++++++++
20
tests/qemu-iotests/testenv.py | 1 +
21
3 files changed, 16 insertions(+), 3 deletions(-)
22
23
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
24
index XXXXXXX..XXXXXXX 100755
25
--- a/tests/qemu-iotests/check
26
+++ b/tests/qemu-iotests/check
27
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
28
p.add_argument('-gdb', action='store_true',
29
help="start gdbserver with $GDB_OPTIONS options \
30
('localhost:12345' if $GDB_OPTIONS is empty)")
31
+ p.add_argument('-valgrind', action='store_true',
32
+ help='use valgrind, sets VALGRIND_QEMU environment '
33
+ 'variable')
34
+
35
p.add_argument('-misalign', action='store_true',
36
help='misalign memory allocations')
37
p.add_argument('--color', choices=['on', 'off', 'auto'],
38
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
39
g_bash.add_argument('-o', dest='imgopts',
40
help='options to pass to qemu-img create/convert, '
41
'sets IMGOPTS environment variable')
42
- g_bash.add_argument('-valgrind', action='store_true',
43
- help='use valgrind, sets VALGRIND_QEMU environment '
44
- 'variable')
45
46
g_sel = p.add_argument_group('test selecting options',
47
'The following options specify test set '
48
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
49
index XXXXXXX..XXXXXXX 100644
50
--- a/tests/qemu-iotests/iotests.py
51
+++ b/tests/qemu-iotests/iotests.py
52
@@ -XXX,XX +XXX,XX @@
53
sys.stderr.write('Please run this test via the "check" script\n')
54
sys.exit(os.EX_USAGE)
55
56
+qemu_valgrind = []
57
+if os.environ.get('VALGRIND_QEMU') == "y" and \
58
+ os.environ.get('NO_VALGRIND') != "y":
59
+ valgrind_logfile = "--log-file=" + test_dir
60
+ # %p allows to put the valgrind process PID, since
61
+ # we don't know it a priori (subprocess.Popen is
62
+ # not yet invoked)
63
+ valgrind_logfile += "/%p.valgrind"
64
+
65
+ qemu_valgrind = ['valgrind', valgrind_logfile, '--error-exitcode=99']
66
+
67
socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
68
69
luks_default_secret_object = 'secret,id=keysec0,data=' + \
70
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tests/qemu-iotests/testenv.py
73
+++ b/tests/qemu-iotests/testenv.py
74
@@ -XXX,XX +XXX,XX @@ def print_env(self) -> None:
75
SOCK_DIR -- {SOCK_DIR}
76
SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
77
GDB_OPTIONS -- {GDB_OPTIONS}
78
+VALGRIND_QEMU -- {VALGRIND_QEMU}
79
"""
80
81
args = collections.defaultdict(str, self.get_env())
82
--
83
2.31.1
84
85
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
As with gdbserver, valgrind delays the test execution, so
4
the default QMP socket timeout and the generic class
5
Timeout in iotests.py timeouts too soon.
6
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210809090114.64834-12-eesposit@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
tests/qemu-iotests/iotests.py | 6 +++---
14
1 file changed, 3 insertions(+), 3 deletions(-)
15
16
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
17
index XXXXXXX..XXXXXXX 100644
18
--- a/tests/qemu-iotests/iotests.py
19
+++ b/tests/qemu-iotests/iotests.py
20
@@ -XXX,XX +XXX,XX @@ def __init__(self, seconds, errmsg="Timeout"):
21
self.seconds = seconds
22
self.errmsg = errmsg
23
def __enter__(self):
24
- if qemu_gdb:
25
+ if qemu_gdb or qemu_valgrind:
26
return self
27
signal.signal(signal.SIGALRM, self.timeout)
28
signal.setitimer(signal.ITIMER_REAL, self.seconds)
29
return self
30
def __exit__(self, exc_type, value, traceback):
31
- if qemu_gdb:
32
+ if qemu_gdb or qemu_valgrind:
33
return False
34
signal.setitimer(signal.ITIMER_REAL, 0)
35
return False
36
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
37
38
def __init__(self, path_suffix=''):
39
name = "qemu%s-%d" % (path_suffix, os.getpid())
40
- timer = 15.0 if not qemu_gdb else None
41
+ timer = 15.0 if not (qemu_gdb or qemu_valgrind) else None
42
super().__init__(qemu_prog, qemu_opts, wrapper=qemu_gdb,
43
name=name,
44
base_temp_dir=test_dir,
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
When using -valgrind on the script tests, it generates a log file
4
in $TEST_DIR that is either read (if valgrind finds problems) or
5
otherwise deleted. Provide the same exact behavior when using
6
-valgrind on the python tests.
7
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20210809090114.64834-13-eesposit@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 11 +++++++++++
15
1 file changed, 11 insertions(+)
16
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def __init__(self, path_suffix=''):
22
sock_dir=sock_dir, qmp_timer=timer)
23
self._num_drives = 0
24
25
+ def _post_shutdown(self) -> None:
26
+ super()._post_shutdown()
27
+ if not qemu_valgrind or not self._popen:
28
+ return
29
+ valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
30
+ if self.exitcode() == 99:
31
+ with open(valgrind_filename) as f:
32
+ print(f.read())
33
+ else:
34
+ os.remove(valgrind_filename)
35
+
36
def add_object(self, opts):
37
self._args.append('-object')
38
self._args.append(opts)
39
--
40
2.31.1
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
If -gdb and -valgrind are both defined, return an error.
4
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210809090114.64834-14-eesposit@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
tests/qemu-iotests/iotests.py | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/iotests.py
17
+++ b/tests/qemu-iotests/iotests.py
18
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
19
def __init__(self, path_suffix=''):
20
name = "qemu%s-%d" % (path_suffix, os.getpid())
21
timer = 15.0 if not (qemu_gdb or qemu_valgrind) else None
22
- super().__init__(qemu_prog, qemu_opts, wrapper=qemu_gdb,
23
+ if qemu_gdb and qemu_valgrind:
24
+ sys.stderr.write('gdb and valgrind are mutually exclusive\n')
25
+ sys.exit(1)
26
+ wrapper = qemu_gdb if qemu_gdb else qemu_valgrind
27
+ super().__init__(qemu_prog, qemu_opts, wrapper=wrapper,
28
name=name,
29
base_temp_dir=test_dir,
30
socket_scm_helper=socket_scm_helper,
31
--
32
2.31.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20210809090114.64834-15-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
docs/devel/testing.rst | 6 ++++++
10
1 file changed, 6 insertions(+)
11
12
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/testing.rst
15
+++ b/docs/devel/testing.rst
16
@@ -XXX,XX +XXX,XX @@ a failing test:
17
If the ``-gdb`` option is not used, ``$GDB_OPTIONS`` is ignored,
18
regardless of whether it is set or not.
19
20
+* ``-valgrind`` attaches a valgrind instance to QEMU. If it detects
21
+ warnings, it will print and save the log in
22
+ ``$TEST_DIR/<valgrind_pid>.valgrind``.
23
+ The final command line will be ``valgrind --log-file=$TEST_DIR/
24
+ <valgrind_pid>.valgrind --error-exitcode=99 $QEMU ...``
25
+
26
* ``-d`` (debug) just increases the logging verbosity, showing
27
for example the QMP commands and answers.
28
29
--
30
2.31.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Using the flag -p, allow the qemu binary to print to stdout.
4
5
Also create the common function _close_qemu_log_file() to
6
avoid accessing machine.py private fields directly and have
7
duplicate code.
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20210809090114.64834-16-eesposit@redhat.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
15
python/qemu/machine/machine.py | 9 ++++++---
16
tests/qemu-iotests/check | 4 +++-
17
tests/qemu-iotests/iotests.py | 8 ++++++++
18
tests/qemu-iotests/testenv.py | 9 +++++++--
19
4 files changed, 24 insertions(+), 6 deletions(-)
20
21
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
22
index XXXXXXX..XXXXXXX 100644
23
--- a/python/qemu/machine/machine.py
24
+++ b/python/qemu/machine/machine.py
25
@@ -XXX,XX +XXX,XX @@ def _post_launch(self) -> None:
26
if self._qmp_connection:
27
self._qmp.accept(self._qmp_timer)
28
29
+ def _close_qemu_log_file(self) -> None:
30
+ if self._qemu_log_file is not None:
31
+ self._qemu_log_file.close()
32
+ self._qemu_log_file = None
33
+
34
def _post_shutdown(self) -> None:
35
"""
36
Called to cleanup the VM instance after the process has exited.
37
@@ -XXX,XX +XXX,XX @@ def _post_shutdown(self) -> None:
38
self._qmp.close()
39
self._qmp_connection = None
40
41
- if self._qemu_log_file is not None:
42
- self._qemu_log_file.close()
43
- self._qemu_log_file = None
44
+ self._close_qemu_log_file()
45
46
self._load_io_log()
47
48
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
49
index XXXXXXX..XXXXXXX 100755
50
--- a/tests/qemu-iotests/check
51
+++ b/tests/qemu-iotests/check
52
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
53
help='pretty print output for make check')
54
55
p.add_argument('-d', dest='debug', action='store_true', help='debug')
56
+ p.add_argument('-p', dest='print', action='store_true',
57
+ help='redirects qemu\'s stdout and stderr to the test output')
58
p.add_argument('-gdb', action='store_true',
59
help="start gdbserver with $GDB_OPTIONS options \
60
('localhost:12345' if $GDB_OPTIONS is empty)")
61
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
62
aiomode=args.aiomode, cachemode=args.cachemode,
63
imgopts=args.imgopts, misalign=args.misalign,
64
debug=args.debug, valgrind=args.valgrind,
65
- gdb=args.gdb)
66
+ gdb=args.gdb, qprint=args.print)
67
68
if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
69
if not args.tests:
70
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tests/qemu-iotests/iotests.py
73
+++ b/tests/qemu-iotests/iotests.py
74
@@ -XXX,XX +XXX,XX @@
75
if gdb_qemu_env:
76
qemu_gdb = ['gdbserver'] + gdb_qemu_env.strip().split(' ')
77
78
+qemu_print = os.environ.get('PRINT_QEMU', False)
79
+
80
imgfmt = os.environ.get('IMGFMT', 'raw')
81
imgproto = os.environ.get('IMGPROTO', 'file')
82
output_dir = os.environ.get('OUTPUT_DIR', '.')
83
@@ -XXX,XX +XXX,XX @@ def _post_shutdown(self) -> None:
84
else:
85
os.remove(valgrind_filename)
86
87
+ def _pre_launch(self) -> None:
88
+ super()._pre_launch()
89
+ if qemu_print:
90
+ # set QEMU binary output to stdout
91
+ self._close_qemu_log_file()
92
+
93
def add_object(self, opts):
94
self._args.append('-object')
95
self._args.append(opts)
96
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
97
index XXXXXXX..XXXXXXX 100644
98
--- a/tests/qemu-iotests/testenv.py
99
+++ b/tests/qemu-iotests/testenv.py
100
@@ -XXX,XX +XXX,XX @@ class TestEnv(ContextManager['TestEnv']):
101
'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU',
102
'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
103
'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_',
104
- 'GDB_OPTIONS']
105
+ 'GDB_OPTIONS', 'PRINT_QEMU']
106
107
def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
108
if self.debug:
109
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
110
misalign: bool = False,
111
debug: bool = False,
112
valgrind: bool = False,
113
- gdb: bool = False) -> None:
114
+ gdb: bool = False,
115
+ qprint: bool = False) -> None:
116
self.imgfmt = imgfmt
117
self.imgproto = imgproto
118
self.aiomode = aiomode
119
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
120
self.misalign = misalign
121
self.debug = debug
122
123
+ if qprint:
124
+ self.print_qemu = 'y'
125
+
126
if gdb:
127
self.gdb_options = os.getenv('GDB_OPTIONS', DEF_GDB_OPTIONS)
128
if not self.gdb_options:
129
@@ -XXX,XX +XXX,XX @@ def print_env(self) -> None:
130
SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
131
GDB_OPTIONS -- {GDB_OPTIONS}
132
VALGRIND_QEMU -- {VALGRIND_QEMU}
133
+PRINT_QEMU_OUTPUT -- {PRINT_QEMU}
134
"""
135
136
args = collections.defaultdict(str, self.get_env())
137
--
138
2.31.1
139
140
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-Id: <20210809090114.64834-17-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
docs/devel/testing.rst | 4 ++++
10
1 file changed, 4 insertions(+)
11
12
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/testing.rst
15
+++ b/docs/devel/testing.rst
16
@@ -XXX,XX +XXX,XX @@ a failing test:
17
* ``-d`` (debug) just increases the logging verbosity, showing
18
for example the QMP commands and answers.
19
20
+* ``-p`` (print) redirects QEMU’s stdout and stderr to the test output,
21
+ instead of saving it into a log file in
22
+ ``$TEST_DIR/qemu-machine-<random_string>``.
23
+
24
Test case groups
25
----------------
26
27
--
28
2.31.1
29
30
diff view generated by jsdifflib
1
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
1
When a write request is converted into a write zeroes request by the
2
detect-zeroes= feature, it is no longer associated with an I/O buffer.
3
The BDRV_REQ_REGISTERED_BUF flag doesn't make sense without an I/O
4
buffer and must be cleared because bdrv_co_do_pwrite_zeroes() fails with
5
-EINVAL when it's set.
2
6
3
Include linux/fs.h to avoid the following build failure on uclibc or
7
Fiona Ebner <f.ebner@proxmox.com> bisected and diagnosed this QEMU 7.2
4
musl raised since version 6.0.0:
8
regression where writes containing zeroes to a blockdev with
9
discard=unmap,detect-zeroes=unmap fail.
5
10
6
../block/export/fuse.c: In function 'fuse_lseek':
11
Buglink: https://gitlab.com/qemu-project/qemu/-/issues/1404
7
../block/export/fuse.c:641:19: error: 'SEEK_HOLE' undeclared (first use in this function)
12
Fixes: e8b6535533be ("block: add BDRV_REQ_REGISTERED_BUF request flag")
8
641 | if (whence != SEEK_HOLE && whence != SEEK_DATA) {
13
Tested-by: Fiona Ebner <f.ebner@proxmox.com>
9
| ^~~~~~~~~
14
Cc: qemu-stable@nongnu.org
10
../block/export/fuse.c:641:19: note: each undeclared identifier is reported only once for each function it appears in
15
Reviewed-by: Eric Blake <eblake@redhat.com>
11
../block/export/fuse.c:641:42: error: 'SEEK_DATA' undeclared (first use in this function); did you mean 'SEEK_SET'?
16
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
12
641 | if (whence != SEEK_HOLE && whence != SEEK_DATA) {
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
| ^~~~~~~~~
18
Message-Id: <20230207203719.242926-2-stefanha@redhat.com>
14
| SEEK_SET
15
16
Fixes:
17
- http://autobuild.buildroot.org/results/33c90ebf04997f4d3557cfa66abc9cf9a3076137
18
19
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
20
Message-Id: <20210827220301.272887-1-fontaine.fabrice@gmail.com>
21
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
22
---
19
---
23
block/export/fuse.c | 3 +++
20
block/io.c | 3 +++
24
1 file changed, 3 insertions(+)
21
1 file changed, 3 insertions(+)
25
22
26
diff --git a/block/export/fuse.c b/block/export/fuse.c
23
diff --git a/block/io.c b/block/io.c
27
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
28
--- a/block/export/fuse.c
25
--- a/block/io.c
29
+++ b/block/export/fuse.c
26
+++ b/block/io.c
30
@@ -XXX,XX +XXX,XX @@
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
31
#include <fuse.h>
28
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
32
#include <fuse_lowlevel.h>
29
flags |= BDRV_REQ_MAY_UNMAP;
33
30
}
34
+#ifdef __linux__
31
+
35
+#include <linux/fs.h>
32
+ /* Can't use optimization hint with bufferless zero write */
36
+#endif
33
+ flags &= ~BDRV_REQ_REGISTERED_BUF;
37
34
}
38
/* Prevent overly long bounce buffer allocations */
35
39
#define FUSE_MAX_BOUNCE_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024))
36
if (ret < 0) {
40
--
37
--
41
2.31.1
38
2.39.1
42
43
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
1
The block layer APIs use BdrvRequestFlags while qemu-io code uses int.
2
Although the code compiles and runs fine, BdrvRequestFlags is clearer
3
because it differentiates between other types of flags like bdrv_open()
4
flags.
2
5
3
Signed-off-by: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
6
This is purely refactoring.
4
Message-Id: <20210802062507.347555-1-maozhongyi@cmss.chinamobile.com>
7
5
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20230207203719.242926-3-stefanha@redhat.com>
6
---
12
---
7
block/monitor/block-hmp-cmds.c | 12 ++++++------
13
qemu-io-cmds.c | 13 +++++++------
8
1 file changed, 6 insertions(+), 6 deletions(-)
14
1 file changed, 7 insertions(+), 6 deletions(-)
9
15
10
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
11
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
12
--- a/block/monitor/block-hmp-cmds.c
18
--- a/qemu-io-cmds.c
13
+++ b/block/monitor/block-hmp-cmds.c
19
+++ b/qemu-io-cmds.c
14
@@ -XXX,XX +XXX,XX @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
20
@@ -XXX,XX +XXX,XX @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
15
16
if (!filename) {
17
error_setg(&err, QERR_MISSING_PARAMETER, "target");
18
- hmp_handle_error(mon, err);
19
- return;
20
+ goto end;
21
}
22
qmp_drive_mirror(&mirror, &err);
23
+end:
24
hmp_handle_error(mon, err);
25
}
21
}
26
22
27
@@ -XXX,XX +XXX,XX @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
23
static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
28
24
- int64_t bytes, int flags, int64_t *total)
29
if (!filename) {
25
+ int64_t bytes, BdrvRequestFlags flags, int64_t *total)
30
error_setg(&err, QERR_MISSING_PARAMETER, "target");
26
{
31
- hmp_handle_error(mon, err);
27
int ret;
32
- return;
28
33
+ goto end;
29
@@ -XXX,XX +XXX,XX @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
34
}
35
36
qmp_drive_backup(&backup, &err);
37
+end:
38
hmp_handle_error(mon, err);
39
}
30
}
40
31
41
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
32
static int do_pwrite_zeroes(BlockBackend *blk, int64_t offset,
42
* will be taken internally. Today it's actually required.
33
- int64_t bytes, int flags, int64_t *total)
43
*/
34
+ int64_t bytes, BdrvRequestFlags flags,
44
error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
35
+ int64_t *total)
45
- hmp_handle_error(mon, err);
36
{
46
- return;
37
int ret = blk_pwrite_zeroes(blk, offset, bytes,
47
+ goto end;
38
flags | BDRV_REQ_ZERO_WRITE);
48
}
39
@@ -XXX,XX +XXX,XX @@ static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
49
50
mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
51
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
52
filename, false, NULL,
53
!!format, format,
54
true, mode, &err);
55
+end:
56
hmp_handle_error(mon, err);
57
}
40
}
58
41
42
static int do_aio_writev(BlockBackend *blk, QEMUIOVector *qiov,
43
- int64_t offset, int flags, int *total)
44
+ int64_t offset, BdrvRequestFlags flags, int *total)
45
{
46
int async_ret = NOT_DONE;
47
48
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
49
struct timespec t1, t2;
50
bool Cflag = false, qflag = false, bflag = false;
51
bool Pflag = false, zflag = false, cflag = false, sflag = false;
52
- int flags = 0;
53
+ BdrvRequestFlags flags = 0;
54
int c, cnt, ret;
55
char *buf = NULL;
56
int64_t offset;
57
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
58
{
59
struct timespec t1, t2;
60
bool Cflag = false, qflag = false;
61
- int flags = 0;
62
+ BdrvRequestFlags flags = 0;
63
int c, cnt, ret;
64
char *buf;
65
int64_t offset;
66
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
67
int nr_iov, c;
68
int pattern = 0xcd;
69
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
70
- int flags = 0;
71
+ BdrvRequestFlags flags = 0;
72
73
ctx->blk = blk;
74
while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
59
--
75
--
60
2.31.1
76
2.39.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
1
3
The following command-line fails due to a permissions conflict:
4
5
$ qemu-storage-daemon \
6
--blockdev driver=nvme,node-name=nvme0,device=0000:08:00.0,namespace=1 \
7
--blockdev driver=raw,node-name=l1-1,file=nvme0,offset=0,size=1073741824 \
8
--blockdev driver=raw,node-name=l1-2,file=nvme0,offset=1073741824,size=1073741824 \
9
--nbd-server addr.type=unix,addr.path=/tmp/nbd.sock,max-connections=2 \
10
--export type=nbd,id=nbd-l1-1,node-name=l1-1,name=l1-1,writable=on \
11
--export type=nbd,id=nbd-l1-2,node-name=l1-2,name=l1-2,writable=on
12
13
qemu-storage-daemon: --export type=nbd,id=nbd-l1-1,node-name=l1-1,name=l1-1,writable=on: Permission conflict on node 'nvme0': permissions 'resize' are both required by node 'l1-1' (uses node 'nvme0' as 'file' child) and unshared by node 'l1-2' (uses node 'nvme0' as 'file' child).
14
15
The problem is that block/raw-format.c relies on bdrv_default_perms() to
16
set permissions on the nvme node. The default permissions add RESIZE in
17
anticipation of a format driver like qcow2 that needs to grow the image
18
file. This fails because RESIZE is unshared, so we cannot get the RESIZE
19
permission.
20
21
Max Reitz pointed out that block/crypto.c already handles this case by
22
implementing a custom ->bdrv_child_perm() function that adjusts the
23
result of bdrv_default_perms().
24
25
This patch takes the same approach in block/raw-format.c so that RESIZE
26
is only required if it's actually necessary (e.g. the parent is qcow2).
27
28
Cc: Max Reitz <mreitz@redhat.com>
29
Cc: Kevin Wolf <kwolf@redhat.com>
30
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
31
Message-Id: <20210726122839.822900-1-stefanha@redhat.com>
32
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
33
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
34
---
35
block/raw-format.c | 21 ++++++++++++++++++++-
36
1 file changed, 20 insertions(+), 1 deletion(-)
37
38
diff --git a/block/raw-format.c b/block/raw-format.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/raw-format.c
41
+++ b/block/raw-format.c
42
@@ -XXX,XX +XXX,XX @@ static void raw_cancel_in_flight(BlockDriverState *bs)
43
bdrv_cancel_in_flight(bs->file->bs);
44
}
45
46
+static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
47
+ BdrvChildRole role,
48
+ BlockReopenQueue *reopen_queue,
49
+ uint64_t parent_perm, uint64_t parent_shared,
50
+ uint64_t *nperm, uint64_t *nshared)
51
+{
52
+ bdrv_default_perms(bs, c, role, reopen_queue, parent_perm,
53
+ parent_shared, nperm, nshared);
54
+
55
+ /*
56
+ * bdrv_default_perms() may add WRITE and/or RESIZE (see comment in
57
+ * bdrv_default_perms_for_storage() for an explanation) but we only need
58
+ * them if they are in parent_perm. Drop WRITE and RESIZE whenever possible
59
+ * to avoid permission conflicts.
60
+ */
61
+ *nperm &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
62
+ *nperm |= parent_perm & (BLK_PERM_WRITE | BLK_PERM_RESIZE);
63
+}
64
+
65
BlockDriver bdrv_raw = {
66
.format_name = "raw",
67
.instance_size = sizeof(BDRVRawState),
68
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
69
.bdrv_reopen_commit = &raw_reopen_commit,
70
.bdrv_reopen_abort = &raw_reopen_abort,
71
.bdrv_open = &raw_open,
72
- .bdrv_child_perm = bdrv_default_perms,
73
+ .bdrv_child_perm = raw_child_perm,
74
.bdrv_co_create_opts = &raw_co_create_opts,
75
.bdrv_co_preadv = &raw_co_preadv,
76
.bdrv_co_pwritev = &raw_co_pwritev,
77
--
78
2.31.1
79
80
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Silences a new pylint warning. The dangers of *not* doing this are
4
somewhat unclear; I believe the file object gets garbage collected
5
eventually, but possibly the way in which it happens is
6
non-deterministic. Maybe this is a valid warning, but if there are
7
consequences of not doing it, I am not aware of them at present.
8
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20210720173336.1876937-2-jsnow@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 7 ++++---
15
1 file changed, 4 insertions(+), 3 deletions(-)
16
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def notrun(reason):
22
# Each test in qemu-iotests has a number ("seq")
23
seq = os.path.basename(sys.argv[0])
24
25
- open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
26
+ with open('%s/%s.notrun' % (output_dir, seq), 'w') as outfile:
27
+ outfile.write(reason + '\n')
28
logger.warning("%s not run: %s", seq, reason)
29
sys.exit(0)
30
31
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
32
# Each test in qemu-iotests has a number ("seq")
33
seq = os.path.basename(sys.argv[0])
34
35
- open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
36
- ' [case not run] ' + reason + '\n')
37
+ with open('%s/%s.casenotrun' % (output_dir, seq), 'a') as outfile:
38
+ outfile.write(' [case not run] ' + reason + '\n')
39
40
def _verify_image_format(supported_fmts: Sequence[str] = (),
41
unsupported_fmts: Sequence[str] = ()) -> None:
42
--
43
2.31.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Avoids a warning from pylint not to use open() outside of a
4
with-statement, and is ... probably more portable anyway. Not that I
5
think we care too much about running tests *on* Windows, but... eh.
6
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20210720173336.1876937-3-jsnow@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 14 +++++++-------
13
1 file changed, 7 insertions(+), 7 deletions(-)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def qemu_io_silent(*args):
20
default_args = qemu_io_args
21
22
args = default_args + list(args)
23
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
24
- if exitcode < 0:
25
+ result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False)
26
+ if result.returncode < 0:
27
sys.stderr.write('qemu-io received signal %i: %s\n' %
28
- (-exitcode, ' '.join(args)))
29
- return exitcode
30
+ (-result.returncode, ' '.join(args)))
31
+ return result.returncode
32
33
def qemu_io_silent_check(*args):
34
'''Run qemu-io and return the true if subprocess returned 0'''
35
args = qemu_io_args + list(args)
36
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'),
37
- stderr=subprocess.STDOUT)
38
- return exitcode == 0
39
+ result = subprocess.run(args, stdout=subprocess.DEVNULL,
40
+ stderr=subprocess.STDOUT, check=False)
41
+ return result.returncode == 0
42
43
class QemuIoInteractive:
44
def __init__(self, *args):
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add function to transactionally replace bs inside BdrvChild.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210824083856.17408-2-vsementsov@virtuozzo.com>
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
---
10
include/block/block.h | 2 ++
11
block.c | 31 +++++++++++++++++++++++++++++++
12
2 files changed, 33 insertions(+)
13
14
diff --git a/include/block/block.h b/include/block/block.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block.h
17
+++ b/include/block/block.h
18
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
19
Error **errp);
20
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
21
Error **errp);
22
+int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
23
+ Error **errp);
24
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
25
int flags, Error **errp);
26
int bdrv_drop_filter(BlockDriverState *bs, Error **errp);
27
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
30
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ out:
32
return ret;
33
}
34
35
+/* Not for empty child */
36
+int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
37
+ Error **errp)
38
+{
39
+ int ret;
40
+ Transaction *tran = tran_new();
41
+ g_autoptr(GHashTable) found = NULL;
42
+ g_autoptr(GSList) refresh_list = NULL;
43
+ BlockDriverState *old_bs = child->bs;
44
+
45
+ bdrv_ref(old_bs);
46
+ bdrv_drained_begin(old_bs);
47
+ bdrv_drained_begin(new_bs);
48
+
49
+ bdrv_replace_child_tran(child, new_bs, tran);
50
+
51
+ found = g_hash_table_new(NULL, NULL);
52
+ refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
53
+ refresh_list = bdrv_topological_dfs(refresh_list, found, new_bs);
54
+
55
+ ret = bdrv_list_refresh_perms(refresh_list, NULL, tran, errp);
56
+
57
+ tran_finalize(tran, ret);
58
+
59
+ bdrv_drained_end(old_bs);
60
+ bdrv_drained_end(new_bs);
61
+ bdrv_unref(old_bs);
62
+
63
+ return ret;
64
+}
65
+
66
static void bdrv_delete(BlockDriverState *bs)
67
{
68
assert(bdrv_op_blocker_is_empty(bs));
69
--
70
2.31.1
71
72
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add function to change bs inside blk.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210824083856.17408-3-vsementsov@virtuozzo.com>
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
---
10
include/sysemu/block-backend.h | 1 +
11
block/block-backend.c | 8 ++++++++
12
2 files changed, 9 insertions(+)
13
14
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/sysemu/block-backend.h
17
+++ b/include/sysemu/block-backend.h
18
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public);
19
BlockDriverState *blk_bs(BlockBackend *blk);
20
void blk_remove_bs(BlockBackend *blk);
21
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp);
22
+int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp);
23
bool bdrv_has_blk(BlockDriverState *bs);
24
bool bdrv_is_root_node(BlockDriverState *bs);
25
int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
26
diff --git a/block/block-backend.c b/block/block-backend.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/block-backend.c
29
+++ b/block/block-backend.c
30
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
31
return 0;
32
}
33
34
+/*
35
+ * Change BlockDriverState associated with @blk.
36
+ */
37
+int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp)
38
+{
39
+ return bdrv_replace_child_bs(blk->root, new_bs, errp);
40
+}
41
+
42
/*
43
* Sets the permission bitmasks that the user of the BlockBackend needs.
44
*/
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add field, so property can declare support for setting the property
4
when device is realized. To be used in the following commit.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-4-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/hw/qdev-properties.h | 1 +
12
hw/core/qdev-properties.c | 6 +++---
13
2 files changed, 4 insertions(+), 3 deletions(-)
14
15
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/qdev-properties.h
18
+++ b/include/hw/qdev-properties.h
19
@@ -XXX,XX +XXX,XX @@ struct PropertyInfo {
20
const char *name;
21
const char *description;
22
const QEnumLookup *enum_table;
23
+ bool realized_set_allowed; /* allow setting property on realized device */
24
int (*print)(Object *obj, Property *prop, char *dest, size_t len);
25
void (*set_default_value)(ObjectProperty *op, const Property *prop);
26
ObjectProperty *(*create)(ObjectClass *oc, const char *name,
27
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/core/qdev-properties.c
30
+++ b/hw/core/qdev-properties.c
31
@@ -XXX,XX +XXX,XX @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
32
33
/* returns: true if property is allowed to be set, false otherwise */
34
static bool qdev_prop_allow_set(Object *obj, const char *name,
35
- Error **errp)
36
+ const PropertyInfo *info, Error **errp)
37
{
38
DeviceState *dev = DEVICE(obj);
39
40
- if (dev->realized) {
41
+ if (dev->realized && !info->realized_set_allowed) {
42
qdev_prop_set_after_realize(dev, name, errp);
43
return false;
44
}
45
@@ -XXX,XX +XXX,XX @@ static void field_prop_set(Object *obj, Visitor *v, const char *name,
46
{
47
Property *prop = opaque;
48
49
- if (!qdev_prop_allow_set(obj, name, errp)) {
50
+ if (!qdev_prop_allow_set(obj, name, prop->info, errp)) {
51
return;
52
}
53
54
--
55
2.31.1
56
57
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We need an ability to insert filters above top block node, attached to
4
block device. It can't be achieved with blockdev-reopen command. So, we
5
want do it with help of qom-set.
6
7
Intended usage:
8
9
Assume there is a node A that is attached to some guest device.
10
11
1. blockdev-add to create a filter node B that has A as its child.
12
13
2. qom-set to change the node attached to the guest device’s
14
BlockBackend from A to B.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-Id: <20210824083856.17408-5-vsementsov@virtuozzo.com>
19
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
20
---
21
hw/core/qdev-properties-system.c | 43 +++++++++++++++++++++++---------
22
1 file changed, 31 insertions(+), 12 deletions(-)
23
24
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/qdev-properties-system.c
27
+++ b/hw/core/qdev-properties-system.c
28
@@ -XXX,XX +XXX,XX @@
29
30
static bool check_prop_still_unset(Object *obj, const char *name,
31
const void *old_val, const char *new_val,
32
- Error **errp)
33
+ bool allow_override, Error **errp)
34
{
35
const GlobalProperty *prop = qdev_find_global_prop(obj, name);
36
37
- if (!old_val) {
38
+ if (!old_val || (!prop && allow_override)) {
39
return true;
40
}
41
42
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
43
BlockBackend *blk;
44
bool blk_created = false;
45
int ret;
46
+ BlockDriverState *bs;
47
+ AioContext *ctx;
48
49
if (!visit_type_str(v, name, &str, errp)) {
50
return;
51
}
52
53
- /*
54
- * TODO Should this really be an error? If no, the old value
55
- * needs to be released before we store the new one.
56
- */
57
- if (!check_prop_still_unset(obj, name, *ptr, str, errp)) {
58
+ if (!check_prop_still_unset(obj, name, *ptr, str, true, errp)) {
59
+ return;
60
+ }
61
+
62
+ if (*ptr) {
63
+ /* BlockBackend alread exists. So, we want to change attached node */
64
+ blk = *ptr;
65
+ ctx = blk_get_aio_context(blk);
66
+ bs = bdrv_lookup_bs(NULL, str, errp);
67
+ if (!bs) {
68
+ return;
69
+ }
70
+
71
+ if (ctx != bdrv_get_aio_context(bs)) {
72
+ error_setg(errp, "Different aio context is not supported for new "
73
+ "node");
74
+ }
75
+
76
+ aio_context_acquire(ctx);
77
+ blk_replace_bs(blk, bs, errp);
78
+ aio_context_release(ctx);
79
return;
80
}
81
82
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
83
84
blk = blk_by_name(str);
85
if (!blk) {
86
- BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
87
+ bs = bdrv_lookup_bs(NULL, str, NULL);
88
if (bs) {
89
/*
90
* If the device supports iothreads, it will make sure to move the
91
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
92
* aware of iothreads require their BlockBackends to be in the main
93
* AioContext.
94
*/
95
- AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
96
- qemu_get_aio_context();
97
+ ctx = iothread ? bdrv_get_aio_context(bs) : qemu_get_aio_context();
98
blk = blk_new(ctx, 0, BLK_PERM_ALL);
99
blk_created = true;
100
101
@@ -XXX,XX +XXX,XX @@ static void release_drive(Object *obj, const char *name, void *opaque)
102
const PropertyInfo qdev_prop_drive = {
103
.name = "str",
104
.description = "Node name or ID of a block device to use as a backend",
105
+ .realized_set_allowed = true,
106
.get = get_drive,
107
.set = set_drive,
108
.release = release_drive,
109
@@ -XXX,XX +XXX,XX @@ const PropertyInfo qdev_prop_drive = {
110
const PropertyInfo qdev_prop_drive_iothread = {
111
.name = "str",
112
.description = "Node name or ID of a block device to use as a backend",
113
+ .realized_set_allowed = true,
114
.get = get_drive,
115
.set = set_drive_iothread,
116
.release = release_drive,
117
@@ -XXX,XX +XXX,XX @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
118
* TODO Should this really be an error? If no, the old value
119
* needs to be released before we store the new one.
120
*/
121
- if (!check_prop_still_unset(obj, name, be->chr, str, errp)) {
122
+ if (!check_prop_still_unset(obj, name, be->chr, str, false, errp)) {
123
return;
124
}
125
126
@@ -XXX,XX +XXX,XX @@ static void set_netdev(Object *obj, Visitor *v, const char *name,
127
* TODO Should this really be an error? If no, the old value
128
* needs to be released before we store the new one.
129
*/
130
- if (!check_prop_still_unset(obj, name, ncs[i], str, errp)) {
131
+ if (!check_prop_still_unset(obj, name, ncs[i], str, false, errp)) {
132
goto out;
133
}
134
135
--
136
2.31.1
137
138
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to convert backup_top to full featured public filter,
4
which can be used in separate of backup job. Start from renaming from
5
"how it used" to "what it does".
6
7
While updating comments in 283 iotest, drop and rephrase also things
8
about ".active", as this field is now dropped, and filter doesn't have
9
"inactive" mode.
10
11
Note that this change may be considered as incompatible interface
12
change, as backup-top filter format name was visible through
13
query-block and query-named-block-nodes.
14
15
Still, consider the following reasoning:
16
17
1. backup-top was never documented, so if someone depends on format
18
name (for driver that can't be used other than it is automatically
19
inserted on backup job start), it's a kind of "undocumented feature
20
use". So I think we are free to change it.
21
22
2. There is a hope, that there is no such users: it's a lot more native
23
to give a good node-name to backup-top filter if need to operate
24
with it somehow, and don't touch format name.
25
26
3. Another "incompatible" change in further commit would be moving
27
copy-before-write filter from using backing child to file child. And
28
this is even more reasonable than renaming: for now all public
29
filters are file-child based.
30
31
So, it's a risky change, but risk seems small and good interface worth
32
it.
33
34
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
35
Reviewed-by: Max Reitz <mreitz@redhat.com>
36
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
37
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
38
---
39
block/{backup-top.h => copy-before-write.h} | 28 +++---
40
block/backup.c | 22 ++---
41
block/{backup-top.c => copy-before-write.c} | 100 ++++++++++----------
42
MAINTAINERS | 4 +-
43
block/meson.build | 2 +-
44
tests/qemu-iotests/283 | 35 +++----
45
tests/qemu-iotests/283.out | 4 +-
46
7 files changed, 95 insertions(+), 100 deletions(-)
47
rename block/{backup-top.h => copy-before-write.h} (56%)
48
rename block/{backup-top.c => copy-before-write.c} (62%)
49
50
diff --git a/block/backup-top.h b/block/copy-before-write.h
51
similarity index 56%
52
rename from block/backup-top.h
53
rename to block/copy-before-write.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/backup-top.h
56
+++ b/block/copy-before-write.h
57
@@ -XXX,XX +XXX,XX @@
58
/*
59
- * backup-top filter driver
60
+ * copy-before-write filter driver
61
*
62
* The driver performs Copy-Before-Write (CBW) operation: it is injected above
63
* some node, and before each write it copies _old_ data to the target node.
64
*
65
- * Copyright (c) 2018-2019 Virtuozzo International GmbH.
66
+ * Copyright (c) 2018-2021 Virtuozzo International GmbH.
67
*
68
* Author:
69
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
70
@@ -XXX,XX +XXX,XX @@
71
* along with this program. If not, see <http://www.gnu.org/licenses/>.
72
*/
73
74
-#ifndef BACKUP_TOP_H
75
-#define BACKUP_TOP_H
76
+#ifndef COPY_BEFORE_WRITE_H
77
+#define COPY_BEFORE_WRITE_H
78
79
#include "block/block_int.h"
80
#include "block/block-copy.h"
81
82
-BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
83
- BlockDriverState *target,
84
- const char *filter_node_name,
85
- uint64_t cluster_size,
86
- BackupPerf *perf,
87
- BdrvRequestFlags write_flags,
88
- BlockCopyState **bcs,
89
- Error **errp);
90
-void bdrv_backup_top_drop(BlockDriverState *bs);
91
+BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
92
+ BlockDriverState *target,
93
+ const char *filter_node_name,
94
+ uint64_t cluster_size,
95
+ BackupPerf *perf,
96
+ BdrvRequestFlags write_flags,
97
+ BlockCopyState **bcs,
98
+ Error **errp);
99
+void bdrv_cbw_drop(BlockDriverState *bs);
100
101
-#endif /* BACKUP_TOP_H */
102
+#endif /* COPY_BEFORE_WRITE_H */
103
diff --git a/block/backup.c b/block/backup.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/backup.c
106
+++ b/block/backup.c
107
@@ -XXX,XX +XXX,XX @@
108
#include "qemu/bitmap.h"
109
#include "qemu/error-report.h"
110
111
-#include "block/backup-top.h"
112
+#include "block/copy-before-write.h"
113
114
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
115
116
typedef struct BackupBlockJob {
117
BlockJob common;
118
- BlockDriverState *backup_top;
119
+ BlockDriverState *cbw;
120
BlockDriverState *source_bs;
121
BlockDriverState *target_bs;
122
123
@@ -XXX,XX +XXX,XX @@ static void backup_clean(Job *job)
124
{
125
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
126
block_job_remove_all_bdrv(&s->common);
127
- bdrv_backup_top_drop(s->backup_top);
128
+ bdrv_cbw_drop(s->cbw);
129
}
130
131
void backup_do_checkpoint(BlockJob *job, Error **errp)
132
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
133
BackupBlockJob *job = NULL;
134
int64_t cluster_size;
135
BdrvRequestFlags write_flags;
136
- BlockDriverState *backup_top = NULL;
137
+ BlockDriverState *cbw = NULL;
138
BlockCopyState *bcs = NULL;
139
140
assert(bs);
141
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
142
write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
143
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
144
145
- backup_top = bdrv_backup_top_append(bs, target, filter_node_name,
146
+ cbw = bdrv_cbw_append(bs, target, filter_node_name,
147
cluster_size, perf,
148
write_flags, &bcs, errp);
149
- if (!backup_top) {
150
+ if (!cbw) {
151
goto error;
152
}
153
154
/* job->len is fixed, so we can't allow resize */
155
- job = block_job_create(job_id, &backup_job_driver, txn, backup_top,
156
+ job = block_job_create(job_id, &backup_job_driver, txn, cbw,
157
0, BLK_PERM_ALL,
158
speed, creation_flags, cb, opaque, errp);
159
if (!job) {
160
goto error;
161
}
162
163
- job->backup_top = backup_top;
164
+ job->cbw = cbw;
165
job->source_bs = bs;
166
job->target_bs = target;
167
job->on_source_error = on_source_error;
168
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
169
block_copy_set_progress_meter(bcs, &job->common.job.progress);
170
block_copy_set_speed(bcs, speed);
171
172
- /* Required permissions are already taken by backup-top target */
173
+ /* Required permissions are taken by copy-before-write filter target */
174
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
175
&error_abort);
176
177
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
178
if (sync_bitmap) {
179
bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL);
180
}
181
- if (backup_top) {
182
- bdrv_backup_top_drop(backup_top);
183
+ if (cbw) {
184
+ bdrv_cbw_drop(cbw);
185
}
186
187
return NULL;
188
diff --git a/block/backup-top.c b/block/copy-before-write.c
189
similarity index 62%
190
rename from block/backup-top.c
191
rename to block/copy-before-write.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/block/backup-top.c
194
+++ b/block/copy-before-write.c
195
@@ -XXX,XX +XXX,XX @@
196
/*
197
- * backup-top filter driver
198
+ * copy-before-write filter driver
199
*
200
* The driver performs Copy-Before-Write (CBW) operation: it is injected above
201
* some node, and before each write it copies _old_ data to the target node.
202
*
203
- * Copyright (c) 2018-2019 Virtuozzo International GmbH.
204
+ * Copyright (c) 2018-2021 Virtuozzo International GmbH.
205
*
206
* Author:
207
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
208
@@ -XXX,XX +XXX,XX @@
209
#include "block/qdict.h"
210
#include "block/block-copy.h"
211
212
-#include "block/backup-top.h"
213
+#include "block/copy-before-write.h"
214
215
-typedef struct BDRVBackupTopState {
216
+typedef struct BDRVCopyBeforeWriteState {
217
BlockCopyState *bcs;
218
BdrvChild *target;
219
int64_t cluster_size;
220
-} BDRVBackupTopState;
221
+} BDRVCopyBeforeWriteState;
222
223
-static coroutine_fn int backup_top_co_preadv(
224
+static coroutine_fn int cbw_co_preadv(
225
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
226
QEMUIOVector *qiov, int flags)
227
{
228
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
229
}
230
231
-static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
232
- uint64_t bytes, BdrvRequestFlags flags)
233
+static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
234
+ uint64_t offset, uint64_t bytes, BdrvRequestFlags flags)
235
{
236
- BDRVBackupTopState *s = bs->opaque;
237
+ BDRVCopyBeforeWriteState *s = bs->opaque;
238
uint64_t off, end;
239
240
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
241
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
242
return block_copy(s->bcs, off, end - off, true);
243
}
244
245
-static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
246
- int64_t offset, int bytes)
247
+static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
248
+ int64_t offset, int bytes)
249
{
250
- int ret = backup_top_cbw(bs, offset, bytes, 0);
251
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
252
if (ret < 0) {
253
return ret;
254
}
255
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
256
return bdrv_co_pdiscard(bs->backing, offset, bytes);
257
}
258
259
-static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
260
+static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
261
int64_t offset, int bytes, BdrvRequestFlags flags)
262
{
263
- int ret = backup_top_cbw(bs, offset, bytes, flags);
264
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
265
if (ret < 0) {
266
return ret;
267
}
268
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
269
return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
270
}
271
272
-static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
273
- uint64_t offset,
274
- uint64_t bytes,
275
- QEMUIOVector *qiov, int flags)
276
+static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
277
+ uint64_t offset,
278
+ uint64_t bytes,
279
+ QEMUIOVector *qiov, int flags)
280
{
281
- int ret = backup_top_cbw(bs, offset, bytes, flags);
282
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
283
if (ret < 0) {
284
return ret;
285
}
286
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
287
return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
288
}
289
290
-static int coroutine_fn backup_top_co_flush(BlockDriverState *bs)
291
+static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
292
{
293
if (!bs->backing) {
294
return 0;
295
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_flush(BlockDriverState *bs)
296
return bdrv_co_flush(bs->backing->bs);
297
}
298
299
-static void backup_top_refresh_filename(BlockDriverState *bs)
300
+static void cbw_refresh_filename(BlockDriverState *bs)
301
{
302
if (bs->backing == NULL) {
303
/*
304
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
305
bs->backing->bs->filename);
306
}
307
308
-static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
309
- BdrvChildRole role,
310
- BlockReopenQueue *reopen_queue,
311
- uint64_t perm, uint64_t shared,
312
- uint64_t *nperm, uint64_t *nshared)
313
+static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
314
+ BdrvChildRole role,
315
+ BlockReopenQueue *reopen_queue,
316
+ uint64_t perm, uint64_t shared,
317
+ uint64_t *nperm, uint64_t *nshared)
318
{
319
if (!(role & BDRV_CHILD_FILTERED)) {
320
/*
321
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
322
}
323
}
324
325
-BlockDriver bdrv_backup_top_filter = {
326
- .format_name = "backup-top",
327
- .instance_size = sizeof(BDRVBackupTopState),
328
+BlockDriver bdrv_cbw_filter = {
329
+ .format_name = "copy-before-write",
330
+ .instance_size = sizeof(BDRVCopyBeforeWriteState),
331
332
- .bdrv_co_preadv = backup_top_co_preadv,
333
- .bdrv_co_pwritev = backup_top_co_pwritev,
334
- .bdrv_co_pwrite_zeroes = backup_top_co_pwrite_zeroes,
335
- .bdrv_co_pdiscard = backup_top_co_pdiscard,
336
- .bdrv_co_flush = backup_top_co_flush,
337
+ .bdrv_co_preadv = cbw_co_preadv,
338
+ .bdrv_co_pwritev = cbw_co_pwritev,
339
+ .bdrv_co_pwrite_zeroes = cbw_co_pwrite_zeroes,
340
+ .bdrv_co_pdiscard = cbw_co_pdiscard,
341
+ .bdrv_co_flush = cbw_co_flush,
342
343
- .bdrv_refresh_filename = backup_top_refresh_filename,
344
+ .bdrv_refresh_filename = cbw_refresh_filename,
345
346
- .bdrv_child_perm = backup_top_child_perm,
347
+ .bdrv_child_perm = cbw_child_perm,
348
349
.is_filter = true,
350
};
351
352
-BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
353
- BlockDriverState *target,
354
- const char *filter_node_name,
355
- uint64_t cluster_size,
356
- BackupPerf *perf,
357
- BdrvRequestFlags write_flags,
358
- BlockCopyState **bcs,
359
- Error **errp)
360
+BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
361
+ BlockDriverState *target,
362
+ const char *filter_node_name,
363
+ uint64_t cluster_size,
364
+ BackupPerf *perf,
365
+ BdrvRequestFlags write_flags,
366
+ BlockCopyState **bcs,
367
+ Error **errp)
368
{
369
ERRP_GUARD();
370
int ret;
371
- BDRVBackupTopState *state;
372
+ BDRVCopyBeforeWriteState *state;
373
BlockDriverState *top;
374
bool appended = false;
375
376
assert(source->total_sectors == target->total_sectors);
377
378
- top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name,
379
+ top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
380
BDRV_O_RDWR, errp);
381
if (!top) {
382
return NULL;
383
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
384
385
ret = bdrv_append(top, source, errp);
386
if (ret < 0) {
387
- error_prepend(errp, "Cannot append backup-top filter: ");
388
+ error_prepend(errp, "Cannot append copy-before-write filter: ");
389
goto fail;
390
}
391
appended = true;
392
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
393
394
fail:
395
if (appended) {
396
- bdrv_backup_top_drop(top);
397
+ bdrv_cbw_drop(top);
398
} else {
399
bdrv_unref(top);
400
}
401
@@ -XXX,XX +XXX,XX @@ fail:
402
return NULL;
403
}
404
405
-void bdrv_backup_top_drop(BlockDriverState *bs)
406
+void bdrv_cbw_drop(BlockDriverState *bs)
407
{
408
- BDRVBackupTopState *s = bs->opaque;
409
+ BDRVCopyBeforeWriteState *s = bs->opaque;
410
411
bdrv_drop_filter(bs, &error_abort);
412
413
diff --git a/MAINTAINERS b/MAINTAINERS
414
index XXXXXXX..XXXXXXX 100644
415
--- a/MAINTAINERS
416
+++ b/MAINTAINERS
417
@@ -XXX,XX +XXX,XX @@ F: block/mirror.c
418
F: qapi/job.json
419
F: block/block-copy.c
420
F: include/block/block-copy.c
421
-F: block/backup-top.h
422
-F: block/backup-top.c
423
+F: block/copy-before-write.h
424
+F: block/copy-before-write.c
425
F: include/block/aio_task.h
426
F: block/aio_task.c
427
F: util/qemu-co-shared-resource.c
428
diff --git a/block/meson.build b/block/meson.build
429
index XXXXXXX..XXXXXXX 100644
430
--- a/block/meson.build
431
+++ b/block/meson.build
432
@@ -XXX,XX +XXX,XX @@ block_ss.add(files(
433
'aio_task.c',
434
'amend.c',
435
'backup.c',
436
- 'backup-top.c',
437
+ 'copy-before-write.c',
438
'blkdebug.c',
439
'blklogwrites.c',
440
'blkverify.c',
441
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
442
index XXXXXXX..XXXXXXX 100755
443
--- a/tests/qemu-iotests/283
444
+++ b/tests/qemu-iotests/283
445
@@ -XXX,XX +XXX,XX @@
446
#!/usr/bin/env python3
447
# group: auto quick
448
#
449
-# Test for backup-top filter permission activation failure
450
+# Test for copy-before-write filter permission conflict
451
#
452
# Copyright (c) 2019 Virtuozzo International GmbH.
453
#
454
@@ -XXX,XX +XXX,XX @@ size = 1024 * 1024
455
""" Test description
456
457
When performing a backup, all writes on the source subtree must go through the
458
-backup-top filter so it can copy all data to the target before it is changed.
459
-backup-top filter is appended above source node, to achieve this thing, so all
460
-parents of source node are handled. A configuration with side parents of source
461
-sub-tree with write permission is unsupported (we'd have append several
462
-backup-top filter like nodes to handle such parents). The test create an
463
-example of such configuration and checks that a backup is then not allowed
464
-(blockdev-backup command should fail).
465
+copy-before-write filter so it can copy all data to the target before it is
466
+changed. copy-before-write filter is appended above source node, to achieve
467
+this thing, so all parents of source node are handled. A configuration with
468
+side parents of source sub-tree with write permission is unsupported (we'd have
469
+append several copy-before-write filter like nodes to handle such parents). The
470
+test create an example of such configuration and checks that a backup is then
471
+not allowed (blockdev-backup command should fail).
472
473
The configuration:
474
475
@@ -XXX,XX +XXX,XX @@ The configuration:
476
│ base │ ◀──────────── │ other │
477
└─────────────┘ └───────┘
478
479
-On activation (see .active field of backup-top state in block/backup-top.c),
480
-backup-top is going to unshare write permission on its source child. Write
481
-unsharing will be propagated to the "source->base" link and will conflict with
482
-other node write permission. So permission update will fail and backup job will
483
-not be started.
484
+copy-before-write filter wants to unshare write permission on its source child.
485
+Write unsharing will be propagated to the "source->base" link and will conflict
486
+with other node write permission. So permission update will fail and backup job
487
+will not be started.
488
489
Note, that the only thing which prevents backup of running on such
490
configuration is default permission propagation scheme. It may be altered by
491
@@ -XXX,XX +XXX,XX @@ vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
492
vm.shutdown()
493
494
495
-print('\n=== backup-top should be gone after job-finalize ===\n')
496
+print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
497
498
-# Check that the backup-top node is gone after job-finalize.
499
-#
500
-# During finalization, the node becomes inactive and can no longer
501
-# function. If it is still present, new parents might be attached, and
502
-# there would be no meaningful way to handle their I/O requests.
503
+# Check that the copy-before-write node is gone after job-finalize.
504
505
vm = iotests.VM()
506
vm.launch()
507
@@ -XXX,XX +XXX,XX @@ vm.qmp_log('blockdev-backup',
508
509
vm.event_wait('BLOCK_JOB_PENDING', 5.0)
510
511
-# The backup-top filter should still be present prior to finalization
512
+# The copy-before-write filter should still be present prior to finalization
513
assert vm.node_info('backup-filter') is not None
514
515
vm.qmp_log('job-finalize', id='backup')
516
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
517
index XXXXXXX..XXXXXXX 100644
518
--- a/tests/qemu-iotests/283.out
519
+++ b/tests/qemu-iotests/283.out
520
@@ -XXX,XX +XXX,XX @@
521
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
522
{"return": {}}
523
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
524
-{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
525
+{"error": {"class": "GenericError", "desc": "Cannot append copy-before-write filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
526
527
-=== backup-top should be gone after job-finalize ===
528
+=== copy-before-write filter should be gone after job-finalize ===
529
530
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "source"}}
531
{"return": {}}
532
--
533
2.31.1
534
535
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We want to simplify initialization interface of copy-before-write
4
filter as we are going to make it public. So, let's detect fleecing
5
scheme exactly in block-copy code, to not pass this information through
6
extra levels.
7
8
Why not just set BDRV_REQ_SERIALISING unconditionally: because we are
9
going to implement new more efficient fleecing scheme which will not
10
rely on backing feature.
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
Message-Id: <20210824083856.17408-7-vsementsov@virtuozzo.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
17
block/copy-before-write.h | 2 +-
18
include/block/block-copy.h | 3 +--
19
block/backup.c | 21 +--------------------
20
block/block-copy.c | 24 +++++++++++++++++++++---
21
block/copy-before-write.c | 4 ++--
22
5 files changed, 26 insertions(+), 28 deletions(-)
23
24
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/copy-before-write.h
27
+++ b/block/copy-before-write.h
28
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
29
const char *filter_node_name,
30
uint64_t cluster_size,
31
BackupPerf *perf,
32
- BdrvRequestFlags write_flags,
33
+ bool compress,
34
BlockCopyState **bcs,
35
Error **errp);
36
void bdrv_cbw_drop(BlockDriverState *bs);
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block-copy.h
40
+++ b/include/block/block-copy.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState BlockCopyCallState;
42
43
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
44
int64_t cluster_size, bool use_copy_range,
45
- BdrvRequestFlags write_flags,
46
- Error **errp);
47
+ bool compress, Error **errp);
48
49
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
50
51
diff --git a/block/backup.c b/block/backup.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/backup.c
54
+++ b/block/backup.c
55
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
56
int64_t len, target_len;
57
BackupBlockJob *job = NULL;
58
int64_t cluster_size;
59
- BdrvRequestFlags write_flags;
60
BlockDriverState *cbw = NULL;
61
BlockCopyState *bcs = NULL;
62
63
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
64
goto error;
65
}
66
67
- /*
68
- * If source is in backing chain of target assume that target is going to be
69
- * used for "image fleecing", i.e. it should represent a kind of snapshot of
70
- * source at backup-start point in time. And target is going to be read by
71
- * somebody (for example, used as NBD export) during backup job.
72
- *
73
- * In this case, we need to add BDRV_REQ_SERIALISING write flag to avoid
74
- * intersection of backup writes and third party reads from target,
75
- * otherwise reading from target we may occasionally read already updated by
76
- * guest data.
77
- *
78
- * For more information see commit f8d59dfb40bb and test
79
- * tests/qemu-iotests/222
80
- */
81
- write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
82
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
83
-
84
cbw = bdrv_cbw_append(bs, target, filter_node_name,
85
- cluster_size, perf,
86
- write_flags, &bcs, errp);
87
+ cluster_size, perf, compress, &bcs, errp);
88
if (!cbw) {
89
goto error;
90
}
91
diff --git a/block/block-copy.c b/block/block-copy.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/block/block-copy.c
94
+++ b/block/block-copy.c
95
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
96
97
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
98
int64_t cluster_size, bool use_copy_range,
99
- BdrvRequestFlags write_flags, Error **errp)
100
+ bool compress, Error **errp)
101
{
102
BlockCopyState *s;
103
BdrvDirtyBitmap *copy_bitmap;
104
+ bool is_fleecing;
105
106
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
107
errp);
108
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
109
}
110
bdrv_disable_dirty_bitmap(copy_bitmap);
111
112
+ /*
113
+ * If source is in backing chain of target assume that target is going to be
114
+ * used for "image fleecing", i.e. it should represent a kind of snapshot of
115
+ * source at backup-start point in time. And target is going to be read by
116
+ * somebody (for example, used as NBD export) during backup job.
117
+ *
118
+ * In this case, we need to add BDRV_REQ_SERIALISING write flag to avoid
119
+ * intersection of backup writes and third party reads from target,
120
+ * otherwise reading from target we may occasionally read already updated by
121
+ * guest data.
122
+ *
123
+ * For more information see commit f8d59dfb40bb and test
124
+ * tests/qemu-iotests/222
125
+ */
126
+ is_fleecing = bdrv_chain_contains(target->bs, source->bs);
127
+
128
s = g_new(BlockCopyState, 1);
129
*s = (BlockCopyState) {
130
.source = source,
131
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
132
.copy_bitmap = copy_bitmap,
133
.cluster_size = cluster_size,
134
.len = bdrv_dirty_bitmap_size(copy_bitmap),
135
- .write_flags = write_flags,
136
+ .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0) |
137
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
138
.mem = shres_create(BLOCK_COPY_MAX_MEM),
139
.max_transfer = QEMU_ALIGN_DOWN(
140
block_copy_max_transfer(source, target),
141
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
142
* behalf).
143
*/
144
s->method = COPY_READ_WRITE_CLUSTER;
145
- } else if (write_flags & BDRV_REQ_WRITE_COMPRESSED) {
146
+ } else if (compress) {
147
/* Compression supports only cluster-size writes and no copy-range. */
148
s->method = COPY_READ_WRITE_CLUSTER;
149
} else {
150
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block/copy-before-write.c
153
+++ b/block/copy-before-write.c
154
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
155
const char *filter_node_name,
156
uint64_t cluster_size,
157
BackupPerf *perf,
158
- BdrvRequestFlags write_flags,
159
+ bool compress,
160
BlockCopyState **bcs,
161
Error **errp)
162
{
163
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
164
state->cluster_size = cluster_size;
165
state->bcs = block_copy_state_new(top->backing, state->target,
166
cluster_size, perf->use_copy_range,
167
- write_flags, errp);
168
+ compress, errp);
169
if (!state->bcs) {
170
error_prepend(errp, "Cannot create block-copy-state: ");
171
goto fail;
172
--
173
2.31.1
174
175
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We'll need a possibility to set compress and use_copy_range options
4
after initialization of the state. So make corresponding part of
5
block_copy_state_new() separate and public.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210824083856.17408-8-vsementsov@virtuozzo.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
include/block/block-copy.h | 3 +++
13
block/block-copy.c | 49 ++++++++++++++++++++++----------------
14
2 files changed, 32 insertions(+), 20 deletions(-)
15
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
19
+++ b/include/block/block-copy.h
20
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
21
int64_t cluster_size, bool use_copy_range,
22
bool compress, Error **errp);
23
24
+/* Function should be called prior any actual copy request */
25
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
26
+ bool compress);
27
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
28
29
void block_copy_state_free(BlockCopyState *s);
30
diff --git a/block/block-copy.c b/block/block-copy.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/block-copy.c
33
+++ b/block/block-copy.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
35
target->bs->bl.max_transfer));
36
}
37
38
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
39
+ bool compress)
40
+{
41
+ /* Keep BDRV_REQ_SERIALISING set (or not set) in block_copy_state_new() */
42
+ s->write_flags = (s->write_flags & BDRV_REQ_SERIALISING) |
43
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
44
+
45
+ if (s->max_transfer < s->cluster_size) {
46
+ /*
47
+ * copy_range does not respect max_transfer. We don't want to bother
48
+ * with requests smaller than block-copy cluster size, so fallback to
49
+ * buffered copying (read and write respect max_transfer on their
50
+ * behalf).
51
+ */
52
+ s->method = COPY_READ_WRITE_CLUSTER;
53
+ } else if (compress) {
54
+ /* Compression supports only cluster-size writes and no copy-range. */
55
+ s->method = COPY_READ_WRITE_CLUSTER;
56
+ } else {
57
+ /*
58
+ * If copy range enabled, start with COPY_RANGE_SMALL, until first
59
+ * successful copy_range (look at block_copy_do_copy).
60
+ */
61
+ s->method = use_copy_range ? COPY_RANGE_SMALL : COPY_READ_WRITE;
62
+ }
63
+}
64
+
65
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
66
int64_t cluster_size, bool use_copy_range,
67
bool compress, Error **errp)
68
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
69
.copy_bitmap = copy_bitmap,
70
.cluster_size = cluster_size,
71
.len = bdrv_dirty_bitmap_size(copy_bitmap),
72
- .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0) |
73
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
74
+ .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0),
75
.mem = shres_create(BLOCK_COPY_MAX_MEM),
76
.max_transfer = QEMU_ALIGN_DOWN(
77
block_copy_max_transfer(source, target),
78
cluster_size),
79
};
80
81
- if (s->max_transfer < cluster_size) {
82
- /*
83
- * copy_range does not respect max_transfer. We don't want to bother
84
- * with requests smaller than block-copy cluster size, so fallback to
85
- * buffered copying (read and write respect max_transfer on their
86
- * behalf).
87
- */
88
- s->method = COPY_READ_WRITE_CLUSTER;
89
- } else if (compress) {
90
- /* Compression supports only cluster-size writes and no copy-range. */
91
- s->method = COPY_READ_WRITE_CLUSTER;
92
- } else {
93
- /*
94
- * If copy range enabled, start with COPY_RANGE_SMALL, until first
95
- * successful copy_range (look at block_copy_do_copy).
96
- */
97
- s->method = use_copy_range ? COPY_RANGE_SMALL : COPY_READ_WRITE;
98
- }
99
+ block_copy_set_copy_opts(s, use_copy_range, compress);
100
101
ratelimit_init(&s->rate_limit);
102
qemu_co_mutex_init(&s->lock);
103
--
104
2.31.1
105
106
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter, so it would be
4
initialized through options. Still we don't want to publish compress
5
and copy-range options, as
6
7
1. Modern way to enable compression is to use compress filter.
8
9
2. For copy-range it's unclean how to make proper interface:
10
- it's has experimental prefix for backup job anyway
11
- the whole BackupPerf structure doesn't make sense for the filter
12
So, let's just add copy-range possibility to the filter later if
13
needed.
14
15
Still, we are going to continue support for compression and
16
experimental copy-range in backup job. So, set these options after
17
filter creation.
18
19
Note, that we can drop "compress" argument of bdrv_cbw_append() now, as
20
well as "perf". The only reason not doing so is that now, when I
21
prepare this patch the big series around it is already reviewed and I
22
want to avoid extra rebase conflicts to simplify review of the
23
following version.
24
25
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
27
Message-Id: <20210824083856.17408-9-vsementsov@virtuozzo.com>
28
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
29
---
30
block/copy-before-write.h | 1 -
31
block/backup.c | 3 ++-
32
block/copy-before-write.c | 4 +---
33
3 files changed, 3 insertions(+), 5 deletions(-)
34
35
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/copy-before-write.h
38
+++ b/block/copy-before-write.h
39
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
40
BlockDriverState *target,
41
const char *filter_node_name,
42
uint64_t cluster_size,
43
- BackupPerf *perf,
44
bool compress,
45
BlockCopyState **bcs,
46
Error **errp);
47
diff --git a/block/backup.c b/block/backup.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/backup.c
50
+++ b/block/backup.c
51
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
52
}
53
54
cbw = bdrv_cbw_append(bs, target, filter_node_name,
55
- cluster_size, perf, compress, &bcs, errp);
56
+ cluster_size, false, &bcs, errp);
57
if (!cbw) {
58
goto error;
59
}
60
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
61
job->len = len;
62
job->perf = *perf;
63
64
+ block_copy_set_copy_opts(bcs, perf->use_copy_range, compress);
65
block_copy_set_progress_meter(bcs, &job->common.job.progress);
66
block_copy_set_speed(bcs, speed);
67
68
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/copy-before-write.c
71
+++ b/block/copy-before-write.c
72
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
73
BlockDriverState *target,
74
const char *filter_node_name,
75
uint64_t cluster_size,
76
- BackupPerf *perf,
77
bool compress,
78
BlockCopyState **bcs,
79
Error **errp)
80
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
81
82
state->cluster_size = cluster_size;
83
state->bcs = block_copy_state_new(top->backing, state->target,
84
- cluster_size, perf->use_copy_range,
85
- compress, errp);
86
+ cluster_size, false, compress, errp);
87
if (!state->bcs) {
88
error_prepend(errp, "Cannot create block-copy-state: ");
89
goto fail;
90
--
91
2.31.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
The main consumer of cluster-size is block-copy. Let's calculate it
4
here instead of passing through backup-top.
5
6
We are going to publish copy-before-write filter soon, so it will be
7
created through options. But we don't want for now to make explicit
8
option for cluster-size, let's continue to calculate it automatically.
9
So, now is the time to get rid of cluster_size argument for
10
bdrv_cbw_append().
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Message-Id: <20210824083856.17408-10-vsementsov@virtuozzo.com>
15
[hreitz: Add qemu/error-report.h include to block/block-copy.c]
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
---
18
block/copy-before-write.h | 1 -
19
include/block/block-copy.h | 5 +--
20
block/backup.c | 62 ++++++--------------------------------
21
block/block-copy.c | 52 +++++++++++++++++++++++++++++++-
22
block/copy-before-write.c | 10 +++---
23
5 files changed, 67 insertions(+), 63 deletions(-)
24
25
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.h
28
+++ b/block/copy-before-write.h
29
@@ -XXX,XX +XXX,XX @@
30
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
31
BlockDriverState *target,
32
const char *filter_node_name,
33
- uint64_t cluster_size,
34
bool compress,
35
BlockCopyState **bcs,
36
Error **errp);
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block-copy.h
40
+++ b/include/block/block-copy.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
42
typedef struct BlockCopyCallState BlockCopyCallState;
43
44
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
45
- int64_t cluster_size, bool use_copy_range,
46
- bool compress, Error **errp);
47
+ bool use_copy_range, bool compress,
48
+ Error **errp);
49
50
/* Function should be called prior any actual copy request */
51
void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
52
@@ -XXX,XX +XXX,XX @@ void block_copy_kick(BlockCopyCallState *call_state);
53
void block_copy_call_cancel(BlockCopyCallState *call_state);
54
55
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
56
+int64_t block_copy_cluster_size(BlockCopyState *s);
57
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
58
59
#endif /* BLOCK_COPY_H */
60
diff --git a/block/backup.c b/block/backup.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/backup.c
63
+++ b/block/backup.c
64
@@ -XXX,XX +XXX,XX @@
65
66
#include "block/copy-before-write.h"
67
68
-#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
69
-
70
typedef struct BackupBlockJob {
71
BlockJob common;
72
BlockDriverState *cbw;
73
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver backup_job_driver = {
74
.set_speed = backup_set_speed,
75
};
76
77
-static int64_t backup_calculate_cluster_size(BlockDriverState *target,
78
- Error **errp)
79
-{
80
- int ret;
81
- BlockDriverInfo bdi;
82
- bool target_does_cow = bdrv_backing_chain_next(target);
83
-
84
- /*
85
- * If there is no backing file on the target, we cannot rely on COW if our
86
- * backup cluster size is smaller than the target cluster size. Even for
87
- * targets with a backing file, try to avoid COW if possible.
88
- */
89
- ret = bdrv_get_info(target, &bdi);
90
- if (ret == -ENOTSUP && !target_does_cow) {
91
- /* Cluster size is not defined */
92
- warn_report("The target block device doesn't provide "
93
- "information about the block size and it doesn't have a "
94
- "backing file. The default block size of %u bytes is "
95
- "used. If the actual block size of the target exceeds "
96
- "this default, the backup may be unusable",
97
- BACKUP_CLUSTER_SIZE_DEFAULT);
98
- return BACKUP_CLUSTER_SIZE_DEFAULT;
99
- } else if (ret < 0 && !target_does_cow) {
100
- error_setg_errno(errp, -ret,
101
- "Couldn't determine the cluster size of the target image, "
102
- "which has no backing file");
103
- error_append_hint(errp,
104
- "Aborting, since this may create an unusable destination image\n");
105
- return ret;
106
- } else if (ret < 0 && target_does_cow) {
107
- /* Not fatal; just trudge on ahead. */
108
- return BACKUP_CLUSTER_SIZE_DEFAULT;
109
- }
110
-
111
- return MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
112
-}
113
-
114
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
115
BlockDriverState *target, int64_t speed,
116
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
117
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
118
return NULL;
119
}
120
121
- cluster_size = backup_calculate_cluster_size(target, errp);
122
- if (cluster_size < 0) {
123
- goto error;
124
- }
125
-
126
if (perf->max_workers < 1) {
127
error_setg(errp, "max-workers must be greater than zero");
128
return NULL;
129
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
130
return NULL;
131
}
132
133
- if (perf->max_chunk && perf->max_chunk < cluster_size) {
134
- error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
135
- "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
136
- return NULL;
137
- }
138
-
139
-
140
if (sync_bitmap) {
141
/* If we need to write to this bitmap, check that we can: */
142
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
143
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
144
goto error;
145
}
146
147
- cbw = bdrv_cbw_append(bs, target, filter_node_name,
148
- cluster_size, false, &bcs, errp);
149
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
150
if (!cbw) {
151
goto error;
152
}
153
154
+ cluster_size = block_copy_cluster_size(bcs);
155
+
156
+ if (perf->max_chunk && perf->max_chunk < cluster_size) {
157
+ error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
158
+ "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
159
+ goto error;
160
+ }
161
+
162
/* job->len is fixed, so we can't allow resize */
163
job = block_job_create(job_id, &backup_job_driver, txn, cbw,
164
0, BLK_PERM_ALL,
165
diff --git a/block/block-copy.c b/block/block-copy.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/block-copy.c
168
+++ b/block/block-copy.c
169
@@ -XXX,XX +XXX,XX @@
170
#include "qemu/units.h"
171
#include "qemu/coroutine.h"
172
#include "block/aio_task.h"
173
+#include "qemu/error-report.h"
174
175
#define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB)
176
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
177
#define BLOCK_COPY_MAX_MEM (128 * MiB)
178
#define BLOCK_COPY_MAX_WORKERS 64
179
#define BLOCK_COPY_SLICE_TIME 100000000ULL /* ns */
180
+#define BLOCK_COPY_CLUSTER_SIZE_DEFAULT (1 << 16)
181
182
typedef enum {
183
COPY_READ_WRITE_CLUSTER,
184
@@ -XXX,XX +XXX,XX @@ void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
185
}
186
}
187
188
+static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
189
+ Error **errp)
190
+{
191
+ int ret;
192
+ BlockDriverInfo bdi;
193
+ bool target_does_cow = bdrv_backing_chain_next(target);
194
+
195
+ /*
196
+ * If there is no backing file on the target, we cannot rely on COW if our
197
+ * backup cluster size is smaller than the target cluster size. Even for
198
+ * targets with a backing file, try to avoid COW if possible.
199
+ */
200
+ ret = bdrv_get_info(target, &bdi);
201
+ if (ret == -ENOTSUP && !target_does_cow) {
202
+ /* Cluster size is not defined */
203
+ warn_report("The target block device doesn't provide "
204
+ "information about the block size and it doesn't have a "
205
+ "backing file. The default block size of %u bytes is "
206
+ "used. If the actual block size of the target exceeds "
207
+ "this default, the backup may be unusable",
208
+ BLOCK_COPY_CLUSTER_SIZE_DEFAULT);
209
+ return BLOCK_COPY_CLUSTER_SIZE_DEFAULT;
210
+ } else if (ret < 0 && !target_does_cow) {
211
+ error_setg_errno(errp, -ret,
212
+ "Couldn't determine the cluster size of the target image, "
213
+ "which has no backing file");
214
+ error_append_hint(errp,
215
+ "Aborting, since this may create an unusable destination image\n");
216
+ return ret;
217
+ } else if (ret < 0 && target_does_cow) {
218
+ /* Not fatal; just trudge on ahead. */
219
+ return BLOCK_COPY_CLUSTER_SIZE_DEFAULT;
220
+ }
221
+
222
+ return MAX(BLOCK_COPY_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
223
+}
224
+
225
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
226
- int64_t cluster_size, bool use_copy_range,
227
+ bool use_copy_range,
228
bool compress, Error **errp)
229
{
230
BlockCopyState *s;
231
+ int64_t cluster_size;
232
BdrvDirtyBitmap *copy_bitmap;
233
bool is_fleecing;
234
235
+ cluster_size = block_copy_calculate_cluster_size(target->bs, errp);
236
+ if (cluster_size < 0) {
237
+ return NULL;
238
+ }
239
+
240
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
241
errp);
242
if (!copy_bitmap) {
243
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
244
return s->copy_bitmap;
245
}
246
247
+int64_t block_copy_cluster_size(BlockCopyState *s)
248
+{
249
+ return s->cluster_size;
250
+}
251
+
252
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip)
253
{
254
qatomic_set(&s->skip_unallocated, skip);
255
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/block/copy-before-write.c
258
+++ b/block/copy-before-write.c
259
@@ -XXX,XX +XXX,XX @@
260
typedef struct BDRVCopyBeforeWriteState {
261
BlockCopyState *bcs;
262
BdrvChild *target;
263
- int64_t cluster_size;
264
} BDRVCopyBeforeWriteState;
265
266
static coroutine_fn int cbw_co_preadv(
267
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
268
{
269
BDRVCopyBeforeWriteState *s = bs->opaque;
270
uint64_t off, end;
271
+ int64_t cluster_size = block_copy_cluster_size(s->bcs);
272
273
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
274
return 0;
275
}
276
277
- off = QEMU_ALIGN_DOWN(offset, s->cluster_size);
278
- end = QEMU_ALIGN_UP(offset + bytes, s->cluster_size);
279
+ off = QEMU_ALIGN_DOWN(offset, cluster_size);
280
+ end = QEMU_ALIGN_UP(offset + bytes, cluster_size);
281
282
return block_copy(s->bcs, off, end - off, true);
283
}
284
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_cbw_filter = {
285
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
286
BlockDriverState *target,
287
const char *filter_node_name,
288
- uint64_t cluster_size,
289
bool compress,
290
BlockCopyState **bcs,
291
Error **errp)
292
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
293
}
294
appended = true;
295
296
- state->cluster_size = cluster_size;
297
state->bcs = block_copy_state_new(top->backing, state->target,
298
- cluster_size, false, compress, errp);
299
+ false, compress, errp);
300
if (!state->bcs) {
301
error_prepend(errp, "Cannot create block-copy-state: ");
302
goto fail;
303
--
304
2.31.1
305
306
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter. So, user should be
4
able to create it with blockdev-add first, specifying both filtered and
5
target children. And then do blockdev-reopen, to actually insert the
6
filter where needed.
7
8
Currently, filter unshares write permission unconditionally on source
9
node. It's good, but it will not allow to do blockdev-add. So, let's
10
relax restrictions when filter doesn't have any parent.
11
12
Test output is modified, as now permission conflict happens only when
13
job creates a blk parent for filter node.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <20210824083856.17408-11-vsementsov@virtuozzo.com>
18
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
19
---
20
block/copy-before-write.c | 8 +++++---
21
tests/qemu-iotests/283.out | 2 +-
22
2 files changed, 6 insertions(+), 4 deletions(-)
23
24
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/copy-before-write.c
27
+++ b/block/copy-before-write.c
28
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
29
bdrv_default_perms(bs, c, role, reopen_queue,
30
perm, shared, nperm, nshared);
31
32
- if (perm & BLK_PERM_WRITE) {
33
- *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
34
+ if (!QLIST_EMPTY(&bs->parents)) {
35
+ if (perm & BLK_PERM_WRITE) {
36
+ *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
37
+ }
38
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
39
}
40
- *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
41
}
42
}
43
44
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tests/qemu-iotests/283.out
47
+++ b/tests/qemu-iotests/283.out
48
@@ -XXX,XX +XXX,XX @@
49
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
50
{"return": {}}
51
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
52
-{"error": {"class": "GenericError", "desc": "Cannot append copy-before-write filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
53
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
54
55
=== copy-before-write filter should be gone after job-finalize ===
56
57
--
58
2.31.1
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
bdrv_attach_child() do bdrv_unref() on failure, so we shouldn't do it
4
by hand here.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-12-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
block/copy-before-write.c | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/copy-before-write.c
17
+++ b/block/copy-before-write.c
18
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
19
state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
20
BDRV_CHILD_DATA, errp);
21
if (!state->target) {
22
- bdrv_unref(target);
23
bdrv_unref(top);
24
return NULL;
25
}
26
--
27
2.31.1
28
29
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter, and there no public
4
backing-child-based filter in Qemu. No reason to create a precedent, so
5
let's refactor copy-before-write filter instead.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20210824083856.17408-13-vsementsov@virtuozzo.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
block/copy-before-write.c | 39 ++++++++++++++++++++++-----------------
13
1 file changed, 22 insertions(+), 17 deletions(-)
14
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
18
+++ b/block/copy-before-write.c
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_preadv(
20
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
21
QEMUIOVector *qiov, int flags)
22
{
23
- return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
24
+ return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
25
}
26
27
static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
29
return ret;
30
}
31
32
- return bdrv_co_pdiscard(bs->backing, offset, bytes);
33
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
34
}
35
36
static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
38
return ret;
39
}
40
41
- return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
42
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
43
}
44
45
static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
47
return ret;
48
}
49
50
- return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
51
+ return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
52
}
53
54
static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
55
{
56
- if (!bs->backing) {
57
+ if (!bs->file) {
58
return 0;
59
}
60
61
- return bdrv_co_flush(bs->backing->bs);
62
+ return bdrv_co_flush(bs->file->bs);
63
}
64
65
static void cbw_refresh_filename(BlockDriverState *bs)
66
{
67
- if (bs->backing == NULL) {
68
- /*
69
- * we can be here after failed bdrv_attach_child in
70
- * bdrv_set_backing_hd
71
- */
72
- return;
73
- }
74
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
75
- bs->backing->bs->filename);
76
+ bs->file->bs->filename);
77
}
78
79
static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
80
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
81
top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
82
BDRV_O_RDWR, errp);
83
if (!top) {
84
+ error_prepend(errp, "Cannot open driver: ");
85
return NULL;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
89
state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
90
BDRV_CHILD_DATA, errp);
91
if (!state->target) {
92
+ error_prepend(errp, "Cannot attach target child: ");
93
+ bdrv_unref(top);
94
+ return NULL;
95
+ }
96
+
97
+ bdrv_ref(source);
98
+ top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
99
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
100
+ errp);
101
+ if (!top->file) {
102
+ error_prepend(errp, "Cannot attach file child: ");
103
bdrv_unref(top);
104
return NULL;
105
}
106
107
bdrv_drained_begin(source);
108
109
- ret = bdrv_append(top, source, errp);
110
+ ret = bdrv_replace_node(source, top, errp);
111
if (ret < 0) {
112
error_prepend(errp, "Cannot append copy-before-write filter: ");
113
goto fail;
114
}
115
appended = true;
116
117
- state->bcs = block_copy_state_new(top->backing, state->target,
118
- false, compress, errp);
119
+ state->bcs = block_copy_state_new(top->file, state->target, false, compress,
120
+ errp);
121
if (!state->bcs) {
122
error_prepend(errp, "Cannot create block-copy-state: ");
123
goto fail;
124
--
125
2.31.1
126
127
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Refactor the function to replace child at last. Thus we don't need to
4
revert it and code is simplified.
5
6
block-copy state initialization being done before replacing the child
7
doesn't need any drained section.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20210824083856.17408-14-vsementsov@virtuozzo.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
block/copy-before-write.c | 33 +++++++++++----------------------
15
1 file changed, 11 insertions(+), 22 deletions(-)
16
17
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/copy-before-write.c
20
+++ b/block/copy-before-write.c
21
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
22
int ret;
23
BDRVCopyBeforeWriteState *state;
24
BlockDriverState *top;
25
- bool appended = false;
26
27
assert(source->total_sectors == target->total_sectors);
28
29
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
30
BDRV_CHILD_DATA, errp);
31
if (!state->target) {
32
error_prepend(errp, "Cannot attach target child: ");
33
- bdrv_unref(top);
34
- return NULL;
35
+ goto fail;
36
}
37
38
bdrv_ref(source);
39
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
40
errp);
41
if (!top->file) {
42
error_prepend(errp, "Cannot attach file child: ");
43
- bdrv_unref(top);
44
- return NULL;
45
- }
46
-
47
- bdrv_drained_begin(source);
48
-
49
- ret = bdrv_replace_node(source, top, errp);
50
- if (ret < 0) {
51
- error_prepend(errp, "Cannot append copy-before-write filter: ");
52
goto fail;
53
}
54
- appended = true;
55
56
state->bcs = block_copy_state_new(top->file, state->target, false, compress,
57
errp);
58
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
59
error_prepend(errp, "Cannot create block-copy-state: ");
60
goto fail;
61
}
62
- *bcs = state->bcs;
63
64
+ bdrv_drained_begin(source);
65
+ ret = bdrv_replace_node(source, top, errp);
66
bdrv_drained_end(source);
67
+ if (ret < 0) {
68
+ error_prepend(errp, "Cannot append copy-before-write filter: ");
69
+ goto fail;
70
+ }
71
+
72
+ *bcs = state->bcs;
73
74
return top;
75
76
fail:
77
- if (appended) {
78
- bdrv_cbw_drop(top);
79
- } else {
80
- bdrv_unref(top);
81
- }
82
-
83
- bdrv_drained_end(source);
84
-
85
+ block_copy_state_free(state->bcs);
86
+ bdrv_unref(top);
87
return NULL;
88
}
89
90
--
91
2.31.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Move part of bdrv_cbw_append() to new function cbw_open(). It's an
4
intermediate step for adding normal .bdrv_open() handler to the
5
filter. With this commit no logic is changed, but we have a function
6
which will be turned into .bdrv_open() handler in future commit.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-15-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/copy-before-write.c | 69 +++++++++++++++++++++++----------------
14
1 file changed, 41 insertions(+), 28 deletions(-)
15
16
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/copy-before-write.c
19
+++ b/block/copy-before-write.c
20
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
21
}
22
}
23
24
+static int cbw_init(BlockDriverState *top, BlockDriverState *source,
25
+ BlockDriverState *target, bool compress, Error **errp)
26
+{
27
+ BDRVCopyBeforeWriteState *state = top->opaque;
28
+
29
+ top->total_sectors = source->total_sectors;
30
+ top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
31
+ (BDRV_REQ_FUA & source->supported_write_flags);
32
+ top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
33
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
34
+ source->supported_zero_flags);
35
+
36
+ bdrv_ref(target);
37
+ state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
38
+ BDRV_CHILD_DATA, errp);
39
+ if (!state->target) {
40
+ error_prepend(errp, "Cannot attach target child: ");
41
+ return -EINVAL;
42
+ }
43
+
44
+ bdrv_ref(source);
45
+ top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
46
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
47
+ errp);
48
+ if (!top->file) {
49
+ error_prepend(errp, "Cannot attach file child: ");
50
+ return -EINVAL;
51
+ }
52
+
53
+ state->bcs = block_copy_state_new(top->file, state->target, false, compress,
54
+ errp);
55
+ if (!state->bcs) {
56
+ error_prepend(errp, "Cannot create block-copy-state: ");
57
+ return -EINVAL;
58
+ }
59
+
60
+ return 0;
61
+}
62
+
63
BlockDriver bdrv_cbw_filter = {
64
.format_name = "copy-before-write",
65
.instance_size = sizeof(BDRVCopyBeforeWriteState),
66
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
67
error_prepend(errp, "Cannot open driver: ");
68
return NULL;
69
}
70
-
71
state = top->opaque;
72
- top->total_sectors = source->total_sectors;
73
- top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
74
- (BDRV_REQ_FUA & source->supported_write_flags);
75
- top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
76
- ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
77
- source->supported_zero_flags);
78
-
79
- bdrv_ref(target);
80
- state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
81
- BDRV_CHILD_DATA, errp);
82
- if (!state->target) {
83
- error_prepend(errp, "Cannot attach target child: ");
84
- goto fail;
85
- }
86
87
- bdrv_ref(source);
88
- top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
89
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
90
- errp);
91
- if (!top->file) {
92
- error_prepend(errp, "Cannot attach file child: ");
93
- goto fail;
94
- }
95
-
96
- state->bcs = block_copy_state_new(top->file, state->target, false, compress,
97
- errp);
98
- if (!state->bcs) {
99
- error_prepend(errp, "Cannot create block-copy-state: ");
100
+ ret = cbw_init(top, source, target, compress, errp);
101
+ if (ret < 0) {
102
goto fail;
103
}
104
105
--
106
2.31.1
107
108
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The blk_register_buf() API is an optimization hint that allows some
2
block drivers to avoid I/O buffer housekeeping or bounce buffers.
2
3
3
One more step closer to real .bdrv_open() handler: use more usual names
4
Add an -r option to register the I/O buffer so that qemu-io can be used
4
for bs being initialized and its state.
5
to test the blk_register_buf() API. The next commit will add a test that
6
uses the new option.
5
7
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
8
Message-Id: <20210824083856.17408-16-vsementsov@virtuozzo.com>
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20230207203719.242926-4-stefanha@redhat.com>
10
---
12
---
11
block/copy-before-write.c | 29 ++++++++++++++---------------
13
qemu-io-cmds.c | 204 +++++++++++++++++++++++++++++++------------------
12
1 file changed, 14 insertions(+), 15 deletions(-)
14
1 file changed, 129 insertions(+), 75 deletions(-)
13
15
14
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
16
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/block/copy-before-write.c
18
--- a/qemu-io-cmds.c
17
+++ b/block/copy-before-write.c
19
+++ b/qemu-io-cmds.c
18
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
20
@@ -XXX,XX +XXX,XX @@ static int parse_pattern(const char *arg)
19
}
21
*/
20
}
22
21
23
#define MISALIGN_OFFSET 16
22
-static int cbw_init(BlockDriverState *top, BlockDriverState *source,
24
-static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
23
+static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
25
+static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern,
24
BlockDriverState *target, bool compress, Error **errp)
26
+ bool register_buf)
25
{
27
{
26
- BDRVCopyBeforeWriteState *state = top->opaque;
28
void *buf;
27
+ BDRVCopyBeforeWriteState *s = bs->opaque;
29
28
30
@@ -XXX,XX +XXX,XX @@ static void *qemu_io_alloc(BlockBackend *blk, size_t len, int pattern)
29
- top->total_sectors = source->total_sectors;
31
}
30
- top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
32
buf = blk_blockalign(blk, len);
31
+ bs->total_sectors = source->total_sectors;
33
memset(buf, pattern, len);
32
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
34
+ if (register_buf) {
33
(BDRV_REQ_FUA & source->supported_write_flags);
35
+ blk_register_buf(blk, buf, len, &error_abort);
34
- top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
36
+ }
35
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
37
if (qemuio_misalign) {
36
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
38
buf += MISALIGN_OFFSET;
37
source->supported_zero_flags);
39
}
38
40
return buf;
39
bdrv_ref(target);
41
}
40
- state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
42
41
- BDRV_CHILD_DATA, errp);
43
-static void qemu_io_free(void *p)
42
- if (!state->target) {
44
+static void qemu_io_free(BlockBackend *blk, void *p, size_t len,
43
+ s->target = bdrv_attach_child(bs, target, "target", &child_of_bds,
45
+ bool unregister_buf)
44
+ BDRV_CHILD_DATA, errp);
46
{
45
+ if (!s->target) {
47
if (qemuio_misalign) {
46
error_prepend(errp, "Cannot attach target child: ");
48
p -= MISALIGN_OFFSET;
49
+ len += MISALIGN_OFFSET;
50
+ }
51
+ if (unregister_buf) {
52
+ blk_unregister_buf(blk, p, len);
53
}
54
qemu_vfree(p);
55
}
56
@@ -XXX,XX +XXX,XX @@ static void qemu_io_free(void *p)
57
* @blk - the block backend where the buffer content is going to be written to
58
* @len - the buffer length
59
* @file_name - the file to read the content from
60
+ * @register_buf - call blk_register_buf()
61
*
62
* Returns: the buffer pointer on success
63
* NULL on error
64
*/
65
static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
66
- const char *file_name)
67
+ const char *file_name, bool register_buf)
68
{
69
- char *buf, *buf_origin;
70
+ size_t alloc_len = len + (qemuio_misalign ? MISALIGN_OFFSET : 0);
71
+ char *alloc_buf, *buf, *end;
72
FILE *f = fopen(file_name, "r");
73
int pattern_len;
74
75
@@ -XXX,XX +XXX,XX @@ static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
76
return NULL;
77
}
78
79
- if (qemuio_misalign) {
80
- len += MISALIGN_OFFSET;
81
- }
82
-
83
- buf_origin = buf = blk_blockalign(blk, len);
84
+ alloc_buf = buf = blk_blockalign(blk, alloc_len);
85
86
if (qemuio_misalign) {
87
- buf_origin += MISALIGN_OFFSET;
88
buf += MISALIGN_OFFSET;
89
- len -= MISALIGN_OFFSET;
90
}
91
92
- pattern_len = fread(buf_origin, 1, len, f);
93
+ pattern_len = fread(buf, 1, len, f);
94
95
if (ferror(f)) {
96
perror(file_name);
97
@@ -XXX,XX +XXX,XX @@ static void *qemu_io_alloc_from_file(BlockBackend *blk, size_t len,
98
fclose(f);
99
f = NULL;
100
101
- if (len > pattern_len) {
102
- len -= pattern_len;
103
- buf += pattern_len;
104
-
105
- while (len > 0) {
106
- size_t len_to_copy = MIN(pattern_len, len);
107
-
108
- memcpy(buf, buf_origin, len_to_copy);
109
+ if (register_buf) {
110
+ blk_register_buf(blk, alloc_buf, alloc_len, &error_abort);
111
+ }
112
113
- len -= len_to_copy;
114
- buf += len_to_copy;
115
- }
116
+ end = buf + len;
117
+ for (char *p = buf + pattern_len; p < end; p += pattern_len) {
118
+ memcpy(p, buf, MIN(pattern_len, end - p));
119
}
120
121
- return buf_origin;
122
+ return buf;
123
124
error:
125
- qemu_io_free(buf_origin);
126
+ /*
127
+ * This code path is only taken before blk_register_buf() is called, so
128
+ * hardcode the qemu_io_free() unregister_buf argument to false.
129
+ */
130
+ qemu_io_free(blk, alloc_buf, alloc_len, false);
131
if (f) {
132
fclose(f);
133
}
134
@@ -XXX,XX +XXX,XX @@ static void print_report(const char *op, struct timespec *t, int64_t offset,
135
*/
136
static void *
137
create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
138
- int pattern)
139
+ int pattern, bool register_buf)
140
{
141
size_t *sizes = g_new0(size_t, nr_iov);
142
size_t count = 0;
143
@@ -XXX,XX +XXX,XX @@ create_iovec(BlockBackend *blk, QEMUIOVector *qiov, char **argv, int nr_iov,
144
145
qemu_iovec_init(qiov, nr_iov);
146
147
- buf = p = qemu_io_alloc(blk, count, pattern);
148
+ buf = p = qemu_io_alloc(blk, count, pattern, register_buf);
149
150
for (i = 0; i < nr_iov; i++) {
151
qemu_iovec_add(qiov, p, sizes[i]);
152
@@ -XXX,XX +XXX,XX @@ fail:
153
}
154
155
static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
156
- int64_t bytes, int64_t *total)
157
+ int64_t bytes, BdrvRequestFlags flags, int64_t *total)
158
{
159
int ret;
160
161
@@ -XXX,XX +XXX,XX @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
162
return -ERANGE;
163
}
164
165
- ret = blk_pread(blk, offset, bytes, (uint8_t *)buf, 0);
166
+ ret = blk_pread(blk, offset, bytes, (uint8_t *)buf, flags);
167
if (ret < 0) {
168
return ret;
169
}
170
@@ -XXX,XX +XXX,XX @@ static void aio_rw_done(void *opaque, int ret)
171
}
172
173
static int do_aio_readv(BlockBackend *blk, QEMUIOVector *qiov,
174
- int64_t offset, int *total)
175
+ int64_t offset, BdrvRequestFlags flags, int *total)
176
{
177
int async_ret = NOT_DONE;
178
179
- blk_aio_preadv(blk, offset, qiov, 0, aio_rw_done, &async_ret);
180
+ blk_aio_preadv(blk, offset, qiov, flags, aio_rw_done, &async_ret);
181
while (async_ret == NOT_DONE) {
182
main_loop_wait(false);
183
}
184
@@ -XXX,XX +XXX,XX @@ static void read_help(void)
185
" -p, -- ignored for backwards compatibility\n"
186
" -P, -- use a pattern to verify read data\n"
187
" -q, -- quiet mode, do not show I/O statistics\n"
188
+" -r, -- register I/O buffer\n"
189
" -s, -- start offset for pattern verification (only with -P)\n"
190
" -v, -- dump buffer to standard output\n"
191
"\n");
192
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t read_cmd = {
193
.cfunc = read_f,
194
.argmin = 2,
195
.argmax = -1,
196
- .args = "[-abCqv] [-P pattern [-s off] [-l len]] off len",
197
+ .args = "[-abCqrv] [-P pattern [-s off] [-l len]] off len",
198
.oneline = "reads a number of bytes at a specified offset",
199
.help = read_help,
200
};
201
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
202
int64_t total = 0;
203
int pattern = 0;
204
int64_t pattern_offset = 0, pattern_count = 0;
205
+ BdrvRequestFlags flags = 0;
206
207
- while ((c = getopt(argc, argv, "bCl:pP:qs:v")) != -1) {
208
+ while ((c = getopt(argc, argv, "bCl:pP:qrs:v")) != -1) {
209
switch (c) {
210
case 'b':
211
bflag = true;
212
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
213
case 'q':
214
qflag = true;
215
break;
216
+ case 'r':
217
+ flags |= BDRV_REQ_REGISTERED_BUF;
218
+ break;
219
case 's':
220
sflag = true;
221
pattern_offset = cvtnum(optarg);
222
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
223
count);
224
return -EINVAL;
225
}
226
+ if (flags & BDRV_REQ_REGISTERED_BUF) {
227
+ printf("I/O buffer registration is not supported when reading "
228
+ "from vmstate\n");
229
+ return -EINVAL;
230
+ }
231
}
232
233
- buf = qemu_io_alloc(blk, count, 0xab);
234
+ buf = qemu_io_alloc(blk, count, 0xab, flags & BDRV_REQ_REGISTERED_BUF);
235
236
clock_gettime(CLOCK_MONOTONIC, &t1);
237
if (bflag) {
238
ret = do_load_vmstate(blk, buf, offset, count, &total);
239
} else {
240
- ret = do_pread(blk, buf, offset, count, &total);
241
+ ret = do_pread(blk, buf, offset, count, flags, &total);
242
}
243
clock_gettime(CLOCK_MONOTONIC, &t2);
244
245
@@ -XXX,XX +XXX,XX @@ static int read_f(BlockBackend *blk, int argc, char **argv)
246
print_report("read", &t2, offset, count, total, cnt, Cflag);
247
248
out:
249
- qemu_io_free(buf);
250
+ qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
251
return ret;
252
}
253
254
@@ -XXX,XX +XXX,XX @@ static void readv_help(void)
255
" Uses multiple iovec buffers if more than one byte range is specified.\n"
256
" -C, -- report statistics in a machine parsable format\n"
257
" -P, -- use a pattern to verify read data\n"
258
-" -v, -- dump buffer to standard output\n"
259
" -q, -- quiet mode, do not show I/O statistics\n"
260
+" -r, -- register I/O buffer\n"
261
+" -v, -- dump buffer to standard output\n"
262
"\n");
263
}
264
265
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t readv_cmd = {
266
.cfunc = readv_f,
267
.argmin = 2,
268
.argmax = -1,
269
- .args = "[-Cqv] [-P pattern] off len [len..]",
270
+ .args = "[-Cqrv] [-P pattern] off len [len..]",
271
.oneline = "reads a number of bytes at a specified offset",
272
.help = readv_help,
273
};
274
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
275
QEMUIOVector qiov;
276
int pattern = 0;
277
bool Pflag = false;
278
+ BdrvRequestFlags flags = 0;
279
280
- while ((c = getopt(argc, argv, "CP:qv")) != -1) {
281
+ while ((c = getopt(argc, argv, "CP:qrv")) != -1) {
282
switch (c) {
283
case 'C':
284
Cflag = true;
285
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
286
case 'q':
287
qflag = true;
288
break;
289
+ case 'r':
290
+ flags |= BDRV_REQ_REGISTERED_BUF;
291
+ break;
292
case 'v':
293
vflag = true;
294
break;
295
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
296
optind++;
297
298
nr_iov = argc - optind;
299
- buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab);
300
+ buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, 0xab,
301
+ flags & BDRV_REQ_REGISTERED_BUF);
302
if (buf == NULL) {
47
return -EINVAL;
303
return -EINVAL;
48
}
304
}
49
305
50
bdrv_ref(source);
306
clock_gettime(CLOCK_MONOTONIC, &t1);
51
- top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
307
- ret = do_aio_readv(blk, &qiov, offset, &total);
52
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
308
+ ret = do_aio_readv(blk, &qiov, offset, flags, &total);
53
- errp);
309
clock_gettime(CLOCK_MONOTONIC, &t2);
54
- if (!top->file) {
310
55
+ bs->file = bdrv_attach_child(bs, source, "file", &child_of_bds,
311
if (ret < 0) {
56
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
312
@@ -XXX,XX +XXX,XX @@ static int readv_f(BlockBackend *blk, int argc, char **argv)
57
+ errp);
313
print_report("read", &t2, offset, qiov.size, total, cnt, Cflag);
58
+ if (!bs->file) {
314
59
error_prepend(errp, "Cannot attach file child: ");
315
out:
316
+ qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
317
qemu_iovec_destroy(&qiov);
318
- qemu_io_free(buf);
319
return ret;
320
}
321
322
@@ -XXX,XX +XXX,XX @@ static void write_help(void)
323
" filled with a set pattern (0xcdcdcdcd).\n"
324
" -b, -- write to the VM state rather than the virtual disk\n"
325
" -c, -- write compressed data with blk_write_compressed\n"
326
+" -C, -- report statistics in a machine parsable format\n"
327
" -f, -- use Force Unit Access semantics\n"
328
" -n, -- with -z, don't allow slow fallback\n"
329
" -p, -- ignored for backwards compatibility\n"
330
" -P, -- use different pattern to fill file\n"
331
+" -q, -- quiet mode, do not show I/O statistics\n"
332
+" -r, -- register I/O buffer\n"
333
" -s, -- use a pattern file to fill the write buffer\n"
334
-" -C, -- report statistics in a machine parsable format\n"
335
-" -q, -- quiet mode, do not show I/O statistics\n"
336
" -u, -- with -z, allow unmapping\n"
337
" -z, -- write zeroes using blk_pwrite_zeroes\n"
338
"\n");
339
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t write_cmd = {
340
.perm = BLK_PERM_WRITE,
341
.argmin = 2,
342
.argmax = -1,
343
- .args = "[-bcCfnquz] [-P pattern | -s source_file] off len",
344
+ .args = "[-bcCfnqruz] [-P pattern | -s source_file] off len",
345
.oneline = "writes a number of bytes at a specified offset",
346
.help = write_help,
347
};
348
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
349
int pattern = 0xcd;
350
const char *file_name = NULL;
351
352
- while ((c = getopt(argc, argv, "bcCfnpP:qs:uz")) != -1) {
353
+ while ((c = getopt(argc, argv, "bcCfnpP:qrs:uz")) != -1) {
354
switch (c) {
355
case 'b':
356
bflag = true;
357
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
358
case 'q':
359
qflag = true;
360
break;
361
+ case 'r':
362
+ flags |= BDRV_REQ_REGISTERED_BUF;
363
+ break;
364
case 's':
365
sflag = true;
366
file_name = optarg;
367
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
368
}
369
}
370
371
- if (!zflag) {
372
+ if (zflag) {
373
+ if (flags & BDRV_REQ_REGISTERED_BUF) {
374
+ printf("cannot combine zero write with registered I/O buffer\n");
375
+ return -EINVAL;
376
+ }
377
+ } else {
378
if (sflag) {
379
- buf = qemu_io_alloc_from_file(blk, count, file_name);
380
+ buf = qemu_io_alloc_from_file(blk, count, file_name,
381
+ flags & BDRV_REQ_REGISTERED_BUF);
382
if (!buf) {
383
return -EINVAL;
384
}
385
} else {
386
- buf = qemu_io_alloc(blk, count, pattern);
387
+ buf = qemu_io_alloc(blk, count, pattern,
388
+ flags & BDRV_REQ_REGISTERED_BUF);
389
}
390
}
391
392
@@ -XXX,XX +XXX,XX @@ static int write_f(BlockBackend *blk, int argc, char **argv)
393
394
out:
395
if (!zflag) {
396
- qemu_io_free(buf);
397
+ qemu_io_free(blk, buf, count, flags & BDRV_REQ_REGISTERED_BUF);
398
}
399
return ret;
400
}
401
@@ -XXX,XX +XXX,XX @@ writev_help(void)
402
"\n"
403
" Writes into a segment of the currently open file, using a buffer\n"
404
" filled with a set pattern (0xcdcdcdcd).\n"
405
-" -P, -- use different pattern to fill file\n"
406
" -C, -- report statistics in a machine parsable format\n"
407
" -f, -- use Force Unit Access semantics\n"
408
+" -P, -- use different pattern to fill file\n"
409
" -q, -- quiet mode, do not show I/O statistics\n"
410
+" -r, -- register I/O buffer\n"
411
"\n");
412
}
413
414
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t writev_cmd = {
415
.perm = BLK_PERM_WRITE,
416
.argmin = 2,
417
.argmax = -1,
418
- .args = "[-Cfq] [-P pattern] off len [len..]",
419
+ .args = "[-Cfqr] [-P pattern] off len [len..]",
420
.oneline = "writes a number of bytes at a specified offset",
421
.help = writev_help,
422
};
423
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
424
int pattern = 0xcd;
425
QEMUIOVector qiov;
426
427
- while ((c = getopt(argc, argv, "CfqP:")) != -1) {
428
+ while ((c = getopt(argc, argv, "CfP:qr")) != -1) {
429
switch (c) {
430
case 'C':
431
Cflag = true;
432
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
433
case 'q':
434
qflag = true;
435
break;
436
+ case 'r':
437
+ flags |= BDRV_REQ_REGISTERED_BUF;
438
+ break;
439
case 'P':
440
pattern = parse_pattern(optarg);
441
if (pattern < 0) {
442
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
443
optind++;
444
445
nr_iov = argc - optind;
446
- buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern);
447
+ buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
448
+ flags & BDRV_REQ_REGISTERED_BUF);
449
if (buf == NULL) {
60
return -EINVAL;
450
return -EINVAL;
61
}
451
}
62
452
@@ -XXX,XX +XXX,XX @@ static int writev_f(BlockBackend *blk, int argc, char **argv)
63
- state->bcs = block_copy_state_new(top->file, state->target, false, compress,
453
t2 = tsub(t2, t1);
64
- errp);
454
print_report("wrote", &t2, offset, qiov.size, total, cnt, Cflag);
65
- if (!state->bcs) {
455
out:
66
+ s->bcs = block_copy_state_new(bs->file, s->target, false, compress, errp);
456
+ qemu_io_free(blk, buf, qiov.size, flags & BDRV_REQ_REGISTERED_BUF);
67
+ if (!s->bcs) {
457
qemu_iovec_destroy(&qiov);
68
error_prepend(errp, "Cannot create block-copy-state: ");
458
- qemu_io_free(buf);
459
return ret;
460
}
461
462
@@ -XXX,XX +XXX,XX @@ struct aio_ctx {
463
bool zflag;
464
BlockAcctCookie acct;
465
int pattern;
466
+ BdrvRequestFlags flags;
467
struct timespec t1;
468
};
469
470
@@ -XXX,XX +XXX,XX @@ static void aio_write_done(void *opaque, int ret)
471
ctx->qiov.size, 1, ctx->Cflag);
472
out:
473
if (!ctx->zflag) {
474
- qemu_io_free(ctx->buf);
475
+ qemu_io_free(ctx->blk, ctx->buf, ctx->qiov.size,
476
+ ctx->flags & BDRV_REQ_REGISTERED_BUF);
477
qemu_iovec_destroy(&ctx->qiov);
478
}
479
g_free(ctx);
480
@@ -XXX,XX +XXX,XX @@ static void aio_read_done(void *opaque, int ret)
481
print_report("read", &t2, ctx->offset, ctx->qiov.size,
482
ctx->qiov.size, 1, ctx->Cflag);
483
out:
484
- qemu_io_free(ctx->buf);
485
+ qemu_io_free(ctx->blk, ctx->buf, ctx->qiov.size,
486
+ ctx->flags & BDRV_REQ_REGISTERED_BUF);
487
qemu_iovec_destroy(&ctx->qiov);
488
g_free(ctx);
489
}
490
@@ -XXX,XX +XXX,XX @@ static void aio_read_help(void)
491
" considered successful once the request is submitted, independently\n"
492
" of potential I/O errors or pattern mismatches.\n"
493
" -C, -- report statistics in a machine parsable format\n"
494
-" -P, -- use a pattern to verify read data\n"
495
" -i, -- treat request as invalid, for exercising stats\n"
496
-" -v, -- dump buffer to standard output\n"
497
+" -P, -- use a pattern to verify read data\n"
498
" -q, -- quiet mode, do not show I/O statistics\n"
499
+" -r, -- register I/O buffer\n"
500
+" -v, -- dump buffer to standard output\n"
501
"\n");
502
}
503
504
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_read_cmd = {
505
.cfunc = aio_read_f,
506
.argmin = 2,
507
.argmax = -1,
508
- .args = "[-Ciqv] [-P pattern] off len [len..]",
509
+ .args = "[-Ciqrv] [-P pattern] off len [len..]",
510
.oneline = "asynchronously reads a number of bytes",
511
.help = aio_read_help,
512
};
513
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
514
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
515
516
ctx->blk = blk;
517
- while ((c = getopt(argc, argv, "CP:iqv")) != -1) {
518
+ while ((c = getopt(argc, argv, "CiP:qrv")) != -1) {
519
switch (c) {
520
case 'C':
521
ctx->Cflag = true;
522
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
523
case 'q':
524
ctx->qflag = true;
525
break;
526
+ case 'r':
527
+ ctx->flags |= BDRV_REQ_REGISTERED_BUF;
528
+ break;
529
case 'v':
530
ctx->vflag = true;
531
break;
532
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
533
optind++;
534
535
nr_iov = argc - optind;
536
- ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab);
537
+ ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov, 0xab,
538
+ ctx->flags & BDRV_REQ_REGISTERED_BUF);
539
if (ctx->buf == NULL) {
540
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_READ);
541
g_free(ctx);
542
@@ -XXX,XX +XXX,XX @@ static int aio_read_f(BlockBackend *blk, int argc, char **argv)
543
clock_gettime(CLOCK_MONOTONIC, &ctx->t1);
544
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
545
BLOCK_ACCT_READ);
546
- blk_aio_preadv(blk, ctx->offset, &ctx->qiov, 0, aio_read_done, ctx);
547
+ blk_aio_preadv(blk, ctx->offset, &ctx->qiov, ctx->flags, aio_read_done,
548
+ ctx);
549
return 0;
550
}
551
552
@@ -XXX,XX +XXX,XX @@ static void aio_write_help(void)
553
" Note that due to its asynchronous nature, this command will be\n"
554
" considered successful once the request is submitted, independently\n"
555
" of potential I/O errors or pattern mismatches.\n"
556
-" -P, -- use different pattern to fill file\n"
557
" -C, -- report statistics in a machine parsable format\n"
558
" -f, -- use Force Unit Access semantics\n"
559
" -i, -- treat request as invalid, for exercising stats\n"
560
+" -P, -- use different pattern to fill file\n"
561
" -q, -- quiet mode, do not show I/O statistics\n"
562
+" -r, -- register I/O buffer\n"
563
" -u, -- with -z, allow unmapping\n"
564
" -z, -- write zeroes using blk_aio_pwrite_zeroes\n"
565
"\n");
566
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t aio_write_cmd = {
567
.perm = BLK_PERM_WRITE,
568
.argmin = 2,
569
.argmax = -1,
570
- .args = "[-Cfiquz] [-P pattern] off len [len..]",
571
+ .args = "[-Cfiqruz] [-P pattern] off len [len..]",
572
.oneline = "asynchronously writes a number of bytes",
573
.help = aio_write_help,
574
};
575
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
576
int nr_iov, c;
577
int pattern = 0xcd;
578
struct aio_ctx *ctx = g_new0(struct aio_ctx, 1);
579
- BdrvRequestFlags flags = 0;
580
581
ctx->blk = blk;
582
- while ((c = getopt(argc, argv, "CfiqP:uz")) != -1) {
583
+ while ((c = getopt(argc, argv, "CfiP:qruz")) != -1) {
584
switch (c) {
585
case 'C':
586
ctx->Cflag = true;
587
break;
588
case 'f':
589
- flags |= BDRV_REQ_FUA;
590
+ ctx->flags |= BDRV_REQ_FUA;
591
break;
592
case 'q':
593
ctx->qflag = true;
594
break;
595
+ case 'r':
596
+ ctx->flags |= BDRV_REQ_REGISTERED_BUF;
597
+ break;
598
case 'u':
599
- flags |= BDRV_REQ_MAY_UNMAP;
600
+ ctx->flags |= BDRV_REQ_MAY_UNMAP;
601
break;
602
case 'P':
603
pattern = parse_pattern(optarg);
604
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
69
return -EINVAL;
605
return -EINVAL;
70
}
606
}
607
608
- if ((flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
609
+ if ((ctx->flags & BDRV_REQ_MAY_UNMAP) && !ctx->zflag) {
610
printf("-u requires -z to be specified\n");
611
g_free(ctx);
612
return -EINVAL;
613
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
614
return -EINVAL;
615
}
616
617
+ if (ctx->zflag && (ctx->flags & BDRV_REQ_REGISTERED_BUF)) {
618
+ printf("cannot combine zero write with registered I/O buffer\n");
619
+ g_free(ctx);
620
+ return -EINVAL;
621
+ }
622
+
623
ctx->offset = cvtnum(argv[optind]);
624
if (ctx->offset < 0) {
625
int ret = ctx->offset;
626
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
627
}
628
629
ctx->qiov.size = count;
630
- blk_aio_pwrite_zeroes(blk, ctx->offset, count, flags, aio_write_done,
631
- ctx);
632
+ blk_aio_pwrite_zeroes(blk, ctx->offset, count, ctx->flags,
633
+ aio_write_done, ctx);
634
} else {
635
nr_iov = argc - optind;
636
ctx->buf = create_iovec(blk, &ctx->qiov, &argv[optind], nr_iov,
637
- pattern);
638
+ pattern, ctx->flags & BDRV_REQ_REGISTERED_BUF);
639
if (ctx->buf == NULL) {
640
block_acct_invalid(blk_get_stats(blk), BLOCK_ACCT_WRITE);
641
g_free(ctx);
642
@@ -XXX,XX +XXX,XX @@ static int aio_write_f(BlockBackend *blk, int argc, char **argv)
643
block_acct_start(blk_get_stats(blk), &ctx->acct, ctx->qiov.size,
644
BLOCK_ACCT_WRITE);
645
646
- blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, flags, aio_write_done,
647
- ctx);
648
+ blk_aio_pwritev(blk, ctx->offset, &ctx->qiov, ctx->flags,
649
+ aio_write_done, ctx);
650
}
651
652
return 0;
71
--
653
--
72
2.31.1
654
2.39.1
73
74
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
In the next commit we'll get rid of source argument of cbw_init().
4
Prepare to it now, to make next commit simpler: move the code block
5
that uses source below attaching the child and use bs->file->bs instead
6
of source variable.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-17-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/copy-before-write.c | 14 +++++++-------
14
1 file changed, 7 insertions(+), 7 deletions(-)
15
16
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/copy-before-write.c
19
+++ b/block/copy-before-write.c
20
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
21
{
22
BDRVCopyBeforeWriteState *s = bs->opaque;
23
24
- bs->total_sectors = source->total_sectors;
25
- bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
26
- (BDRV_REQ_FUA & source->supported_write_flags);
27
- bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
28
- ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
29
- source->supported_zero_flags);
30
-
31
bdrv_ref(target);
32
s->target = bdrv_attach_child(bs, target, "target", &child_of_bds,
33
BDRV_CHILD_DATA, errp);
34
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
35
return -EINVAL;
36
}
37
38
+ bs->total_sectors = bs->file->bs->total_sectors;
39
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
40
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
41
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
42
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
43
+ bs->file->bs->supported_zero_flags);
44
+
45
s->bcs = block_copy_state_new(bs->file, s->target, false, compress, errp);
46
if (!s->bcs) {
47
error_prepend(errp, "Cannot create block-copy-state: ");
48
--
49
2.31.1
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
Message-Id: <20210824083856.17408-18-vsementsov@virtuozzo.com>
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
---
8
block/copy-before-write.h | 1 -
9
block/backup.c | 2 +-
10
block/copy-before-write.c | 7 +++----
11
3 files changed, 4 insertions(+), 6 deletions(-)
12
13
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/copy-before-write.h
16
+++ b/block/copy-before-write.h
17
@@ -XXX,XX +XXX,XX @@
18
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
19
BlockDriverState *target,
20
const char *filter_node_name,
21
- bool compress,
22
BlockCopyState **bcs,
23
Error **errp);
24
void bdrv_cbw_drop(BlockDriverState *bs);
25
diff --git a/block/backup.c b/block/backup.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/backup.c
28
+++ b/block/backup.c
29
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
30
goto error;
31
}
32
33
- cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
34
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
35
if (!cbw) {
36
goto error;
37
}
38
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/copy-before-write.c
41
+++ b/block/copy-before-write.c
42
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
43
}
44
45
static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
46
- BlockDriverState *target, bool compress, Error **errp)
47
+ BlockDriverState *target, Error **errp)
48
{
49
BDRVCopyBeforeWriteState *s = bs->opaque;
50
51
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
52
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
53
bs->file->bs->supported_zero_flags);
54
55
- s->bcs = block_copy_state_new(bs->file, s->target, false, compress, errp);
56
+ s->bcs = block_copy_state_new(bs->file, s->target, false, false, errp);
57
if (!s->bcs) {
58
error_prepend(errp, "Cannot create block-copy-state: ");
59
return -EINVAL;
60
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_cbw_filter = {
61
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
62
BlockDriverState *target,
63
const char *filter_node_name,
64
- bool compress,
65
BlockCopyState **bcs,
66
Error **errp)
67
{
68
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
69
}
70
state = top->opaque;
71
72
- ret = cbw_init(top, source, target, compress, errp);
73
+ ret = cbw_init(top, source, target, errp);
74
if (ret < 0) {
75
goto fail;
76
}
77
--
78
2.31.1
79
80
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
One more step closer to .bdrv_open(): use options instead of plain
4
arguments. Move to bdrv_open_child() calls, native for drive open
5
handlers.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20210824083856.17408-19-vsementsov@virtuozzo.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
block/copy-before-write.c | 29 +++++++++++++++--------------
13
1 file changed, 15 insertions(+), 14 deletions(-)
14
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
18
+++ b/block/copy-before-write.c
19
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
20
}
21
}
22
23
-static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
24
- BlockDriverState *target, Error **errp)
25
+static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
26
{
27
BDRVCopyBeforeWriteState *s = bs->opaque;
28
29
- bdrv_ref(target);
30
- s->target = bdrv_attach_child(bs, target, "target", &child_of_bds,
31
- BDRV_CHILD_DATA, errp);
32
- if (!s->target) {
33
- error_prepend(errp, "Cannot attach target child: ");
34
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
35
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
36
+ false, errp);
37
+ if (!bs->file) {
38
return -EINVAL;
39
}
40
41
- bdrv_ref(source);
42
- bs->file = bdrv_attach_child(bs, source, "file", &child_of_bds,
43
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
44
- errp);
45
- if (!bs->file) {
46
- error_prepend(errp, "Cannot attach file child: ");
47
+ s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
48
+ BDRV_CHILD_DATA, false, errp);
49
+ if (!s->target) {
50
return -EINVAL;
51
}
52
53
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
54
int ret;
55
BDRVCopyBeforeWriteState *state;
56
BlockDriverState *top;
57
+ QDict *opts;
58
59
assert(source->total_sectors == target->total_sectors);
60
61
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
62
}
63
state = top->opaque;
64
65
- ret = cbw_init(top, source, target, errp);
66
+ opts = qdict_new();
67
+ qdict_put_str(opts, "file", bdrv_get_node_name(source));
68
+ qdict_put_str(opts, "target", bdrv_get_node_name(target));
69
+
70
+ ret = cbw_init(top, opts, errp);
71
+ qobject_unref(opts);
72
if (ret < 0) {
73
goto fail;
74
}
75
--
76
2.31.1
77
78
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter to be used in separate
4
of backup. Future step would support bitmap for the filter. But let's
5
start from full set bitmap.
6
7
We have to modify backup, as bitmap is first initialized by
8
copy-before-write filter, and then backup modifies it.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20210824083856.17408-20-vsementsov@virtuozzo.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
15
block/backup.c | 16 +++++++---------
16
block/copy-before-write.c | 4 ++++
17
2 files changed, 11 insertions(+), 9 deletions(-)
18
19
diff --git a/block/backup.c b/block/backup.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/backup.c
22
+++ b/block/backup.c
23
@@ -XXX,XX +XXX,XX @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
24
BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
25
26
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
27
+ bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
28
ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
29
NULL, true);
30
assert(ret);
31
- } else {
32
- if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
33
- /*
34
- * We can't hog the coroutine to initialize this thoroughly.
35
- * Set a flag and resume work when we are able to yield safely.
36
- */
37
- block_copy_set_skip_unallocated(job->bcs, true);
38
- }
39
- bdrv_set_dirty_bitmap(bcs_bitmap, 0, job->len);
40
+ } else if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
41
+ /*
42
+ * We can't hog the coroutine to initialize this thoroughly.
43
+ * Set a flag and resume work when we are able to yield safely.
44
+ */
45
+ block_copy_set_skip_unallocated(job->bcs, true);
46
}
47
48
estimate = bdrv_get_dirty_count(bcs_bitmap);
49
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/copy-before-write.c
52
+++ b/block/copy-before-write.c
53
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
54
static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
55
{
56
BDRVCopyBeforeWriteState *s = bs->opaque;
57
+ BdrvDirtyBitmap *copy_bitmap;
58
59
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
60
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
61
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
62
return -EINVAL;
63
}
64
65
+ copy_bitmap = block_copy_dirty_bitmap(s->bcs);
66
+ bdrv_set_dirty_bitmap(copy_bitmap, 0, bdrv_dirty_bitmap_size(copy_bitmap));
67
+
68
return 0;
69
}
70
71
--
72
2.31.1
73
74
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Now block-copy will crash if user don't set progress meter by
4
block_copy_set_progress_meter(). copy-before-write filter will be used
5
in separate of backup job, and it doesn't want any progress meter (for
6
now). So, allow not setting it.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-21-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/block-copy.c | 18 +++++++++++-------
14
1 file changed, 11 insertions(+), 7 deletions(-)
15
16
diff --git a/block/block-copy.c b/block/block-copy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/block-copy.c
19
+++ b/block/block-copy.c
20
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
21
bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
22
}
23
QLIST_REMOVE(task, list);
24
- progress_set_remaining(task->s->progress,
25
- bdrv_get_dirty_count(task->s->copy_bitmap) +
26
- task->s->in_flight_bytes);
27
+ if (task->s->progress) {
28
+ progress_set_remaining(task->s->progress,
29
+ bdrv_get_dirty_count(task->s->copy_bitmap) +
30
+ task->s->in_flight_bytes);
31
+ }
32
qemu_co_queue_restart_all(&task->wait_queue);
33
}
34
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
36
t->call_state->ret = ret;
37
t->call_state->error_is_read = error_is_read;
38
}
39
- } else {
40
+ } else if (s->progress) {
41
progress_work_done(s->progress, t->bytes);
42
}
43
}
44
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
45
if (!ret) {
46
qemu_co_mutex_lock(&s->lock);
47
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
48
- progress_set_remaining(s->progress,
49
- bdrv_get_dirty_count(s->copy_bitmap) +
50
- s->in_flight_bytes);
51
+ if (s->progress) {
52
+ progress_set_remaining(s->progress,
53
+ bdrv_get_dirty_count(s->copy_bitmap) +
54
+ s->in_flight_bytes);
55
+ }
56
qemu_co_mutex_unlock(&s->lock);
57
}
58
59
--
60
2.31.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Finally, copy-before-write gets own .bdrv_open and .bdrv_close
4
handlers, block_init() call and becomes available through bdrv_open().
5
6
To achieve this:
7
8
- cbw_init gets unused flags argument and becomes cbw_open
9
- block_copy_state_free() call moved to new cbw_close()
10
- in bdrv_cbw_append:
11
- options are completed with driver and node-name, and we can simply
12
use bdrv_insert_node() to do both open and drained replacing
13
- in bdrv_cbw_drop:
14
- cbw_close() is now responsible for freeing s->bcs, so don't do it
15
here
16
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Message-Id: <20210824083856.17408-22-vsementsov@virtuozzo.com>
20
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
21
---
22
block/copy-before-write.c | 60 ++++++++++++++++++---------------------
23
1 file changed, 28 insertions(+), 32 deletions(-)
24
25
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.c
28
+++ b/block/copy-before-write.c
29
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
30
}
31
}
32
33
-static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
34
+static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
35
+ Error **errp)
36
{
37
BDRVCopyBeforeWriteState *s = bs->opaque;
38
BdrvDirtyBitmap *copy_bitmap;
39
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
40
return 0;
41
}
42
43
+static void cbw_close(BlockDriverState *bs)
44
+{
45
+ BDRVCopyBeforeWriteState *s = bs->opaque;
46
+
47
+ block_copy_state_free(s->bcs);
48
+ s->bcs = NULL;
49
+}
50
+
51
BlockDriver bdrv_cbw_filter = {
52
.format_name = "copy-before-write",
53
.instance_size = sizeof(BDRVCopyBeforeWriteState),
54
55
+ .bdrv_open = cbw_open,
56
+ .bdrv_close = cbw_close,
57
+
58
.bdrv_co_preadv = cbw_co_preadv,
59
.bdrv_co_pwritev = cbw_co_pwritev,
60
.bdrv_co_pwrite_zeroes = cbw_co_pwrite_zeroes,
61
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
62
Error **errp)
63
{
64
ERRP_GUARD();
65
- int ret;
66
BDRVCopyBeforeWriteState *state;
67
BlockDriverState *top;
68
QDict *opts;
69
70
assert(source->total_sectors == target->total_sectors);
71
72
- top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
73
- BDRV_O_RDWR, errp);
74
- if (!top) {
75
- error_prepend(errp, "Cannot open driver: ");
76
- return NULL;
77
- }
78
- state = top->opaque;
79
-
80
opts = qdict_new();
81
+ qdict_put_str(opts, "driver", "copy-before-write");
82
+ if (filter_node_name) {
83
+ qdict_put_str(opts, "node-name", filter_node_name);
84
+ }
85
qdict_put_str(opts, "file", bdrv_get_node_name(source));
86
qdict_put_str(opts, "target", bdrv_get_node_name(target));
87
88
- ret = cbw_init(top, opts, errp);
89
- qobject_unref(opts);
90
- if (ret < 0) {
91
- goto fail;
92
- }
93
-
94
- bdrv_drained_begin(source);
95
- ret = bdrv_replace_node(source, top, errp);
96
- bdrv_drained_end(source);
97
- if (ret < 0) {
98
- error_prepend(errp, "Cannot append copy-before-write filter: ");
99
- goto fail;
100
+ top = bdrv_insert_node(source, opts, BDRV_O_RDWR, errp);
101
+ if (!top) {
102
+ return NULL;
103
}
104
105
+ state = top->opaque;
106
*bcs = state->bcs;
107
108
return top;
109
-
110
-fail:
111
- block_copy_state_free(state->bcs);
112
- bdrv_unref(top);
113
- return NULL;
114
}
115
116
void bdrv_cbw_drop(BlockDriverState *bs)
117
{
118
- BDRVCopyBeforeWriteState *s = bs->opaque;
119
-
120
bdrv_drop_filter(bs, &error_abort);
121
-
122
- block_copy_state_free(s->bcs);
123
-
124
bdrv_unref(bs);
125
}
126
+
127
+static void cbw_init(void)
128
+{
129
+ bdrv_register(&bdrv_cbw_filter);
130
+}
131
+
132
+block_init(cbw_init);
133
--
134
2.31.1
135
136
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Acked-by: Markus Armbruster <armbru@redhat.com>
6
Message-Id: <20210824083856.17408-23-vsementsov@virtuozzo.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
qapi/block-core.json | 25 +++++++++++++++++++++++--
10
1 file changed, 23 insertions(+), 2 deletions(-)
11
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
17
# @blklogwrites: Since 3.0
18
# @blkreplay: Since 4.2
19
# @compress: Since 5.0
20
+# @copy-before-write: Since 6.2
21
#
22
# Since: 2.9
23
##
24
{ 'enum': 'BlockdevDriver',
25
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
26
- 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
27
- 'gluster',
28
+ 'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg',
29
+ 'file', 'ftp', 'ftps', 'gluster',
30
{'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
31
{'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
32
'http', 'https', 'iscsi',
33
@@ -XXX,XX +XXX,XX @@
34
'base': 'BlockdevOptionsGenericFormat',
35
'data': { '*bottom': 'str' } }
36
37
+##
38
+# @BlockdevOptionsCbw:
39
+#
40
+# Driver specific block device options for the copy-before-write driver,
41
+# which does so called copy-before-write operations: when data is
42
+# written to the filter, the filter first reads corresponding blocks
43
+# from its file child and copies them to @target child. After successfully
44
+# copying, the write request is propagated to file child. If copying
45
+# fails, the original write request is failed too and no data is written
46
+# to file child.
47
+#
48
+# @target: The target for copy-before-write operations.
49
+#
50
+# Since: 6.2
51
+##
52
+{ 'struct': 'BlockdevOptionsCbw',
53
+ 'base': 'BlockdevOptionsGenericFormat',
54
+ 'data': { 'target': 'BlockdevRef' } }
55
+
56
##
57
# @BlockdevOptions:
58
#
59
@@ -XXX,XX +XXX,XX @@
60
'bochs': 'BlockdevOptionsGenericFormat',
61
'cloop': 'BlockdevOptionsGenericFormat',
62
'compress': 'BlockdevOptionsGenericFormat',
63
+ 'copy-before-write':'BlockdevOptionsCbw',
64
'copy-on-read':'BlockdevOptionsCor',
65
'dmg': 'BlockdevOptionsGenericFormat',
66
'file': 'BlockdevOptionsFile',
67
--
68
2.31.1
69
70
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
- use shorter construction
4
- don't create new dict if not needed
5
- drop extra unpacking key-val arguments
6
- drop extra default values
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: John Snow <jsnow@redhat.com>
11
Message-Id: <20210824083856.17408-24-vsementsov@virtuozzo.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
python/qemu/machine/machine.py | 18 ++++++++----------
15
1 file changed, 8 insertions(+), 10 deletions(-)
16
17
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/python/qemu/machine/machine.py
20
+++ b/python/qemu/machine/machine.py
21
@@ -XXX,XX +XXX,XX @@ def _qmp(self) -> QEMUMonitorProtocol:
22
return self._qmp_connection
23
24
@classmethod
25
- def _qmp_args(cls, _conv_keys: bool = True, **args: Any) -> Dict[str, Any]:
26
- qmp_args = dict()
27
- for key, value in args.items():
28
- if _conv_keys:
29
- qmp_args[key.replace('_', '-')] = value
30
- else:
31
- qmp_args[key] = value
32
- return qmp_args
33
+ def _qmp_args(cls, conv_keys: bool,
34
+ args: Dict[str, Any]) -> Dict[str, object]:
35
+ if conv_keys:
36
+ return {k.replace('_', '-'): v for k, v in args.items()}
37
+
38
+ return args
39
40
def qmp(self, cmd: str,
41
conv_keys: bool = True,
42
@@ -XXX,XX +XXX,XX @@ def qmp(self, cmd: str,
43
"""
44
Invoke a QMP command and return the response dict
45
"""
46
- qmp_args = self._qmp_args(conv_keys, **args)
47
+ qmp_args = self._qmp_args(conv_keys, args)
48
return self._qmp.cmd(cmd, args=qmp_args)
49
50
def command(self, cmd: str,
51
@@ -XXX,XX +XXX,XX @@ def command(self, cmd: str,
52
On success return the response dict.
53
On failure raise an exception.
54
"""
55
- qmp_args = self._qmp_args(conv_keys, **args)
56
+ qmp_args = self._qmp_args(conv_keys, args)
57
return self._qmp.command(cmd, **qmp_args)
58
59
def get_qmp_event(self, wait: bool = False) -> Optional[QMPMessage]:
60
--
61
2.31.1
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We often call qmp() with unpacking dict, like qmp('foo', **{...}).
4
mypy don't really like it, it thinks that passed unpacked dict is a
5
positional argument and complains that it type should be bool (because
6
second argument of qmp() is conv_keys: bool).
7
8
Allow passing dict directly, simplifying interface, and giving a way to
9
satisfy mypy.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: John Snow <jsnow@redhat.com>
14
Message-Id: <20210824083856.17408-25-vsementsov@virtuozzo.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
17
python/qemu/machine/machine.py | 12 +++++++++++-
18
1 file changed, 11 insertions(+), 1 deletion(-)
19
20
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
21
index XXXXXXX..XXXXXXX 100644
22
--- a/python/qemu/machine/machine.py
23
+++ b/python/qemu/machine/machine.py
24
@@ -XXX,XX +XXX,XX @@ def _qmp_args(cls, conv_keys: bool,
25
return args
26
27
def qmp(self, cmd: str,
28
- conv_keys: bool = True,
29
+ args_dict: Optional[Dict[str, object]] = None,
30
+ conv_keys: Optional[bool] = None,
31
**args: Any) -> QMPMessage:
32
"""
33
Invoke a QMP command and return the response dict
34
"""
35
+ if args_dict is not None:
36
+ assert not args
37
+ assert conv_keys is None
38
+ args = args_dict
39
+ conv_keys = False
40
+
41
+ if conv_keys is None:
42
+ conv_keys = True
43
+
44
qmp_args = self._qmp_args(conv_keys, args)
45
return self._qmp.cmd(cmd, args=qmp_args)
46
47
--
48
2.31.1
49
50
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
mypy thinks that return value of these methods in subclusses is
4
QEMUMachine, which is wrong. So, make typing smarter.
5
6
Suggested-by: John Snow <jsnow@redhat.com>
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210824083856.17408-26-vsementsov@virtuozzo.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
python/qemu/machine/machine.py | 10 +++++++---
13
1 file changed, 7 insertions(+), 3 deletions(-)
14
15
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/python/qemu/machine/machine.py
18
+++ b/python/qemu/machine/machine.py
19
@@ -XXX,XX +XXX,XX @@
20
Sequence,
21
Tuple,
22
Type,
23
+ TypeVar,
24
)
25
26
from qemu.qmp import ( # pylint: disable=import-error
27
@@ -XXX,XX +XXX,XX @@ class AbnormalShutdown(QEMUMachineError):
28
"""
29
30
31
+_T = TypeVar('_T', bound='QEMUMachine')
32
+
33
+
34
class QEMUMachine:
35
"""
36
A QEMU VM.
37
@@ -XXX,XX +XXX,XX @@ def __init__(self,
38
self._remove_files: List[str] = []
39
self._user_killed = False
40
41
- def __enter__(self) -> 'QEMUMachine':
42
+ def __enter__(self: _T) -> _T:
43
return self
44
45
def __exit__(self,
46
@@ -XXX,XX +XXX,XX @@ def add_monitor_null(self) -> None:
47
self._args.append('-monitor')
48
self._args.append('null')
49
50
- def add_fd(self, fd: int, fdset: int,
51
- opaque: str, opts: str = '') -> 'QEMUMachine':
52
+ def add_fd(self: _T, fd: int, fdset: int,
53
+ opaque: str, opts: str = '') -> _T:
54
"""
55
Pass a file descriptor to the VM
56
"""
57
--
58
2.31.1
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Here:
4
- long line
5
- move to new interface of vm.qmp() (direct passing dict), to avoid
6
mypy false-positive, as it thinks that unpacked dict is a positional
7
argument.
8
- extra parenthesis
9
- handle event_wait possible None value
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20210824083856.17408-27-vsementsov@virtuozzo.com>
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
---
16
tests/qemu-iotests/222 | 20 +++++++++++---------
17
tests/qemu-iotests/297 | 2 +-
18
2 files changed, 12 insertions(+), 10 deletions(-)
19
20
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/222
23
+++ b/tests/qemu-iotests/222
24
@@ -XXX,XX +XXX,XX @@ remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1]
25
26
with iotests.FilePath('base.img') as base_img_path, \
27
iotests.FilePath('fleece.img') as fleece_img_path, \
28
- iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \
29
+ iotests.FilePath('nbd.sock',
30
+ base_dir=iotests.sock_dir) as nbd_sock_path, \
31
iotests.VM() as vm:
32
33
log('--- Setting up images ---')
34
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
35
tgt_node = "fleeceNode"
36
37
# create tgt_node backed by src_node
38
- log(vm.qmp("blockdev-add", **{
39
+ log(vm.qmp("blockdev-add", {
40
"driver": "qcow2",
41
"node-name": tgt_node,
42
"file": {
43
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
44
45
nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
46
log(vm.qmp("nbd-server-start",
47
- **{"addr": { "type": "unix",
48
- "data": { "path": nbd_sock_path } } }))
49
+ {"addr": { "type": "unix",
50
+ "data": { "path": nbd_sock_path } } }))
51
52
log(vm.qmp("nbd-server-add", device=tgt_node))
53
54
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
55
log('--- Sanity Check ---')
56
log('')
57
58
- for p in (patterns + zeroes):
59
+ for p in patterns + zeroes:
60
cmd = "read -P%s %s %s" % p
61
log(cmd)
62
assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
63
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
64
log('--- Verifying Data ---')
65
log('')
66
67
- for p in (patterns + zeroes):
68
+ for p in patterns + zeroes:
69
cmd = "read -P%s %s %s" % p
70
log(cmd)
71
assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
72
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
73
log('')
74
75
log(vm.qmp('block-job-cancel', device=src_node))
76
- log(vm.event_wait('BLOCK_JOB_CANCELLED'),
77
- filters=[iotests.filter_qmp_event])
78
+ e = vm.event_wait('BLOCK_JOB_CANCELLED')
79
+ assert e is not None
80
+ log(e, filters=[iotests.filter_qmp_event])
81
log(vm.qmp('nbd-server-stop'))
82
log(vm.qmp('blockdev-del', node_name=tgt_node))
83
vm.shutdown()
84
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
85
log('--- Confirming writes ---')
86
log('')
87
88
- for p in (overwrite + remainder):
89
+ for p in overwrite + remainder:
90
cmd = "read -P%s %s %s" % p
91
log(cmd)
92
assert qemu_io_silent(base_img_path, '-c', cmd) == 0
93
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
94
index XXXXXXX..XXXXXXX 100755
95
--- a/tests/qemu-iotests/297
96
+++ b/tests/qemu-iotests/297
97
@@ -XXX,XX +XXX,XX @@ SKIP_FILES = (
98
'096', '118', '124', '132', '136', '139', '147', '148', '149',
99
'151', '152', '155', '163', '165', '169', '194', '196', '199', '202',
100
'203', '205', '206', '207', '208', '210', '211', '212', '213', '216',
101
- '218', '219', '222', '224', '228', '234', '235', '236', '237', '238',
102
+ '218', '219', '224', '228', '234', '235', '236', '237', '238',
103
'240', '242', '245', '246', '248', '255', '256', '257', '258', '260',
104
'262', '264', '266', '274', '277', '280', '281', '295', '296', '298',
105
'299', '302', '303', '304', '307',
106
--
107
2.31.1
108
109
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
The file use both single and double quotes for strings. Let's be
4
consistent.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-28-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
tests/qemu-iotests/222 | 68 +++++++++++++++++++++---------------------
12
1 file changed, 34 insertions(+), 34 deletions(-)
13
14
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/222
17
+++ b/tests/qemu-iotests/222
18
@@ -XXX,XX +XXX,XX @@ iotests.script_initialize(
19
supported_platforms=['linux'],
20
)
21
22
-patterns = [("0x5d", "0", "64k"),
23
- ("0xd5", "1M", "64k"),
24
- ("0xdc", "32M", "64k"),
25
- ("0xcd", "0x3ff0000", "64k")] # 64M - 64K
26
+patterns = [('0x5d', '0', '64k'),
27
+ ('0xd5', '1M', '64k'),
28
+ ('0xdc', '32M', '64k'),
29
+ ('0xcd', '0x3ff0000', '64k')] # 64M - 64K
30
31
-overwrite = [("0xab", "0", "64k"), # Full overwrite
32
- ("0xad", "0x00f8000", "64k"), # Partial-left (1M-32K)
33
- ("0x1d", "0x2008000", "64k"), # Partial-right (32M+32K)
34
- ("0xea", "0x3fe0000", "64k")] # Adjacent-left (64M - 128K)
35
+overwrite = [('0xab', '0', '64k'), # Full overwrite
36
+ ('0xad', '0x00f8000', '64k'), # Partial-left (1M-32K)
37
+ ('0x1d', '0x2008000', '64k'), # Partial-right (32M+32K)
38
+ ('0xea', '0x3fe0000', '64k')] # Adjacent-left (64M - 128K)
39
40
-zeroes = [("0", "0x00f8000", "32k"), # Left-end of partial-left (1M-32K)
41
- ("0", "0x2010000", "32k"), # Right-end of partial-right (32M+64K)
42
- ("0", "0x3fe0000", "64k")] # overwrite[3]
43
+zeroes = [('0', '0x00f8000', '32k'), # Left-end of partial-left (1M-32K)
44
+ ('0', '0x2010000', '32k'), # Right-end of partial-right (32M+64K)
45
+ ('0', '0x3fe0000', '64k')] # overwrite[3]
46
47
-remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1]
48
- ("0xdc", "32M", "32k"), # Left-end of partial-right [2]
49
- ("0xcd", "0x3ff0000", "64k")] # patterns[3]
50
+remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
51
+ ('0xdc', '32M', '32k'), # Left-end of partial-right [2]
52
+ ('0xcd', '0x3ff0000', '64k')] # patterns[3]
53
54
with iotests.FilePath('base.img') as base_img_path, \
55
iotests.FilePath('fleece.img') as fleece_img_path, \
56
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
57
log('')
58
59
assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
60
- assert qemu_img('create', '-f', "qcow2", fleece_img_path, '64M') == 0
61
+ assert qemu_img('create', '-f', 'qcow2', fleece_img_path, '64M') == 0
62
63
for p in patterns:
64
qemu_io('-f', iotests.imgfmt,
65
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
66
log('--- Setting up Fleecing Graph ---')
67
log('')
68
69
- src_node = "drive0"
70
- tgt_node = "fleeceNode"
71
+ src_node = 'drive0'
72
+ tgt_node = 'fleeceNode'
73
74
# create tgt_node backed by src_node
75
- log(vm.qmp("blockdev-add", {
76
- "driver": "qcow2",
77
- "node-name": tgt_node,
78
- "file": {
79
- "driver": "file",
80
- "filename": fleece_img_path,
81
+ log(vm.qmp('blockdev-add', {
82
+ 'driver': 'qcow2',
83
+ 'node-name': tgt_node,
84
+ 'file': {
85
+ 'driver': 'file',
86
+ 'filename': fleece_img_path,
87
},
88
- "backing": src_node,
89
+ 'backing': src_node,
90
}))
91
92
# Establish COW from source to fleecing node
93
- log(vm.qmp("blockdev-backup",
94
+ log(vm.qmp('blockdev-backup',
95
device=src_node,
96
target=tgt_node,
97
- sync="none"))
98
+ sync='none'))
99
100
log('')
101
log('--- Setting up NBD Export ---')
102
log('')
103
104
nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
105
- log(vm.qmp("nbd-server-start",
106
- {"addr": { "type": "unix",
107
- "data": { "path": nbd_sock_path } } }))
108
+ log(vm.qmp('nbd-server-start',
109
+ {'addr': { 'type': 'unix',
110
+ 'data': { 'path': nbd_sock_path } } }))
111
112
- log(vm.qmp("nbd-server-add", device=tgt_node))
113
+ log(vm.qmp('nbd-server-add', device=tgt_node))
114
115
log('')
116
log('--- Sanity Check ---')
117
log('')
118
119
for p in patterns + zeroes:
120
- cmd = "read -P%s %s %s" % p
121
+ cmd = 'read -P%s %s %s' % p
122
log(cmd)
123
assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
124
125
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
126
log('')
127
128
for p in overwrite:
129
- cmd = "write -P%s %s %s" % p
130
+ cmd = 'write -P%s %s %s' % p
131
log(cmd)
132
log(vm.hmp_qemu_io(src_node, cmd))
133
134
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
135
log('')
136
137
for p in patterns + zeroes:
138
- cmd = "read -P%s %s %s" % p
139
+ cmd = 'read -P%s %s %s' % p
140
log(cmd)
141
assert qemu_io_silent('-r', '-f', 'raw', '-c', cmd, nbd_uri) == 0
142
143
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
144
log('')
145
146
for p in overwrite + remainder:
147
- cmd = "read -P%s %s %s" % p
148
+ cmd = 'read -P%s %s %s' % p
149
log(cmd)
150
assert qemu_io_silent(base_img_path, '-c', cmd) == 0
151
152
--
153
2.31.1
154
155
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Give a good name to test file.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Message-Id: <20210824083856.17408-29-vsementsov@virtuozzo.com>
8
[hreitz: Adjust .gitlab-ci.d/buildtest.yml]
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
.gitlab-ci.d/buildtest.yml | 6 +++---
12
tests/qemu-iotests/{222 => tests/image-fleecing} | 0
13
tests/qemu-iotests/{222.out => tests/image-fleecing.out} | 0
14
3 files changed, 3 insertions(+), 3 deletions(-)
15
rename tests/qemu-iotests/{222 => tests/image-fleecing} (100%)
16
rename tests/qemu-iotests/{222.out => tests/image-fleecing.out} (100%)
17
18
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
19
index XXXXXXX..XXXXXXX 100644
20
--- a/.gitlab-ci.d/buildtest.yml
21
+++ b/.gitlab-ci.d/buildtest.yml
22
@@ -XXX,XX +XXX,XX @@ build-tcg-disabled:
23
- cd tests/qemu-iotests/
24
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
25
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
26
- 170 171 183 184 192 194 208 221 222 226 227 236 253 277
27
+ 170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing
28
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
29
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
30
- 208 209 216 218 222 227 234 246 247 248 250 254 255 257 258
31
- 260 261 262 263 264 270 272 273 277 279
32
+ 208 209 216 218 227 234 246 247 248 250 254 255 257 258
33
+ 260 261 262 263 264 270 272 273 277 279 image-fleecing
34
35
build-user:
36
extends: .native_build_job_template
37
diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/tests/image-fleecing
38
similarity index 100%
39
rename from tests/qemu-iotests/222
40
rename to tests/qemu-iotests/tests/image-fleecing
41
diff --git a/tests/qemu-iotests/222.out b/tests/qemu-iotests/tests/image-fleecing.out
42
similarity index 100%
43
rename from tests/qemu-iotests/222.out
44
rename to tests/qemu-iotests/tests/image-fleecing.out
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: John Snow <jsnow@redhat.com>
6
Message-Id: <20210824083856.17408-30-vsementsov@virtuozzo.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
tests/qemu-iotests/iotests.py | 5 +++--
10
1 file changed, 3 insertions(+), 2 deletions(-)
11
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
13
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/iotests.py
16
@@ -XXX,XX +XXX,XX @@ def resume_drive(self, drive: str) -> None:
17
self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
18
19
def hmp_qemu_io(self, drive: str, cmd: str,
20
- use_log: bool = False) -> QMPMessage:
21
+ use_log: bool = False, qdev: bool = False) -> QMPMessage:
22
"""Write to a given drive using an HMP command"""
23
- return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log)
24
+ d = '-d ' if qdev else ''
25
+ return self.hmp(f'qemu-io {d}{drive} "{cmd}"', use_log=use_log)
26
27
def flatten_qmp_object(self, obj, output=None, basestr=''):
28
if output is None:
29
--
30
2.31.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Define scsi device to operate with it by qom-set in further patch.
4
5
Give a new node-name to source block node, to not look like device
6
name.
7
8
Job now don't want to work without giving explicit id, so, let's call
9
it "fleecing".
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <20210824083856.17408-31-vsementsov@virtuozzo.com>
14
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
---
16
tests/qemu-iotests/tests/image-fleecing | 12 ++++++++----
17
tests/qemu-iotests/tests/image-fleecing.out | 2 +-
18
2 files changed, 9 insertions(+), 5 deletions(-)
19
20
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
21
index XXXXXXX..XXXXXXX 100755
22
--- a/tests/qemu-iotests/tests/image-fleecing
23
+++ b/tests/qemu-iotests/tests/image-fleecing
24
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
25
log('--- Launching VM ---')
26
log('')
27
28
- vm.add_drive(base_img_path)
29
+ src_node = 'source'
30
+ vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
31
+ f'file.filename={base_img_path},node-name={src_node}')
32
+ vm.add_device('virtio-scsi')
33
+ vm.add_device(f'scsi-hd,id=sda,drive={src_node}')
34
vm.launch()
35
log('Done')
36
37
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
38
log('--- Setting up Fleecing Graph ---')
39
log('')
40
41
- src_node = 'drive0'
42
tgt_node = 'fleeceNode'
43
44
# create tgt_node backed by src_node
45
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
46
47
# Establish COW from source to fleecing node
48
log(vm.qmp('blockdev-backup',
49
+ job_id='fleecing',
50
device=src_node,
51
target=tgt_node,
52
sync='none'))
53
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
54
for p in overwrite:
55
cmd = 'write -P%s %s %s' % p
56
log(cmd)
57
- log(vm.hmp_qemu_io(src_node, cmd))
58
+ log(vm.hmp_qemu_io('/machine/peripheral/sda', cmd, qdev=True))
59
60
log('')
61
log('--- Verifying Data ---')
62
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
63
log('--- Cleanup ---')
64
log('')
65
66
- log(vm.qmp('block-job-cancel', device=src_node))
67
+ log(vm.qmp('block-job-cancel', device='fleecing'))
68
e = vm.event_wait('BLOCK_JOB_CANCELLED')
69
assert e is not None
70
log(e, filters=[iotests.filter_qmp_event])
71
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
72
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/tests/image-fleecing.out
74
+++ b/tests/qemu-iotests/tests/image-fleecing.out
75
@@ -XXX,XX +XXX,XX @@ read -P0 0x3fe0000 64k
76
--- Cleanup ---
77
78
{"return": {}}
79
-{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
80
+{"data": {"device": "fleecing", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
81
{"return": {}}
82
{"return": {}}
83
84
--
85
2.31.1
86
87
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Actually target of backup(sync=None) is not a final backup target:
4
image fleecing is intended to be used with external tool, which will
5
copy data from fleecing node to some real backup target.
6
7
Also, we are going to add a test case for "push backup with fleecing",
8
where instead of exporting fleecing node by NBD, we'll start a backup
9
job from fleecing node to real backup target.
10
11
To avoid confusion, let's rename temporary fleecing node now.
12
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <20210824083856.17408-32-vsementsov@virtuozzo.com>
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
---
18
tests/qemu-iotests/tests/image-fleecing | 14 +++++++-------
19
1 file changed, 7 insertions(+), 7 deletions(-)
20
21
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
22
index XXXXXXX..XXXXXXX 100755
23
--- a/tests/qemu-iotests/tests/image-fleecing
24
+++ b/tests/qemu-iotests/tests/image-fleecing
25
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
26
log('')
27
28
src_node = 'source'
29
+ tmp_node = 'temp'
30
vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
31
f'file.filename={base_img_path},node-name={src_node}')
32
vm.add_device('virtio-scsi')
33
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
34
log('--- Setting up Fleecing Graph ---')
35
log('')
36
37
- tgt_node = 'fleeceNode'
38
39
- # create tgt_node backed by src_node
40
+ # create tmp_node backed by src_node
41
log(vm.qmp('blockdev-add', {
42
'driver': 'qcow2',
43
- 'node-name': tgt_node,
44
+ 'node-name': tmp_node,
45
'file': {
46
'driver': 'file',
47
'filename': fleece_img_path,
48
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
49
log(vm.qmp('blockdev-backup',
50
job_id='fleecing',
51
device=src_node,
52
- target=tgt_node,
53
+ target=tmp_node,
54
sync='none'))
55
56
log('')
57
log('--- Setting up NBD Export ---')
58
log('')
59
60
- nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
61
+ nbd_uri = 'nbd+unix:///%s?socket=%s' % (tmp_node, nbd_sock_path)
62
log(vm.qmp('nbd-server-start',
63
{'addr': { 'type': 'unix',
64
'data': { 'path': nbd_sock_path } } }))
65
66
- log(vm.qmp('nbd-server-add', device=tgt_node))
67
+ log(vm.qmp('nbd-server-add', device=tmp_node))
68
69
log('')
70
log('--- Sanity Check ---')
71
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
72
assert e is not None
73
log(e, filters=[iotests.filter_qmp_event])
74
log(vm.qmp('nbd-server-stop'))
75
- log(vm.qmp('blockdev-del', node_name=tgt_node))
76
+ log(vm.qmp('blockdev-del', node_name=tmp_node))
77
vm.shutdown()
78
79
log('')
80
--
81
2.31.1
82
83
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to add a test-case with some behavior modifications. So,
4
let's prepare a function to be reused.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-33-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
tests/qemu-iotests/tests/image-fleecing | 19 +++++++++++++------
12
1 file changed, 13 insertions(+), 6 deletions(-)
13
14
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/tests/image-fleecing
17
+++ b/tests/qemu-iotests/tests/image-fleecing
18
@@ -XXX,XX +XXX,XX @@ remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
19
('0xdc', '32M', '32k'), # Left-end of partial-right [2]
20
('0xcd', '0x3ff0000', '64k')] # patterns[3]
21
22
-with iotests.FilePath('base.img') as base_img_path, \
23
- iotests.FilePath('fleece.img') as fleece_img_path, \
24
- iotests.FilePath('nbd.sock',
25
- base_dir=iotests.sock_dir) as nbd_sock_path, \
26
- iotests.VM() as vm:
27
-
28
+def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
29
log('--- Setting up images ---')
30
log('')
31
32
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
33
34
log('')
35
log('Done')
36
+
37
+
38
+def test():
39
+ with iotests.FilePath('base.img') as base_img_path, \
40
+ iotests.FilePath('fleece.img') as fleece_img_path, \
41
+ iotests.FilePath('nbd.sock',
42
+ base_dir=iotests.sock_dir) as nbd_sock_path, \
43
+ iotests.VM() as vm:
44
+ do_test(base_img_path, fleece_img_path, nbd_sock_path, vm)
45
+
46
+
47
+test()
48
--
49
2.31.1
50
51
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
New fleecing method becomes available: copy-before-write filter.
4
5
Actually we don't need backup job to setup image fleecing. Add test
6
for new recommended way of image fleecing.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-34-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
tests/qemu-iotests/tests/image-fleecing | 50 +++++++++-----
14
tests/qemu-iotests/tests/image-fleecing.out | 72 +++++++++++++++++++++
15
2 files changed, 107 insertions(+), 15 deletions(-)
16
17
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/tests/image-fleecing
20
+++ b/tests/qemu-iotests/tests/image-fleecing
21
@@ -XXX,XX +XXX,XX @@ remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
22
('0xdc', '32M', '32k'), # Left-end of partial-right [2]
23
('0xcd', '0x3ff0000', '64k')] # patterns[3]
24
25
-def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
26
+def do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm):
27
log('--- Setting up images ---')
28
log('')
29
30
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
31
32
src_node = 'source'
33
tmp_node = 'temp'
34
+ qom_path = '/machine/peripheral/sda'
35
vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
36
f'file.filename={base_img_path},node-name={src_node}')
37
vm.add_device('virtio-scsi')
38
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
39
'backing': src_node,
40
}))
41
42
- # Establish COW from source to fleecing node
43
- log(vm.qmp('blockdev-backup',
44
- job_id='fleecing',
45
- device=src_node,
46
- target=tmp_node,
47
- sync='none'))
48
+ # Establish CBW from source to fleecing node
49
+ if use_cbw:
50
+ log(vm.qmp('blockdev-add', {
51
+ 'driver': 'copy-before-write',
52
+ 'node-name': 'fl-cbw',
53
+ 'file': src_node,
54
+ 'target': tmp_node
55
+ }))
56
+
57
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value='fl-cbw'))
58
+ else:
59
+ log(vm.qmp('blockdev-backup',
60
+ job_id='fleecing',
61
+ device=src_node,
62
+ target=tmp_node,
63
+ sync='none'))
64
65
log('')
66
log('--- Setting up NBD Export ---')
67
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
68
for p in overwrite:
69
cmd = 'write -P%s %s %s' % p
70
log(cmd)
71
- log(vm.hmp_qemu_io('/machine/peripheral/sda', cmd, qdev=True))
72
+ log(vm.hmp_qemu_io(qom_path, cmd, qdev=True))
73
74
log('')
75
log('--- Verifying Data ---')
76
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
77
log('--- Cleanup ---')
78
log('')
79
80
- log(vm.qmp('block-job-cancel', device='fleecing'))
81
- e = vm.event_wait('BLOCK_JOB_CANCELLED')
82
- assert e is not None
83
- log(e, filters=[iotests.filter_qmp_event])
84
+ if use_cbw:
85
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value=src_node))
86
+ log(vm.qmp('blockdev-del', node_name='fl-cbw'))
87
+ else:
88
+ log(vm.qmp('block-job-cancel', device='fleecing'))
89
+ e = vm.event_wait('BLOCK_JOB_CANCELLED')
90
+ assert e is not None
91
+ log(e, filters=[iotests.filter_qmp_event])
92
+
93
log(vm.qmp('nbd-server-stop'))
94
log(vm.qmp('blockdev-del', node_name=tmp_node))
95
vm.shutdown()
96
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
97
log('Done')
98
99
100
-def test():
101
+def test(use_cbw):
102
with iotests.FilePath('base.img') as base_img_path, \
103
iotests.FilePath('fleece.img') as fleece_img_path, \
104
iotests.FilePath('nbd.sock',
105
base_dir=iotests.sock_dir) as nbd_sock_path, \
106
iotests.VM() as vm:
107
- do_test(base_img_path, fleece_img_path, nbd_sock_path, vm)
108
+ do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm)
109
+
110
111
+log('=== Test backup(sync=none) based fleecing ===\n')
112
+test(False)
113
114
-test()
115
+log('=== Test filter based fleecing ===\n')
116
+test(True)
117
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
118
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qemu-iotests/tests/image-fleecing.out
120
+++ b/tests/qemu-iotests/tests/image-fleecing.out
121
@@ -XXX,XX +XXX,XX @@
122
+=== Test backup(sync=none) based fleecing ===
123
+
124
--- Setting up images ---
125
126
Done
127
@@ -XXX,XX +XXX,XX @@ read -P0xdc 32M 32k
128
read -P0xcd 0x3ff0000 64k
129
130
Done
131
+=== Test filter based fleecing ===
132
+
133
+--- Setting up images ---
134
+
135
+Done
136
+
137
+--- Launching VM ---
138
+
139
+Done
140
+
141
+--- Setting up Fleecing Graph ---
142
+
143
+{"return": {}}
144
+{"return": {}}
145
+{"return": {}}
146
+
147
+--- Setting up NBD Export ---
148
+
149
+{"return": {}}
150
+{"return": {}}
151
+
152
+--- Sanity Check ---
153
+
154
+read -P0x5d 0 64k
155
+read -P0xd5 1M 64k
156
+read -P0xdc 32M 64k
157
+read -P0xcd 0x3ff0000 64k
158
+read -P0 0x00f8000 32k
159
+read -P0 0x2010000 32k
160
+read -P0 0x3fe0000 64k
161
+
162
+--- Testing COW ---
163
+
164
+write -P0xab 0 64k
165
+{"return": ""}
166
+write -P0xad 0x00f8000 64k
167
+{"return": ""}
168
+write -P0x1d 0x2008000 64k
169
+{"return": ""}
170
+write -P0xea 0x3fe0000 64k
171
+{"return": ""}
172
+
173
+--- Verifying Data ---
174
+
175
+read -P0x5d 0 64k
176
+read -P0xd5 1M 64k
177
+read -P0xdc 32M 64k
178
+read -P0xcd 0x3ff0000 64k
179
+read -P0 0x00f8000 32k
180
+read -P0 0x2010000 32k
181
+read -P0 0x3fe0000 64k
182
+
183
+--- Cleanup ---
184
+
185
+{"return": {}}
186
+{"return": {}}
187
+{"return": {}}
188
+{"return": {}}
189
+
190
+--- Confirming writes ---
191
+
192
+read -P0xab 0 64k
193
+read -P0xad 0x00f8000 64k
194
+read -P0x1d 0x2008000 64k
195
+read -P0xea 0x3fe0000 64k
196
+read -P0xd5 0x108000 32k
197
+read -P0xdc 32M 32k
198
+read -P0xcd 0x3ff0000 64k
199
+
200
+Done
201
--
202
2.31.1
203
204
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This regression test demonstrates that detect-zeroes works with
2
registered buffers. Bug details:
3
https://gitlab.com/qemu-project/qemu/-/issues/1404
2
4
3
The only caller pass copy_range and compress both false. Let's just
5
Reviewed-by: Eric Blake <eblake@redhat.com>
4
drop these arguments.
6
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20230207203719.242926-5-stefanha@redhat.com>
9
---
10
.../tests/detect-zeroes-registered-buf | 58 +++++++++++++++++++
11
.../tests/detect-zeroes-registered-buf.out | 7 +++
12
2 files changed, 65 insertions(+)
13
create mode 100755 tests/qemu-iotests/tests/detect-zeroes-registered-buf
14
create mode 100644 tests/qemu-iotests/tests/detect-zeroes-registered-buf.out
5
15
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
diff --git a/tests/qemu-iotests/tests/detect-zeroes-registered-buf b/tests/qemu-iotests/tests/detect-zeroes-registered-buf
7
Message-Id: <20210824083856.17408-35-vsementsov@virtuozzo.com>
17
new file mode 100755
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
18
index XXXXXXX..XXXXXXX
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
19
--- /dev/null
10
---
20
+++ b/tests/qemu-iotests/tests/detect-zeroes-registered-buf
11
include/block/block-copy.h | 1 -
21
@@ -XXX,XX +XXX,XX @@
12
block/block-copy.c | 5 ++---
22
+#!/usr/bin/env bash
13
block/copy-before-write.c | 2 +-
23
+# group: rw auto quick
14
3 files changed, 3 insertions(+), 5 deletions(-)
24
+#
15
25
+# Check that detect-zeroes=unmap works on writes with registered I/O buffers.
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
26
+# This is a regression test for
17
index XXXXXXX..XXXXXXX 100644
27
+# https://gitlab.com/qemu-project/qemu/-/issues/1404 where I/O requests failed
18
--- a/include/block/block-copy.h
28
+# unexpectedly.
19
+++ b/include/block/block-copy.h
29
+#
20
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
30
+# Copyright Red Hat
21
typedef struct BlockCopyCallState BlockCopyCallState;
31
+#
22
32
+# This program is free software; you can redistribute it and/or modify
23
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
33
+# it under the terms of the GNU General Public License as published by
24
- bool use_copy_range, bool compress,
34
+# the Free Software Foundation; either version 2 of the License, or
25
Error **errp);
35
+# (at your option) any later version.
26
36
+#
27
/* Function should be called prior any actual copy request */
37
+# This program is distributed in the hope that it will be useful,
28
diff --git a/block/block-copy.c b/block/block-copy.c
38
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
29
index XXXXXXX..XXXXXXX 100644
39
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30
--- a/block/block-copy.c
40
+# GNU General Public License for more details.
31
+++ b/block/block-copy.c
41
+#
32
@@ -XXX,XX +XXX,XX @@ static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
42
+# You should have received a copy of the GNU General Public License
33
}
43
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
34
44
+#
35
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
45
+
36
- bool use_copy_range,
46
+# creator
37
- bool compress, Error **errp)
47
+owner=stefanha@redhat.com
38
+ Error **errp)
48
+
39
{
49
+seq=`basename $0`
40
BlockCopyState *s;
50
+echo "QA output created by $seq"
41
int64_t cluster_size;
51
+
42
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
52
+status=1    # failure is the default!
43
cluster_size),
53
+
44
};
54
+_cleanup()
45
55
+{
46
- block_copy_set_copy_opts(s, use_copy_range, compress);
56
+    _cleanup_test_img
47
+ block_copy_set_copy_opts(s, false, false);
57
+}
48
58
+trap "_cleanup; exit \$status" 0 1 2 3 15
49
ratelimit_init(&s->rate_limit);
59
+
50
qemu_co_mutex_init(&s->lock);
60
+# get standard environment, filters and checks
51
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
61
+cd ..
52
index XXXXXXX..XXXXXXX 100644
62
+. ./common.rc
53
--- a/block/copy-before-write.c
63
+. ./common.filter
54
+++ b/block/copy-before-write.c
64
+
55
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
65
+_supported_fmt qcow2
56
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
66
+_supported_proto generic
57
bs->file->bs->supported_zero_flags);
67
+
58
68
+size=128M
59
- s->bcs = block_copy_state_new(bs->file, s->target, false, false, errp);
69
+_make_test_img $size
60
+ s->bcs = block_copy_state_new(bs->file, s->target, errp);
70
+IMGSPEC="driver=$IMGFMT,file.filename=$TEST_IMG,discard=unmap,detect-zeroes=unmap"
61
if (!s->bcs) {
71
+
62
error_prepend(errp, "Cannot create block-copy-state: ");
72
+echo
63
return -EINVAL;
73
+echo "== writing zero buffer to image =="
74
+QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS_NO_FMT" $QEMU_IO -c "write -r -P 0 0 4k" --image-opts "$IMGSPEC" | _filter_qemu_io
75
+
76
+# success, all done
77
+echo "*** done"
78
+rm -f $seq.full
79
+status=0
80
diff --git a/tests/qemu-iotests/tests/detect-zeroes-registered-buf.out b/tests/qemu-iotests/tests/detect-zeroes-registered-buf.out
81
new file mode 100644
82
index XXXXXXX..XXXXXXX
83
--- /dev/null
84
+++ b/tests/qemu-iotests/tests/detect-zeroes-registered-buf.out
85
@@ -XXX,XX +XXX,XX @@
86
+QA output created by detect-zeroes-registered-buf
87
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
88
+
89
+== writing zero buffer to image ==
90
+wrote 4096/4096 bytes at offset 0
91
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
92
+*** done
64
--
93
--
65
2.31.1
94
2.39.1
66
67
diff view generated by jsdifflib