1
The following changes since commit ec397e90d21269037280633b6058d1f280e27667:
1
The following changes since commit eaefea537b476cb853e2edbdc68e969ec777e4bb:
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
Merge remote-tracking branch 'remotes/mjt/tags/trivial-patches-fetch' into staging (2017-12-18 14:17:42 +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
git://github.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 7a9dda0d7f9831c2432620dcfefdadbb7ae888dc:
10
10
11
block/file-win32: add reopen handlers (2021-09-01 14:38:08 +0200)
11
qemu-iotests: add 203 savevm with IOThreads test (2017-12-19 10:25:09 +0000)
12
13
----------------------------------------------------------------
14
Pull request
15
16
v2:
17
* Fixed incorrect virtio_blk_data_plane_create() local_err refactoring in
18
"hw/block: Use errp directly rather than local_err" that broke virtio-blk
19
over virtio-mmio [Peter]
20
21
----------------------------------------------------------------
22
23
Mao Zhongyi (4):
24
hw/block/nvme: Convert to realize
25
hw/block: Fix the return type
26
hw/block: Use errp directly rather than local_err
27
dev-storage: Fix the unusual function name
28
29
Mark Kanda (2):
30
virtio-blk: make queue size configurable
31
virtio-blk: reject configs with logical block size > physical block
32
size
33
34
Paolo Bonzini (1):
35
block: avoid recursive AioContext acquire in bdrv_inactivate_all()
36
37
Stefan Hajnoczi (16):
38
coroutine: simplify co_aio_sleep_ns() prototype
39
qdev: drop unused #include "sysemu/iothread.h"
40
blockdev: hold AioContext for bdrv_unref() in
41
external_snapshot_clean()
42
block: don't keep AioContext acquired after
43
external_snapshot_prepare()
44
block: don't keep AioContext acquired after drive_backup_prepare()
45
block: don't keep AioContext acquired after blockdev_backup_prepare()
46
block: don't keep AioContext acquired after
47
internal_snapshot_prepare()
48
block: drop unused BlockDirtyBitmapState->aio_context field
49
iothread: add iothread_by_id() API
50
blockdev: add x-blockdev-set-iothread testing command
51
qemu-iotests: add 202 external snapshots IOThread test
52
docs: mark nested AioContext locking as a legacy API
53
blockdev: add x-blockdev-set-iothread force boolean
54
iotests: add VM.add_object()
55
iothread: fix iothread_stop() race condition
56
qemu-iotests: add 203 savevm with IOThreads test
57
58
docs/devel/multiple-iothreads.txt | 7 +-
59
qapi/block-core.json | 40 ++++++
60
hw/block/dataplane/virtio-blk.h | 2 +-
61
include/hw/block/block.h | 4 +-
62
include/hw/virtio/virtio-blk.h | 1 +
63
include/qemu/coroutine.h | 6 +-
64
include/sysemu/iothread.h | 4 +-
65
block.c | 14 ++-
66
block/null.c | 3 +-
67
block/sheepdog.c | 3 +-
68
blockdev.c | 259 +++++++++++++++++++++++++++-----------
69
hw/block/block.c | 15 ++-
70
hw/block/dataplane/virtio-blk.c | 12 +-
71
hw/block/fdc.c | 17 +--
72
hw/block/nvme.c | 23 ++--
73
hw/block/virtio-blk.c | 30 +++--
74
hw/core/qdev-properties-system.c | 1 -
75
hw/ide/qdev.c | 12 +-
76
hw/scsi/scsi-disk.c | 13 +-
77
hw/usb/dev-storage.c | 29 ++---
78
iothread.c | 27 +++-
79
util/qemu-coroutine-sleep.c | 4 +-
80
tests/qemu-iotests/202 | 95 ++++++++++++++
81
tests/qemu-iotests/202.out | 11 ++
82
tests/qemu-iotests/203 | 59 +++++++++
83
tests/qemu-iotests/203.out | 6 +
84
tests/qemu-iotests/group | 2 +
85
tests/qemu-iotests/iotests.py | 5 +
86
28 files changed, 531 insertions(+), 173 deletions(-)
87
create mode 100755 tests/qemu-iotests/202
88
create mode 100644 tests/qemu-iotests/202.out
89
create mode 100755 tests/qemu-iotests/203
90
create mode 100644 tests/qemu-iotests/203.out
91
92
--
93
2.14.3
12
94
13
95
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
27
----------------------------------------------------------------
28
Block patches:
29
- Make the backup-top filter driver available for user-created block
30
nodes (i.e. via blockdev-add)
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
41
----------------------------------------------------------------
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
63
Fabrice Fontaine (1):
64
block/export/fuse.c: fix fuse-lseek on uclibc or musl
65
66
John Snow (3):
67
python: Reduce strictness of pylint's duplicate-code check
68
iotests: use with-statement for open() calls
69
iotests: use subprocess.DEVNULL instead of open("/dev/null")
70
71
Mao Zhongyi (1):
72
block/monitor: Consolidate hmp_handle_error calls to reduce redundant
73
code
74
75
Stefan Hajnoczi (1):
76
raw-format: drop WRITE and RESIZE child perms when possible
77
78
Viktor Prutyanov (1):
79
block/file-win32: add reopen handlers
80
81
Vladimir Sementsov-Ogievskiy (34):
82
block: introduce bdrv_replace_child_bs()
83
block: introduce blk_replace_bs
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
163
--
164
2.31.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
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Introduce the "Debugging a test case" section, in preparation
4
to the additional flags that will be added in the next patches.
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20210809090114.64834-5-eesposit@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
docs/devel/testing.rst | 8 ++++++++
13
1 file changed, 8 insertions(+)
14
15
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
16
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/devel/testing.rst
18
+++ b/docs/devel/testing.rst
19
@@ -XXX,XX +XXX,XX @@ another application on the host may have locked the file, possibly leading to a
20
test failure. If using such devices are explicitly desired, consider adding
21
``locking=off`` option to disable image locking.
22
23
+Debugging a test case
24
+-----------------------
25
+The following options to the ``check`` script can be useful when debugging
26
+a failing test:
27
+
28
+* ``-d`` (debug) just increases the logging verbosity, showing
29
+ for example the QMP commands and answers.
30
+
31
Test case groups
32
----------------
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
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
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The AioContext pointer argument to co_aio_sleep_ns() is only used for
2
the sleep timer. It does not affect where the caller coroutine is
3
resumed.
2
4
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Due to changes to coroutine and AIO APIs it is now possible to drop the
4
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
6
AioContext pointer argument. This is safe to do since no caller has
5
Message-Id: <20210824083856.17408-18-vsementsov@virtuozzo.com>
7
specific requirements for which AioContext the timer must run in.
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
9
This patch drops the AioContext pointer argument and renames the
10
function to simplify the API.
11
12
Reported-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reported-by: Eric Blake <eblake@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Message-id: 20171109102652.6360-1-stefanha@redhat.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
18
---
8
block/copy-before-write.h | 1 -
19
include/qemu/coroutine.h | 6 +-----
9
block/backup.c | 2 +-
20
block/null.c | 3 +--
10
block/copy-before-write.c | 7 +++----
21
block/sheepdog.c | 3 +--
11
3 files changed, 4 insertions(+), 6 deletions(-)
22
util/qemu-coroutine-sleep.c | 4 ++--
23
4 files changed, 5 insertions(+), 11 deletions(-)
12
24
13
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
25
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/block/copy-before-write.h
27
--- a/include/qemu/coroutine.h
16
+++ b/block/copy-before-write.h
28
+++ b/include/qemu/coroutine.h
17
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock);
18
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
30
19
BlockDriverState *target,
31
/**
20
const char *filter_node_name,
32
* Yield the coroutine for a given duration
21
- bool compress,
33
- *
22
BlockCopyState **bcs,
34
- * Behaves similarly to co_sleep_ns(), but the sleeping coroutine will be
23
Error **errp);
35
- * resumed when using aio_poll().
24
void bdrv_cbw_drop(BlockDriverState *bs);
36
*/
25
diff --git a/block/backup.c b/block/backup.c
37
-void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
38
- int64_t ns);
39
+void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns);
40
41
/**
42
* Yield until a file descriptor becomes readable
43
diff --git a/block/null.c b/block/null.c
26
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
27
--- a/block/backup.c
45
--- a/block/null.c
28
+++ b/block/backup.c
46
+++ b/block/null.c
29
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
47
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int null_co_common(BlockDriverState *bs)
30
goto error;
48
BDRVNullState *s = bs->opaque;
49
50
if (s->latency_ns) {
51
- co_aio_sleep_ns(bdrv_get_aio_context(bs), QEMU_CLOCK_REALTIME,
52
- s->latency_ns);
53
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, s->latency_ns);
31
}
54
}
32
55
return 0;
33
- cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
56
}
34
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
57
diff --git a/block/sheepdog.c b/block/sheepdog.c
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
58
index XXXXXXX..XXXXXXX 100644
40
--- a/block/copy-before-write.c
59
--- a/block/sheepdog.c
41
+++ b/block/copy-before-write.c
60
+++ b/block/sheepdog.c
42
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
61
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
62
if (s->fd < 0) {
63
DPRINTF("Wait for connection to be established\n");
64
error_report_err(local_err);
65
- co_aio_sleep_ns(bdrv_get_aio_context(s->bs), QEMU_CLOCK_REALTIME,
66
- 1000000000ULL);
67
+ qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000000ULL);
68
}
69
};
70
71
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/util/qemu-coroutine-sleep.c
74
+++ b/util/qemu-coroutine-sleep.c
75
@@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque)
76
aio_co_wake(sleep_cb->co);
43
}
77
}
44
78
45
static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
79
-void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
46
- BlockDriverState *target, bool compress, Error **errp)
80
- int64_t ns)
47
+ BlockDriverState *target, Error **errp)
81
+void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)
48
{
82
{
49
BDRVCopyBeforeWriteState *s = bs->opaque;
83
+ AioContext *ctx = qemu_get_current_aio_context();
50
84
CoSleepCB sleep_cb = {
51
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
85
.co = qemu_coroutine_self(),
52
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
86
};
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
--
87
--
78
2.31.1
88
2.14.3
79
89
80
90
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
We are going to publish copy-before-write filter to be used in separate
3
Convert nvme_init() to realize and rename it to nvme_realize().
4
of backup. Future step would support bitmap for the filter. But let's
5
start from full set bitmap.
6
4
7
We have to modify backup, as bitmap is first initialized by
5
Cc: John Snow <jsnow@redhat.com>
8
copy-before-write filter, and then backup modifies it.
6
Cc: Keith Busch <keith.busch@intel.com>
7
Cc: Kevin Wolf <kwolf@redhat.com>
8
Cc: Max Reitz <mreitz@redhat.com>
9
Cc: Markus Armbruster <armbru@redhat.com>
9
10
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-id: 2882e72d795e04cbe2120f569d551aef2467ac60.1511317952.git.maozy.fnst@cn.fujitsu.com
12
Message-Id: <20210824083856.17408-20-vsementsov@virtuozzo.com>
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
14
---
15
block/backup.c | 16 +++++++---------
15
hw/block/nvme.c | 18 ++++++++++--------
16
block/copy-before-write.c | 4 ++++
16
1 file changed, 10 insertions(+), 8 deletions(-)
17
2 files changed, 11 insertions(+), 9 deletions(-)
18
17
19
diff --git a/block/backup.c b/block/backup.c
18
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
20
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
21
--- a/block/backup.c
20
--- a/hw/block/nvme.c
22
+++ b/block/backup.c
21
+++ b/hw/block/nvme.c
23
@@ -XXX,XX +XXX,XX @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
22
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvme_cmb_ops = {
24
BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
23
},
25
24
};
26
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
25
27
+ bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
26
-static int nvme_init(PCIDevice *pci_dev)
28
ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
27
+static void nvme_realize(PCIDevice *pci_dev, Error **errp)
29
NULL, true);
28
{
30
assert(ret);
29
NvmeCtrl *n = NVME(pci_dev);
31
- } else {
30
NvmeIdCtrl *id = &n->id_ctrl;
32
- if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
31
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
33
- /*
32
Error *local_err = NULL;
34
- * We can't hog the coroutine to initialize this thoroughly.
33
35
- * Set a flag and resume work when we are able to yield safely.
34
if (!n->conf.blk) {
36
- */
35
- return -1;
37
- block_copy_set_skip_unallocated(job->bcs, true);
36
+ error_setg(errp, "drive property not set");
38
- }
37
+ return;
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
}
38
}
47
39
48
estimate = bdrv_get_dirty_count(bcs_bitmap);
40
bs_size = blk_getlength(n->conf.blk);
49
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
41
if (bs_size < 0) {
50
index XXXXXXX..XXXXXXX 100644
42
- return -1;
51
--- a/block/copy-before-write.c
43
+ error_setg(errp, "could not get backing file size");
52
+++ b/block/copy-before-write.c
44
+ return;
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
}
45
}
64
46
65
+ copy_bitmap = block_copy_dirty_bitmap(s->bcs);
47
blkconf_serial(&n->conf, &n->serial);
66
+ bdrv_set_dirty_bitmap(copy_bitmap, 0, bdrv_dirty_bitmap_size(copy_bitmap));
48
if (!n->serial) {
67
+
49
- return -1;
68
return 0;
50
+ error_setg(errp, "serial property not set");
51
+ return;
52
}
53
blkconf_blocksizes(&n->conf);
54
blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
55
false, &local_err);
56
if (local_err) {
57
- error_report_err(local_err);
58
- return -1;
59
+ error_propagate(errp, local_err);
60
+ return;
61
}
62
63
pci_conf = pci_dev->config;
64
@@ -XXX,XX +XXX,XX @@ static int nvme_init(PCIDevice *pci_dev)
65
cpu_to_le64(n->ns_size >>
66
id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas)].ds);
67
}
68
- return 0;
69
}
69
}
70
70
71
static void nvme_exit(PCIDevice *pci_dev)
72
@@ -XXX,XX +XXX,XX @@ static void nvme_class_init(ObjectClass *oc, void *data)
73
DeviceClass *dc = DEVICE_CLASS(oc);
74
PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc);
75
76
- pc->init = nvme_init;
77
+ pc->realize = nvme_realize;
78
pc->exit = nvme_exit;
79
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
80
pc->vendor_id = PCI_VENDOR_ID_INTEL;
71
--
81
--
72
2.31.1
82
2.14.3
73
83
74
84
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
Finally, copy-before-write gets own .bdrv_open and .bdrv_close
3
When the function no success value to transmit, it usually make the
4
handlers, block_init() call and becomes available through bdrv_open().
4
function return void. It has turned out not to be a success, because
5
it means that the extra local_err variable and error_propagate() will
6
be needed. It leads to cumbersome code, therefore, transmit success/
7
failure in the return value is worth.
5
8
6
To achieve this:
9
So fix the return type of blkconf_apply_backend_options(),
10
blkconf_geometry() and virtio_blk_data_plane_create() to avoid it.
7
11
8
- cbw_init gets unused flags argument and becomes cbw_open
12
Cc: John Snow <jsnow@redhat.com>
9
- block_copy_state_free() call moved to new cbw_close()
13
Cc: Kevin Wolf <kwolf@redhat.com>
10
- in bdrv_cbw_append:
14
Cc: Max Reitz <mreitz@redhat.com>
11
- options are completed with driver and node-name, and we can simply
15
Cc: Stefan Hajnoczi <stefanha@redhat.com>
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
16
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-Id: <20210824083856.17408-22-vsementsov@virtuozzo.com>
19
Message-id: ac0edc1fc70c4457e5cec94405eb7d1f89f9c2c1.1511317952.git.maozy.fnst@cn.fujitsu.com
20
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
21
---
21
---
22
block/copy-before-write.c | 60 ++++++++++++++++++---------------------
22
hw/block/dataplane/virtio-blk.h | 2 +-
23
1 file changed, 28 insertions(+), 32 deletions(-)
23
include/hw/block/block.h | 4 ++--
24
hw/block/block.c | 15 +++++++++------
25
hw/block/dataplane/virtio-blk.c | 12 +++++++-----
26
4 files changed, 19 insertions(+), 14 deletions(-)
24
27
25
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
28
diff --git a/hw/block/dataplane/virtio-blk.h b/hw/block/dataplane/virtio-blk.h
26
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.c
30
--- a/hw/block/dataplane/virtio-blk.h
28
+++ b/block/copy-before-write.c
31
+++ b/hw/block/dataplane/virtio-blk.h
29
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
32
@@ -XXX,XX +XXX,XX @@
33
34
typedef struct VirtIOBlockDataPlane VirtIOBlockDataPlane;
35
36
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
37
+bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
38
VirtIOBlockDataPlane **dataplane,
39
Error **errp);
40
void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s);
41
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/hw/block/block.h
44
+++ b/include/hw/block/block.h
45
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
46
/* Configuration helpers */
47
48
void blkconf_serial(BlockConf *conf, char **serial);
49
-void blkconf_geometry(BlockConf *conf, int *trans,
50
+bool blkconf_geometry(BlockConf *conf, int *trans,
51
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
52
Error **errp);
53
void blkconf_blocksizes(BlockConf *conf);
54
-void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
55
+bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
56
bool resizable, Error **errp);
57
58
/* Hard disk geometry */
59
diff --git a/hw/block/block.c b/hw/block/block.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/block/block.c
62
+++ b/hw/block/block.c
63
@@ -XXX,XX +XXX,XX @@ void blkconf_blocksizes(BlockConf *conf)
30
}
64
}
31
}
65
}
32
66
33
-static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
67
-void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
34
+static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
68
+bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
35
+ Error **errp)
69
bool resizable, Error **errp)
36
{
70
{
37
BDRVCopyBeforeWriteState *s = bs->opaque;
71
BlockBackend *blk = conf->blk;
38
BdrvDirtyBitmap *copy_bitmap;
72
@@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
39
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
73
40
return 0;
74
ret = blk_set_perm(blk, perm, shared_perm, errp);
75
if (ret < 0) {
76
- return;
77
+ return false;
78
}
79
80
switch (conf->wce) {
81
@@ -XXX,XX +XXX,XX @@ void blkconf_apply_backend_options(BlockConf *conf, bool readonly,
82
83
blk_set_enable_write_cache(blk, wce);
84
blk_set_on_error(blk, rerror, werror);
85
+
86
+ return true;
41
}
87
}
42
88
43
+static void cbw_close(BlockDriverState *bs)
89
-void blkconf_geometry(BlockConf *conf, int *ptrans,
44
+{
90
+bool blkconf_geometry(BlockConf *conf, int *ptrans,
45
+ BDRVCopyBeforeWriteState *s = bs->opaque;
91
unsigned cyls_max, unsigned heads_max, unsigned secs_max,
46
+
92
Error **errp)
47
+ block_copy_state_free(s->bcs);
93
{
48
+ s->bcs = NULL;
94
@@ -XXX,XX +XXX,XX @@ void blkconf_geometry(BlockConf *conf, int *ptrans,
49
+}
95
if (conf->cyls || conf->heads || conf->secs) {
50
+
96
if (conf->cyls < 1 || conf->cyls > cyls_max) {
51
BlockDriver bdrv_cbw_filter = {
97
error_setg(errp, "cyls must be between 1 and %u", cyls_max);
52
.format_name = "copy-before-write",
98
- return;
53
.instance_size = sizeof(BDRVCopyBeforeWriteState),
99
+ return false;
54
100
}
55
+ .bdrv_open = cbw_open,
101
if (conf->heads < 1 || conf->heads > heads_max) {
56
+ .bdrv_close = cbw_close,
102
error_setg(errp, "heads must be between 1 and %u", heads_max);
57
+
103
- return;
58
.bdrv_co_preadv = cbw_co_preadv,
104
+ return false;
59
.bdrv_co_pwritev = cbw_co_pwritev,
105
}
60
.bdrv_co_pwrite_zeroes = cbw_co_pwrite_zeroes,
106
if (conf->secs < 1 || conf->secs > secs_max) {
61
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
107
error_setg(errp, "secs must be between 1 and %u", secs_max);
108
- return;
109
+ return false;
110
}
111
}
112
+ return true;
113
}
114
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
115
index XXXXXXX..XXXXXXX 100644
116
--- a/hw/block/dataplane/virtio-blk.c
117
+++ b/hw/block/dataplane/virtio-blk.c
118
@@ -XXX,XX +XXX,XX @@ static void notify_guest_bh(void *opaque)
119
}
120
121
/* Context: QEMU global mutex held */
122
-void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
123
+bool virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
124
VirtIOBlockDataPlane **dataplane,
62
Error **errp)
125
Error **errp)
63
{
126
{
64
ERRP_GUARD();
127
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
65
- int ret;
128
error_setg(errp,
66
BDRVCopyBeforeWriteState *state;
129
"device is incompatible with iothread "
67
BlockDriverState *top;
130
"(transport does not support notifiers)");
68
QDict *opts;
131
- return;
69
132
+ return false;
70
assert(source->total_sectors == target->total_sectors);
133
}
71
134
if (!virtio_device_ioeventfd_enabled(vdev)) {
72
- top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
135
error_setg(errp, "ioeventfd is required for iothread");
73
- BDRV_O_RDWR, errp);
136
- return;
74
- if (!top) {
137
+ return false;
75
- error_prepend(errp, "Cannot open driver: ");
138
}
76
- return NULL;
139
77
- }
140
/* If dataplane is (re-)enabled while the guest is running there could
78
- state = top->opaque;
141
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
79
-
142
*/
80
opts = qdict_new();
143
if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
81
+ qdict_put_str(opts, "driver", "copy-before-write");
144
error_prepend(errp, "cannot start virtio-blk dataplane: ");
82
+ if (filter_node_name) {
145
- return;
83
+ qdict_put_str(opts, "node-name", filter_node_name);
146
+ return false;
84
+ }
147
}
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
}
148
}
104
149
/* Don't try if transport does not support notifiers. */
105
+ state = top->opaque;
150
if (!virtio_device_ioeventfd_enabled(vdev)) {
106
*bcs = state->bcs;
151
- return;
107
152
+ return false;
108
return top;
153
}
109
-
154
110
-fail:
155
s = g_new0(VirtIOBlockDataPlane, 1);
111
- block_copy_state_free(state->bcs);
156
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
112
- bdrv_unref(top);
157
s->batch_notify_vqs = bitmap_new(conf->num_queues);
113
- return NULL;
158
159
*dataplane = s;
160
+
161
+ return true;
114
}
162
}
115
163
116
void bdrv_cbw_drop(BlockDriverState *bs)
164
/* Context: QEMU global mutex held */
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
--
165
--
134
2.31.1
166
2.14.3
135
167
136
168
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
Now block-copy will crash if user don't set progress meter by
3
[Drop virtio_blk_data_plane_create() change that misinterprets return
4
block_copy_set_progress_meter(). copy-before-write filter will be used
4
value when the virtio transport does not support dataplane.
5
in separate of backup job, and it doesn't want any progress meter (for
5
--Stefan]
6
now). So, allow not setting it.
6
7
7
Cc: John Snow <jsnow@redhat.com>
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Cc: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Cc: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-21-vsementsov@virtuozzo.com>
10
Cc: Keith Busch <keith.busch@intel.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Cc: Stefan Hajnoczi <stefanha@redhat.com>
12
Cc: "Michael S. Tsirkin" <mst@redhat.com>
13
Cc: Paolo Bonzini <pbonzini@redhat.com>
14
Cc: Gerd Hoffmann <kraxel@redhat.com>
15
Cc: Markus Armbruster <armbru@redhat.com>
16
17
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
18
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
19
Message-id: e77848d3735ba590f23ffbf8094379c646c33d79.1511317952.git.maozy.fnst@cn.fujitsu.com
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
21
---
13
block/block-copy.c | 18 +++++++++++-------
22
hw/block/fdc.c | 17 ++++++-----------
14
1 file changed, 11 insertions(+), 7 deletions(-)
23
hw/block/nvme.c | 7 ++-----
15
24
hw/block/virtio-blk.c | 13 +++++--------
16
diff --git a/block/block-copy.c b/block/block-copy.c
25
hw/ide/qdev.c | 12 ++++--------
17
index XXXXXXX..XXXXXXX 100644
26
hw/scsi/scsi-disk.c | 13 ++++---------
18
--- a/block/block-copy.c
27
hw/usb/dev-storage.c | 9 +++------
19
+++ b/block/block-copy.c
28
6 files changed, 24 insertions(+), 47 deletions(-)
20
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
29
21
bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
30
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
22
}
31
index XXXXXXX..XXXXXXX 100644
23
QLIST_REMOVE(task, list);
32
--- a/hw/block/fdc.c
24
- progress_set_remaining(task->s->progress,
33
+++ b/hw/block/fdc.c
25
- bdrv_get_dirty_count(task->s->copy_bitmap) +
34
@@ -XXX,XX +XXX,XX @@ static void fd_revalidate(FDrive *drv)
26
- task->s->in_flight_bytes);
35
static void fd_change_cb(void *opaque, bool load, Error **errp)
27
+ if (task->s->progress) {
36
{
28
+ progress_set_remaining(task->s->progress,
37
FDrive *drive = opaque;
29
+ bdrv_get_dirty_count(task->s->copy_bitmap) +
38
- Error *local_err = NULL;
30
+ task->s->in_flight_bytes);
39
31
+ }
40
if (!load) {
32
qemu_co_queue_restart_all(&task->wait_queue);
41
blk_set_perm(drive->blk, 0, BLK_PERM_ALL, &error_abort);
33
}
42
} else {
34
43
- blkconf_apply_backend_options(drive->conf,
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
44
- blk_is_read_only(drive->blk), false,
36
t->call_state->ret = ret;
45
- &local_err);
37
t->call_state->error_is_read = error_is_read;
46
- if (local_err) {
38
}
47
- error_propagate(errp, local_err);
39
- } else {
48
+ if (!blkconf_apply_backend_options(drive->conf,
40
+ } else if (s->progress) {
49
+ blk_is_read_only(drive->blk), false,
41
progress_work_done(s->progress, t->bytes);
50
+ errp)) {
51
return;
42
}
52
}
43
}
53
}
44
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
54
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
45
if (!ret) {
55
FloppyDrive *dev = FLOPPY_DRIVE(qdev);
46
qemu_co_mutex_lock(&s->lock);
56
FloppyBus *bus = FLOPPY_BUS(qdev->parent_bus);
47
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
57
FDrive *drive;
48
- progress_set_remaining(s->progress,
58
- Error *local_err = NULL;
49
- bdrv_get_dirty_count(s->copy_bitmap) +
59
int ret;
50
- s->in_flight_bytes);
60
51
+ if (s->progress) {
61
if (dev->unit == -1) {
52
+ progress_set_remaining(s->progress,
62
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
53
+ bdrv_get_dirty_count(s->copy_bitmap) +
63
dev->conf.rerror = BLOCKDEV_ON_ERROR_AUTO;
54
+ s->in_flight_bytes);
64
dev->conf.werror = BLOCKDEV_ON_ERROR_AUTO;
55
+ }
65
56
qemu_co_mutex_unlock(&s->lock);
66
- blkconf_apply_backend_options(&dev->conf, blk_is_read_only(dev->conf.blk),
57
}
67
- false, &local_err);
58
68
- if (local_err) {
69
- error_propagate(errp, local_err);
70
+ if (!blkconf_apply_backend_options(&dev->conf,
71
+ blk_is_read_only(dev->conf.blk),
72
+ false, errp)) {
73
return;
74
}
75
76
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/block/nvme.c
79
+++ b/hw/block/nvme.c
80
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
81
int i;
82
int64_t bs_size;
83
uint8_t *pci_conf;
84
- Error *local_err = NULL;
85
86
if (!n->conf.blk) {
87
error_setg(errp, "drive property not set");
88
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
89
return;
90
}
91
blkconf_blocksizes(&n->conf);
92
- blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
93
- false, &local_err);
94
- if (local_err) {
95
- error_propagate(errp, local_err);
96
+ if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
97
+ false, errp)) {
98
return;
99
}
100
101
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/hw/block/virtio-blk.c
104
+++ b/hw/block/virtio-blk.c
105
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
106
}
107
108
blkconf_serial(&conf->conf, &conf->serial);
109
- blkconf_apply_backend_options(&conf->conf,
110
- blk_is_read_only(conf->conf.blk), true,
111
- &err);
112
- if (err) {
113
- error_propagate(errp, err);
114
+ if (!blkconf_apply_backend_options(&conf->conf,
115
+ blk_is_read_only(conf->conf.blk), true,
116
+ errp)) {
117
return;
118
}
119
s->original_wce = blk_enable_write_cache(conf->conf.blk);
120
- blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, &err);
121
- if (err) {
122
- error_propagate(errp, err);
123
+ if (!blkconf_geometry(&conf->conf, NULL, 65535, 255, 255, errp)) {
124
return;
125
}
126
+
127
blkconf_blocksizes(&conf->conf);
128
129
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
130
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/hw/ide/qdev.c
133
+++ b/hw/ide/qdev.c
134
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
135
{
136
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
137
IDEState *s = bus->ifs + dev->unit;
138
- Error *err = NULL;
139
int ret;
140
141
if (!dev->conf.blk) {
142
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
143
144
blkconf_serial(&dev->conf, &dev->serial);
145
if (kind != IDE_CD) {
146
- blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, &err);
147
- if (err) {
148
- error_propagate(errp, err);
149
+ if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255,
150
+ errp)) {
151
return;
152
}
153
}
154
- blkconf_apply_backend_options(&dev->conf, kind == IDE_CD, kind != IDE_CD,
155
- &err);
156
- if (err) {
157
- error_propagate(errp, err);
158
+ if (!blkconf_apply_backend_options(&dev->conf, kind == IDE_CD,
159
+ kind != IDE_CD, errp)) {
160
return;
161
}
162
163
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/hw/scsi/scsi-disk.c
166
+++ b/hw/scsi/scsi-disk.c
167
@@ -XXX,XX +XXX,XX @@ static void scsi_disk_unit_attention_reported(SCSIDevice *dev)
168
static void scsi_realize(SCSIDevice *dev, Error **errp)
169
{
170
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
171
- Error *err = NULL;
172
173
if (!s->qdev.conf.blk) {
174
error_setg(errp, "drive property not set");
175
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
176
}
177
178
if (dev->type == TYPE_DISK) {
179
- blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, &err);
180
- if (err) {
181
- error_propagate(errp, err);
182
+ if (!blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, errp)) {
183
return;
184
}
185
}
186
- blkconf_apply_backend_options(&dev->conf,
187
- blk_is_read_only(s->qdev.conf.blk),
188
- dev->type == TYPE_DISK, &err);
189
- if (err) {
190
- error_propagate(errp, err);
191
+ if (!blkconf_apply_backend_options(&dev->conf,
192
+ blk_is_read_only(s->qdev.conf.blk),
193
+ dev->type == TYPE_DISK, errp)) {
194
return;
195
}
196
197
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
198
index XXXXXXX..XXXXXXX 100644
199
--- a/hw/usb/dev-storage.c
200
+++ b/hw/usb/dev-storage.c
201
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
202
MSDState *s = USB_STORAGE_DEV(dev);
203
BlockBackend *blk = s->conf.blk;
204
SCSIDevice *scsi_dev;
205
- Error *err = NULL;
206
207
if (!blk) {
208
error_setg(errp, "drive property not set");
209
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
210
211
blkconf_serial(&s->conf, &dev->serial);
212
blkconf_blocksizes(&s->conf);
213
- blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true, &err);
214
- if (err) {
215
- error_propagate(errp, err);
216
+ if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), true,
217
+ errp)) {
218
return;
219
}
220
221
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
222
&usb_msd_scsi_info_storage, NULL);
223
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
224
s->conf.bootindex, dev->serial,
225
- &err);
226
+ errp);
227
blk_unref(blk);
228
if (!scsi_dev) {
229
- error_propagate(errp, err);
230
return;
231
}
232
usb_msd_handle_reset(dev);
59
--
233
--
60
2.31.1
234
2.14.3
61
235
62
236
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
2
2
3
We are going to publish copy-before-write filter, and there no public
3
The function name of usb_msd_{realize,unrealize}_*,
4
backing-child-based filter in Qemu. No reason to create a precedent, so
4
usb_msd_class_initfn_* are unusual. Rename it to
5
let's refactor copy-before-write filter instead.
5
usb_msd_*_{realize,unrealize}, usb_msd_class_*_initfn.
6
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Cc: Gerd Hoffmann <kraxel@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
9
Message-Id: <20210824083856.17408-13-vsementsov@virtuozzo.com>
9
Signed-off-by: Mao Zhongyi <maozy.fnst@cn.fujitsu.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 11e6003433abce35f3f4970e1acc71ee92dbcf51.1511317952.git.maozy.fnst@cn.fujitsu.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
13
---
12
block/copy-before-write.c | 39 ++++++++++++++++++++++-----------------
14
hw/usb/dev-storage.c | 20 ++++++++++----------
13
1 file changed, 22 insertions(+), 17 deletions(-)
15
1 file changed, 10 insertions(+), 10 deletions(-)
14
16
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
17
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
19
--- a/hw/usb/dev-storage.c
18
+++ b/block/copy-before-write.c
20
+++ b/hw/usb/dev-storage.c
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_preadv(
21
@@ -XXX,XX +XXX,XX @@ static void usb_msd_unrealize_storage(USBDevice *dev, Error **errp)
20
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
22
object_unref(OBJECT(&s->bus));
21
QEMUIOVector *qiov, int flags)
23
}
24
25
-static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
26
+static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
22
{
27
{
23
- return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
28
MSDState *s = USB_STORAGE_DEV(dev);
24
+ return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
29
BlockBackend *blk = s->conf.blk;
30
@@ -XXX,XX +XXX,XX @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp)
31
s->scsi_dev = scsi_dev;
25
}
32
}
26
33
27
static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
34
-static void usb_msd_unrealize_bot(USBDevice *dev, Error **errp)
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
35
+static void usb_msd_bot_unrealize(USBDevice *dev, Error **errp)
29
return ret;
36
{
30
}
37
MSDState *s = USB_STORAGE_DEV(dev);
31
38
32
- return bdrv_co_pdiscard(bs->backing, offset, bytes);
39
object_unref(OBJECT(&s->bus));
33
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
34
}
40
}
35
41
36
static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
42
-static void usb_msd_realize_bot(USBDevice *dev, Error **errp)
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
43
+static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
38
return ret;
44
{
39
}
45
MSDState *s = USB_STORAGE_DEV(dev);
40
46
DeviceState *d = DEVICE(dev);
41
- return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
47
@@ -XXX,XX +XXX,XX @@ static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
42
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
48
dc->vmsd = &vmstate_usb_msd;
43
}
49
}
44
50
45
static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
51
-static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data)
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
52
+static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
47
return ret;
53
{
48
}
54
DeviceClass *dc = DEVICE_CLASS(klass);
49
55
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
50
- return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
56
51
+ return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
57
- uc->realize = usb_msd_realize_storage;
58
+ uc->realize = usb_msd_storage_realize;
59
uc->unrealize = usb_msd_unrealize_storage;
60
dc->props = msd_properties;
52
}
61
}
53
62
@@ -XXX,XX +XXX,XX @@ static void usb_msd_instance_init(Object *obj)
54
static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
63
object_property_set_int(obj, -1, "bootindex", NULL);
64
}
65
66
-static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data)
67
+static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
55
{
68
{
56
- if (!bs->backing) {
69
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
57
+ if (!bs->file) {
70
58
return 0;
71
- uc->realize = usb_msd_realize_bot;
59
}
72
- uc->unrealize = usb_msd_unrealize_bot;
60
73
+ uc->realize = usb_msd_bot_realize;
61
- return bdrv_co_flush(bs->backing->bs);
74
+ uc->unrealize = usb_msd_bot_unrealize;
62
+ return bdrv_co_flush(bs->file->bs);
75
uc->attached_settable = true;
63
}
76
}
64
77
65
static void cbw_refresh_filename(BlockDriverState *bs)
78
static const TypeInfo msd_info = {
66
{
79
.name = "usb-storage",
67
- if (bs->backing == NULL) {
80
.parent = TYPE_USB_STORAGE,
68
- /*
81
- .class_init = usb_msd_class_initfn_storage,
69
- * we can be here after failed bdrv_attach_child in
82
+ .class_init = usb_msd_class_storage_initfn,
70
- * bdrv_set_backing_hd
83
.instance_init = usb_msd_instance_init,
71
- */
84
};
72
- return;
85
73
- }
86
static const TypeInfo bot_info = {
74
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
87
.name = "usb-bot",
75
- bs->backing->bs->filename);
88
.parent = TYPE_USB_STORAGE,
76
+ bs->file->bs->filename);
89
- .class_init = usb_msd_class_initfn_bot,
77
}
90
+ .class_init = usb_msd_class_bot_initfn,
78
91
};
79
static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
92
80
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
93
static void usb_msd_register_types(void)
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
--
94
--
125
2.31.1
95
2.14.3
126
96
127
97
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Commit 1351d1ec89eabebc9fdff20451a62c413d7accc1 ("qdev: drop iothread
2
property type") forgot to remove this include.
2
3
3
We need an ability to insert filters above top block node, attached to
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
block device. It can't be achieved with blockdev-reopen command. So, we
5
Message-id: 20171205133954.31006-1-stefanha@redhat.com
5
want do it with help of qom-set.
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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
---
7
---
21
hw/core/qdev-properties-system.c | 43 +++++++++++++++++++++++---------
8
hw/core/qdev-properties-system.c | 1 -
22
1 file changed, 31 insertions(+), 12 deletions(-)
9
1 file changed, 1 deletion(-)
23
10
24
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
11
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
25
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/qdev-properties-system.c
13
--- a/hw/core/qdev-properties-system.c
27
+++ b/hw/core/qdev-properties-system.c
14
+++ b/hw/core/qdev-properties-system.c
28
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@
29
16
#include "qapi/visitor.h"
30
static bool check_prop_still_unset(Object *obj, const char *name,
17
#include "chardev/char-fe.h"
31
const void *old_val, const char *new_val,
18
#include "sysemu/tpm_backend.h"
32
- Error **errp)
19
-#include "sysemu/iothread.h"
33
+ bool allow_override, Error **errp)
20
34
{
21
static void get_pointer(Object *obj, Visitor *v, Property *prop,
35
const GlobalProperty *prop = qdev_find_global_prop(obj, name);
22
char *(*print)(void *ptr),
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
--
23
--
136
2.31.1
24
2.14.3
137
25
138
26
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
bdrv_unref() requires the AioContext lock because bdrv_flush() uses
2
BDRV_POLL_WHILE(), which assumes the AioContext is currently held. If
3
BDRV_POLL_WHILE() runs without AioContext held the
4
pthread_mutex_unlock() call in aio_context_release() fails.
2
5
3
One more step closer to .bdrv_open(): use options instead of plain
6
This patch moves bdrv_unref() into the AioContext locked region to solve
4
arguments. Move to bdrv_open_child() calls, native for drive open
7
the following pthread_mutex_unlock() failure:
5
handlers.
6
8
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
#0 0x00007f566181969b in raise () at /lib64/libc.so.6
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
#1 0x00007f566181b3b1 in abort () at /lib64/libc.so.6
9
Message-Id: <20210824083856.17408-19-vsementsov@virtuozzo.com>
11
#2 0x00005592cd590458 in error_exit (err=<optimized out>, msg=msg@entry=0x5592cdaf6d60 <__func__.23977> "qemu_mutex_unlock") at util/qemu-thread-posix.c:36
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
#3 0x00005592cd96e738 in qemu_mutex_unlock (mutex=mutex@entry=0x5592ce9505e0) at util/qemu-thread-posix.c:96
13
#4 0x00005592cd969b69 in aio_context_release (ctx=ctx@entry=0x5592ce950580) at util/async.c:507
14
#5 0x00005592cd8ead78 in bdrv_flush (bs=bs@entry=0x5592cfa87210) at block/io.c:2478
15
#6 0x00005592cd89df30 in bdrv_close (bs=0x5592cfa87210) at block.c:3207
16
#7 0x00005592cd89df30 in bdrv_delete (bs=0x5592cfa87210) at block.c:3395
17
#8 0x00005592cd89df30 in bdrv_unref (bs=0x5592cfa87210) at block.c:4418
18
#9 0x00005592cd6b7f86 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=<optimized out>, errp=errp@entry=0x7ffe4a1fc9d8) at blockdev.c:2308
19
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
22
Reviewed-by: Eric Blake <eblake@redhat.com>
23
Message-id: 20171206144550.22295-2-stefanha@redhat.com
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
25
---
12
block/copy-before-write.c | 29 +++++++++++++++--------------
26
blockdev.c | 2 +-
13
1 file changed, 15 insertions(+), 14 deletions(-)
27
1 file changed, 1 insertion(+), 1 deletion(-)
14
28
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
29
diff --git a/blockdev.c b/blockdev.c
16
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
31
--- a/blockdev.c
18
+++ b/block/copy-before-write.c
32
+++ b/blockdev.c
19
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
33
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
34
DO_UPCAST(ExternalSnapshotState, common, common);
35
if (state->aio_context) {
36
bdrv_drained_end(state->old_bs);
37
- aio_context_release(state->aio_context);
38
bdrv_unref(state->new_bs);
39
+ aio_context_release(state->aio_context);
20
}
40
}
21
}
41
}
22
42
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
--
43
--
76
2.31.1
44
2.14.3
77
45
78
46
diff view generated by jsdifflib
1
From: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
1
It is not necessary to hold AioContext across transactions anymore since
2
2
bdrv_drained_begin/end() is used to keep the nodes quiesced. In fact,
3
Make 'qemu-img commit' work on Windows.
3
using the AioContext lock for this purpose was always buggy.
4
4
5
Command 'commit' requires reopening backing file in RW mode. So,
5
This patch reduces the scope of AioContext locked regions. This is not
6
add reopen prepare/commit/abort handlers and change dwShareMode
6
just a cleanup but also fixes hangs that occur in BDRV_POLL_WHILE()
7
for CreateFile call in order to allow further read/write reopening.
7
because it is unware of recursive locking and does not release the
8
8
AioContext the necessary number of times to allow progress to be made.
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/418
9
10
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Suggested-by: Hanna Reitz <hreitz@redhat.com>
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Tested-by: Helge Konetzka <hk@zapateado.de>
13
Message-id: 20171206144550.22295-3-stefanha@redhat.com
14
Message-Id: <20210825173625.19415-1-viktor.prutyanov@phystech.edu>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
15
---
17
block/file-win32.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
16
blockdev.c | 71 ++++++++++++++++++++++++++++++++++++++++++--------------------
18
1 file changed, 100 insertions(+), 1 deletion(-)
17
1 file changed, 48 insertions(+), 23 deletions(-)
19
18
20
diff --git a/block/file-win32.c b/block/file-win32.c
19
diff --git a/blockdev.c b/blockdev.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/block/file-win32.c
21
--- a/blockdev.c
23
+++ b/block/file-win32.c
22
+++ b/blockdev.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
23
@@ -XXX,XX +XXX,XX @@ typedef struct ExternalSnapshotState {
25
QEMUWin32AIOState *aio;
24
BlkActionState common;
26
} BDRVRawState;
25
BlockDriverState *old_bs;
27
26
BlockDriverState *new_bs;
28
+typedef struct BDRVRawReopenState {
27
- AioContext *aio_context;
29
+ HANDLE hfile;
28
bool overlay_appended;
30
+} BDRVRawReopenState;
29
} ExternalSnapshotState;
31
+
30
32
/*
31
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
33
* Read/writes the data to/from a given linear buffer.
32
ExternalSnapshotState *state =
34
*
33
DO_UPCAST(ExternalSnapshotState, common, common);
35
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
34
TransactionAction *action = common->action;
36
}
35
+ AioContext *aio_context;
37
36
38
s->hfile = CreateFile(filename, access_flags,
37
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
39
- FILE_SHARE_READ, NULL,
38
* purpose but a different set of parameters */
40
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
39
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
41
OPEN_EXISTING, overlapped, NULL);
40
return;
42
if (s->hfile == INVALID_HANDLE_VALUE) {
41
}
43
int err = GetLastError();
42
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
43
- /* Acquire AioContext now so any threads operating on old_bs stop */
45
return raw_co_create(&options, errp);
44
- state->aio_context = bdrv_get_aio_context(state->old_bs);
46
}
45
- aio_context_acquire(state->aio_context);
47
46
+ aio_context = bdrv_get_aio_context(state->old_bs);
48
+static int raw_reopen_prepare(BDRVReopenState *state,
47
+ aio_context_acquire(aio_context);
49
+ BlockReopenQueue *queue, Error **errp)
48
+
50
+{
49
+ /* Paired with .clean() */
51
+ BDRVRawState *s = state->bs->opaque;
50
bdrv_drained_begin(state->old_bs);
52
+ BDRVRawReopenState *rs;
51
53
+ int access_flags;
52
if (!bdrv_is_inserted(state->old_bs)) {
54
+ DWORD overlapped;
53
error_setg(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
55
+ int ret = 0;
54
- return;
56
+
55
+ goto out;
57
+ if (s->type != FTYPE_FILE) {
56
}
58
+ error_setg(errp, "Can only reopen files");
57
59
+ return -EINVAL;
58
if (bdrv_op_is_blocked(state->old_bs,
60
+ }
59
BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, errp)) {
61
+
60
- return;
62
+ rs = g_new0(BDRVRawReopenState, 1);
61
+ goto out;
63
+
62
}
64
+ /*
63
65
+ * We do not support changing any options (only flags). By leaving
64
if (!bdrv_is_read_only(state->old_bs)) {
66
+ * all options in state->options, we tell the generic reopen code
65
if (bdrv_flush(state->old_bs)) {
67
+ * that we do not support changing any of them, so it will verify
66
error_setg(errp, QERR_IO_ERROR);
68
+ * that their values did not change.
67
- return;
69
+ */
68
+ goto out;
70
+
69
}
71
+ raw_parse_flags(state->flags, s->aio != NULL, &access_flags, &overlapped);
70
}
72
+ rs->hfile = CreateFile(state->bs->filename, access_flags,
71
73
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
72
if (!bdrv_is_first_non_filter(state->old_bs)) {
74
+ OPEN_EXISTING, overlapped, NULL);
73
error_setg(errp, QERR_FEATURE_DISABLED, "snapshot");
75
+
74
- return;
76
+ if (rs->hfile == INVALID_HANDLE_VALUE) {
75
+ goto out;
77
+ int err = GetLastError();
76
}
78
+
77
79
+ error_setg_win32(errp, err, "Could not reopen '%s'",
78
if (action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC) {
80
+ state->bs->filename);
79
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
81
+ if (err == ERROR_ACCESS_DENIED) {
80
82
+ ret = -EACCES;
81
if (node_name && !snapshot_node_name) {
83
+ } else {
82
error_setg(errp, "New snapshot node name missing");
84
+ ret = -EINVAL;
83
- return;
85
+ }
84
+ goto out;
86
+ goto fail;
85
}
87
+ }
86
88
+
87
if (snapshot_node_name &&
89
+ if (s->aio) {
88
bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
90
+ ret = win32_aio_attach(s->aio, rs->hfile);
89
error_setg(errp, "New snapshot node name already in use");
91
+ if (ret < 0) {
90
- return;
92
+ error_setg_errno(errp, -ret, "Could not enable AIO");
91
+ goto out;
93
+ CloseHandle(rs->hfile);
92
}
94
+ goto fail;
93
95
+ }
94
flags = state->old_bs->open_flags;
96
+ }
95
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
97
+
96
int64_t size = bdrv_getlength(state->old_bs);
98
+ state->opaque = rs;
97
if (size < 0) {
99
+
98
error_setg_errno(errp, -size, "bdrv_getlength failed");
100
+ return 0;
99
- return;
101
+
100
+ goto out;
102
+fail:
101
}
103
+ g_free(rs);
102
bdrv_img_create(new_image_file, format,
104
+ state->opaque = NULL;
103
state->old_bs->filename,
105
+
104
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
106
+ return ret;
105
NULL, size, flags, false, &local_err);
107
+}
106
if (local_err) {
108
+
107
error_propagate(errp, local_err);
109
+static void raw_reopen_commit(BDRVReopenState *state)
108
- return;
110
+{
109
+ goto out;
111
+ BDRVRawState *s = state->bs->opaque;
110
}
112
+ BDRVRawReopenState *rs = state->opaque;
111
}
113
+
112
114
+ assert(rs != NULL);
113
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
115
+
114
errp);
116
+ CloseHandle(s->hfile);
115
/* We will manually add the backing_hd field to the bs later */
117
+ s->hfile = rs->hfile;
116
if (!state->new_bs) {
118
+
117
- return;
119
+ g_free(rs);
118
+ goto out;
120
+ state->opaque = NULL;
119
}
121
+}
120
122
+
121
if (bdrv_has_blk(state->new_bs)) {
123
+static void raw_reopen_abort(BDRVReopenState *state)
122
error_setg(errp, "The snapshot is already in use");
124
+{
123
- return;
125
+ BDRVRawReopenState *rs = state->opaque;
124
+ goto out;
126
+
125
}
127
+ if (!rs) {
126
127
if (bdrv_op_is_blocked(state->new_bs, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
128
errp)) {
129
- return;
130
+ goto out;
131
}
132
133
if (state->new_bs->backing != NULL) {
134
error_setg(errp, "The snapshot already has a backing image");
135
- return;
136
+ goto out;
137
}
138
139
if (!state->new_bs->drv->supports_backing) {
140
error_setg(errp, "The snapshot does not support backing images");
141
- return;
142
+ goto out;
143
}
144
145
- bdrv_set_aio_context(state->new_bs, state->aio_context);
146
+ bdrv_set_aio_context(state->new_bs, aio_context);
147
148
/* This removes our old bs and adds the new bs. This is an operation that
149
* can fail, so we need to do it in .prepare; undoing it for abort is
150
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
151
bdrv_append(state->new_bs, state->old_bs, &local_err);
152
if (local_err) {
153
error_propagate(errp, local_err);
154
- return;
155
+ goto out;
156
}
157
state->overlay_appended = true;
158
+
159
+out:
160
+ aio_context_release(aio_context);
161
}
162
163
static void external_snapshot_commit(BlkActionState *common)
164
{
165
ExternalSnapshotState *state =
166
DO_UPCAST(ExternalSnapshotState, common, common);
167
+ AioContext *aio_context;
168
+
169
+ aio_context = bdrv_get_aio_context(state->old_bs);
170
+ aio_context_acquire(aio_context);
171
172
/* We don't need (or want) to use the transactional
173
* bdrv_reopen_multiple() across all the entries at once, because we
174
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_commit(BlkActionState *common)
175
bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
176
NULL);
177
}
178
+
179
+ aio_context_release(aio_context);
180
}
181
182
static void external_snapshot_abort(BlkActionState *common)
183
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
184
DO_UPCAST(ExternalSnapshotState, common, common);
185
if (state->new_bs) {
186
if (state->overlay_appended) {
187
+ AioContext *aio_context;
188
+
189
+ aio_context = bdrv_get_aio_context(state->old_bs);
190
+ aio_context_acquire(aio_context);
191
+
192
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
193
close state->old_bs; we need it */
194
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
195
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
196
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
197
+
198
+ aio_context_release(aio_context);
199
}
200
}
201
}
202
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
203
{
204
ExternalSnapshotState *state =
205
DO_UPCAST(ExternalSnapshotState, common, common);
206
- if (state->aio_context) {
207
- bdrv_drained_end(state->old_bs);
208
- bdrv_unref(state->new_bs);
209
- aio_context_release(state->aio_context);
210
+ AioContext *aio_context;
211
+
212
+ if (!state->old_bs) {
128
+ return;
213
+ return;
129
+ }
214
}
130
+
215
+
131
+ if (rs->hfile != INVALID_HANDLE_VALUE) {
216
+ aio_context = bdrv_get_aio_context(state->old_bs);
132
+ CloseHandle(rs->hfile);
217
+ aio_context_acquire(aio_context);
133
+ }
218
+
134
+
219
+ bdrv_drained_end(state->old_bs);
135
+ g_free(rs);
220
+ bdrv_unref(state->new_bs);
136
+ state->opaque = NULL;
221
+
137
+}
222
+ aio_context_release(aio_context);
138
+
223
}
139
static QemuOptsList raw_create_opts = {
224
140
.name = "raw-create-opts",
225
typedef struct DriveBackupState {
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
--
226
--
154
2.31.1
227
2.14.3
155
228
156
229
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-4-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 42 ++++++++++++++++++++++++++++++++++--------
8
1 file changed, 34 insertions(+), 8 deletions(-)
2
9
3
We are going to convert backup_top to full featured public filter,
10
diff --git a/blockdev.c b/blockdev.c
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
11
index XXXXXXX..XXXXXXX 100644
55
--- a/block/backup-top.h
12
--- a/blockdev.c
56
+++ b/block/copy-before-write.h
13
+++ b/blockdev.c
57
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_clean(BlkActionState *common)
58
/*
15
typedef struct DriveBackupState {
59
- * backup-top filter driver
16
BlkActionState common;
60
+ * copy-before-write filter driver
17
BlockDriverState *bs;
61
*
18
- AioContext *aio_context;
62
* The driver performs Copy-Before-Write (CBW) operation: it is injected above
19
BlockJob *job;
63
* some node, and before each write it copies _old_ data to the target node.
20
} DriveBackupState;
64
*
21
65
- * Copyright (c) 2018-2019 Virtuozzo International GmbH.
22
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
66
+ * Copyright (c) 2018-2021 Virtuozzo International GmbH.
23
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
67
*
24
BlockDriverState *bs;
68
* Author:
25
DriveBackup *backup;
69
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
26
+ AioContext *aio_context;
70
@@ -XXX,XX +XXX,XX @@
27
Error *local_err = NULL;
71
* along with this program. If not, see <http://www.gnu.org/licenses/>.
28
72
*/
29
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
73
30
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
74
-#ifndef BACKUP_TOP_H
31
return;
75
-#define BACKUP_TOP_H
32
}
76
+#ifndef COPY_BEFORE_WRITE_H
33
77
+#define COPY_BEFORE_WRITE_H
34
- /* AioContext is released in .clean() */
78
35
- state->aio_context = bdrv_get_aio_context(bs);
79
#include "block/block_int.h"
36
- aio_context_acquire(state->aio_context);
80
#include "block/block-copy.h"
37
+ aio_context = bdrv_get_aio_context(bs);
81
38
+ aio_context_acquire(aio_context);
82
-BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
39
+
83
- BlockDriverState *target,
40
+ /* Paired with .clean() */
84
- const char *filter_node_name,
41
bdrv_drained_begin(bs);
85
- uint64_t cluster_size,
42
+
86
- BackupPerf *perf,
43
state->bs = bs;
87
- BdrvRequestFlags write_flags,
44
88
- BlockCopyState **bcs,
45
state->job = do_drive_backup(backup, common->block_job_txn, &local_err);
89
- Error **errp);
46
if (local_err) {
90
-void bdrv_backup_top_drop(BlockDriverState *bs);
47
error_propagate(errp, local_err);
91
+BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
48
- return;
92
+ BlockDriverState *target,
49
+ goto out;
93
+ const char *filter_node_name,
50
}
94
+ uint64_t cluster_size,
51
+
95
+ BackupPerf *perf,
52
+out:
96
+ BdrvRequestFlags write_flags,
53
+ aio_context_release(aio_context);
97
+ BlockCopyState **bcs,
54
}
98
+ Error **errp);
55
99
+void bdrv_cbw_drop(BlockDriverState *bs);
56
static void drive_backup_commit(BlkActionState *common)
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
{
57
{
125
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
58
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
126
block_job_remove_all_bdrv(&s->common);
59
+ AioContext *aio_context;
127
- bdrv_backup_top_drop(s->backup_top);
60
+
128
+ bdrv_cbw_drop(s->cbw);
61
+ aio_context = bdrv_get_aio_context(state->bs);
62
+ aio_context_acquire(aio_context);
63
+
64
assert(state->job);
65
block_job_start(state->job);
66
+
67
+ aio_context_release(aio_context);
129
}
68
}
130
69
131
void backup_do_checkpoint(BlockJob *job, Error **errp)
70
static void drive_backup_abort(BlkActionState *common)
132
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
71
@@ -XXX,XX +XXX,XX @@ static void drive_backup_abort(BlkActionState *common)
133
BackupBlockJob *job = NULL;
72
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
134
int64_t cluster_size;
73
135
BdrvRequestFlags write_flags;
74
if (state->job) {
136
- BlockDriverState *backup_top = NULL;
75
+ AioContext *aio_context;
137
+ BlockDriverState *cbw = NULL;
76
+
138
BlockCopyState *bcs = NULL;
77
+ aio_context = bdrv_get_aio_context(state->bs);
139
78
+ aio_context_acquire(aio_context);
140
assert(bs);
79
+
141
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
80
block_job_cancel_sync(state->job);
142
write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
81
+
143
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
82
+ aio_context_release(aio_context);
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
}
83
}
323
}
84
}
324
85
325
-BlockDriver bdrv_backup_top_filter = {
86
static void drive_backup_clean(BlkActionState *common)
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
{
87
{
369
ERRP_GUARD();
88
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
370
int ret;
89
+ AioContext *aio_context;
371
- BDRVBackupTopState *state;
90
372
+ BDRVCopyBeforeWriteState *state;
91
- if (state->aio_context) {
373
BlockDriverState *top;
92
- bdrv_drained_end(state->bs);
374
bool appended = false;
93
- aio_context_release(state->aio_context);
375
94
+ if (!state->bs) {
376
assert(source->total_sectors == target->total_sectors);
95
+ return;
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
}
96
}
391
appended = true;
97
+
392
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
98
+ aio_context = bdrv_get_aio_context(state->bs);
393
99
+ aio_context_acquire(aio_context);
394
fail:
100
+
395
if (appended) {
101
+ bdrv_drained_end(state->bs);
396
- bdrv_backup_top_drop(top);
102
+
397
+ bdrv_cbw_drop(top);
103
+ aio_context_release(aio_context);
398
} else {
399
bdrv_unref(top);
400
}
401
@@ -XXX,XX +XXX,XX @@ fail:
402
return NULL;
403
}
104
}
404
105
405
-void bdrv_backup_top_drop(BlockDriverState *bs)
106
typedef struct BlockdevBackupState {
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
--
107
--
533
2.31.1
108
2.14.3
534
109
535
110
diff view generated by jsdifflib
1
From: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-5-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 44 ++++++++++++++++++++++++++++++++++----------
8
1 file changed, 34 insertions(+), 10 deletions(-)
2
9
3
Signed-off-by: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
10
diff --git a/blockdev.c b/blockdev.c
4
Message-Id: <20210802062507.347555-1-maozhongyi@cmss.chinamobile.com>
5
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
6
---
7
block/monitor/block-hmp-cmds.c | 12 ++++++------
8
1 file changed, 6 insertions(+), 6 deletions(-)
9
10
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/monitor/block-hmp-cmds.c
12
--- a/blockdev.c
13
+++ b/block/monitor/block-hmp-cmds.c
13
+++ b/blockdev.c
14
@@ -XXX,XX +XXX,XX @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
14
@@ -XXX,XX +XXX,XX @@ typedef struct BlockdevBackupState {
15
15
BlkActionState common;
16
if (!filename) {
16
BlockDriverState *bs;
17
error_setg(&err, QERR_MISSING_PARAMETER, "target");
17
BlockJob *job;
18
- hmp_handle_error(mon, err);
18
- AioContext *aio_context;
19
} BlockdevBackupState;
20
21
static BlockJob *do_blockdev_backup(BlockdevBackup *backup, BlockJobTxn *txn,
22
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
23
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
24
BlockdevBackup *backup;
25
BlockDriverState *bs, *target;
26
+ AioContext *aio_context;
27
Error *local_err = NULL;
28
29
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
30
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
31
return;
32
}
33
34
- /* AioContext is released in .clean() */
35
- state->aio_context = bdrv_get_aio_context(bs);
36
- if (state->aio_context != bdrv_get_aio_context(target)) {
37
- state->aio_context = NULL;
38
+ aio_context = bdrv_get_aio_context(bs);
39
+ if (aio_context != bdrv_get_aio_context(target)) {
40
error_setg(errp, "Backup between two IO threads is not implemented");
41
return;
42
}
43
- aio_context_acquire(state->aio_context);
44
+ aio_context_acquire(aio_context);
45
state->bs = bs;
46
+
47
+ /* Paired with .clean() */
48
bdrv_drained_begin(state->bs);
49
50
state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err);
51
if (local_err) {
52
error_propagate(errp, local_err);
19
- return;
53
- return;
20
+ goto end;
54
+ goto out;
21
}
55
}
22
qmp_drive_mirror(&mirror, &err);
56
+
23
+end:
57
+out:
24
hmp_handle_error(mon, err);
58
+ aio_context_release(aio_context);
25
}
59
}
26
60
27
@@ -XXX,XX +XXX,XX @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
61
static void blockdev_backup_commit(BlkActionState *common)
28
62
{
29
if (!filename) {
63
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
30
error_setg(&err, QERR_MISSING_PARAMETER, "target");
64
+ AioContext *aio_context;
31
- hmp_handle_error(mon, err);
65
+
32
- return;
66
+ aio_context = bdrv_get_aio_context(state->bs);
33
+ goto end;
67
+ aio_context_acquire(aio_context);
68
+
69
assert(state->job);
70
block_job_start(state->job);
71
+
72
+ aio_context_release(aio_context);
73
}
74
75
static void blockdev_backup_abort(BlkActionState *common)
76
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_abort(BlkActionState *common)
77
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
78
79
if (state->job) {
80
+ AioContext *aio_context;
81
+
82
+ aio_context = bdrv_get_aio_context(state->bs);
83
+ aio_context_acquire(aio_context);
84
+
85
block_job_cancel_sync(state->job);
86
+
87
+ aio_context_release(aio_context);
34
}
88
}
35
36
qmp_drive_backup(&backup, &err);
37
+end:
38
hmp_handle_error(mon, err);
39
}
89
}
40
90
41
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
91
static void blockdev_backup_clean(BlkActionState *common)
42
* will be taken internally. Today it's actually required.
92
{
43
*/
93
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
44
error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
94
+ AioContext *aio_context;
45
- hmp_handle_error(mon, err);
95
46
- return;
96
- if (state->aio_context) {
47
+ goto end;
97
- bdrv_drained_end(state->bs);
98
- aio_context_release(state->aio_context);
99
+ if (!state->bs) {
100
+ return;
48
}
101
}
49
102
+
50
mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
103
+ aio_context = bdrv_get_aio_context(state->bs);
51
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
104
+ aio_context_acquire(aio_context);
52
filename, false, NULL,
105
+
53
!!format, format,
106
+ bdrv_drained_end(state->bs);
54
true, mode, &err);
107
+
55
+end:
108
+ aio_context_release(aio_context);
56
hmp_handle_error(mon, err);
57
}
109
}
58
110
111
typedef struct BlockDirtyBitmapState {
59
--
112
--
60
2.31.1
113
2.14.3
61
114
62
115
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
2
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
3
Reviewed-by: Eric Blake <eblake@redhat.com>
4
Message-id: 20171206144550.22295-6-stefanha@redhat.com
5
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
6
---
7
blockdev.c | 47 +++++++++++++++++++++++++++++++----------------
8
1 file changed, 31 insertions(+), 16 deletions(-)
2
9
3
The main consumer of cluster-size is block-copy. Let's calculate it
10
diff --git a/blockdev.c b/blockdev.c
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
11
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.h
12
--- a/blockdev.c
28
+++ b/block/copy-before-write.h
13
+++ b/blockdev.c
29
@@ -XXX,XX +XXX,XX @@
14
@@ -XXX,XX +XXX,XX @@ struct BlkActionState {
30
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
15
typedef struct InternalSnapshotState {
31
BlockDriverState *target,
16
BlkActionState common;
32
const char *filter_node_name,
17
BlockDriverState *bs;
33
- uint64_t cluster_size,
18
- AioContext *aio_context;
34
bool compress,
19
QEMUSnapshotInfo sn;
35
BlockCopyState **bcs,
20
bool created;
36
Error **errp);
21
} InternalSnapshotState;
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
22
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
38
index XXXXXXX..XXXXXXX 100644
23
qemu_timeval tv;
39
--- a/include/block/block-copy.h
24
BlockdevSnapshotInternal *internal;
40
+++ b/include/block/block-copy.h
25
InternalSnapshotState *state;
41
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
26
+ AioContext *aio_context;
42
typedef struct BlockCopyCallState BlockCopyCallState;
27
int ret1;
43
28
44
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
29
g_assert(common->action->type ==
45
- int64_t cluster_size, bool use_copy_range,
30
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
46
- bool compress, Error **errp);
31
return;
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
}
32
}
120
33
121
- cluster_size = backup_calculate_cluster_size(target, errp);
34
- /* AioContext is released in .clean() */
122
- if (cluster_size < 0) {
35
- state->aio_context = bdrv_get_aio_context(bs);
123
- goto error;
36
- aio_context_acquire(state->aio_context);
124
- }
37
+ aio_context = bdrv_get_aio_context(bs);
125
-
38
+ aio_context_acquire(aio_context);
126
if (perf->max_workers < 1) {
39
127
error_setg(errp, "max-workers must be greater than zero");
40
state->bs = bs;
128
return NULL;
41
+
129
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
42
+ /* Paired with .clean() */
130
return NULL;
43
bdrv_drained_begin(bs);
44
45
if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, errp)) {
46
- return;
47
+ goto out;
131
}
48
}
132
49
133
- if (perf->max_chunk && perf->max_chunk < cluster_size) {
50
if (bdrv_is_read_only(bs)) {
134
- error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
51
error_setg(errp, "Device '%s' is read only", device);
135
- "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
52
- return;
136
- return NULL;
53
+ goto out;
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
}
54
}
146
55
147
- cbw = bdrv_cbw_append(bs, target, filter_node_name,
56
if (!bdrv_can_snapshot(bs)) {
148
- cluster_size, false, &bcs, errp);
57
error_setg(errp, "Block format '%s' used by device '%s' "
149
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
58
"does not support internal snapshots",
150
if (!cbw) {
59
bs->drv->format_name, device);
151
goto error;
60
- return;
61
+ goto out;
152
}
62
}
153
63
154
+ cluster_size = block_copy_cluster_size(bcs);
64
if (!strlen(name)) {
65
error_setg(errp, "Name is empty");
66
- return;
67
+ goto out;
68
}
69
70
/* check whether a snapshot with name exist */
71
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
72
&local_err);
73
if (local_err) {
74
error_propagate(errp, local_err);
75
- return;
76
+ goto out;
77
} else if (ret) {
78
error_setg(errp,
79
"Snapshot with name '%s' already exists on device '%s'",
80
name, device);
81
- return;
82
+ goto out;
83
}
84
85
/* 3. take the snapshot */
86
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_prepare(BlkActionState *common,
87
error_setg_errno(errp, -ret1,
88
"Failed to create snapshot '%s' on device '%s'",
89
name, device);
90
- return;
91
+ goto out;
92
}
93
94
/* 4. succeed, mark a snapshot is created */
95
state->created = true;
155
+
96
+
156
+ if (perf->max_chunk && perf->max_chunk < cluster_size) {
97
+out:
157
+ error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
98
+ aio_context_release(aio_context);
158
+ "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
99
}
159
+ goto error;
100
160
+ }
101
static void internal_snapshot_abort(BlkActionState *common)
102
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common)
103
DO_UPCAST(InternalSnapshotState, common, common);
104
BlockDriverState *bs = state->bs;
105
QEMUSnapshotInfo *sn = &state->sn;
106
+ AioContext *aio_context;
107
Error *local_error = NULL;
108
109
if (!state->created) {
110
return;
111
}
112
113
+ aio_context = bdrv_get_aio_context(state->bs);
114
+ aio_context_acquire(aio_context);
161
+
115
+
162
/* job->len is fixed, so we can't allow resize */
116
if (bdrv_snapshot_delete(bs, sn->id_str, sn->name, &local_error) < 0) {
163
job = block_job_create(job_id, &backup_job_driver, txn, cbw,
117
error_reportf_err(local_error,
164
0, BLK_PERM_ALL,
118
"Failed to delete snapshot with id '%s' and "
165
diff --git a/block/block-copy.c b/block/block-copy.c
119
@@ -XXX,XX +XXX,XX @@ static void internal_snapshot_abort(BlkActionState *common)
166
index XXXXXXX..XXXXXXX 100644
120
sn->id_str, sn->name,
167
--- a/block/block-copy.c
121
bdrv_get_device_name(bs));
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
}
122
}
123
+
124
+ aio_context_release(aio_context);
186
}
125
}
187
126
188
+static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
127
static void internal_snapshot_clean(BlkActionState *common)
189
+ Error **errp)
128
{
190
+{
129
InternalSnapshotState *state = DO_UPCAST(InternalSnapshotState,
191
+ int ret;
130
common, common);
192
+ BlockDriverInfo bdi;
131
+ AioContext *aio_context;
193
+ bool target_does_cow = bdrv_backing_chain_next(target);
132
133
- if (state->aio_context) {
134
- if (state->bs) {
135
- bdrv_drained_end(state->bs);
136
- }
137
- aio_context_release(state->aio_context);
138
+ if (!state->bs) {
139
+ return;
140
}
194
+
141
+
195
+ /*
142
+ aio_context = bdrv_get_aio_context(state->bs);
196
+ * If there is no backing file on the target, we cannot rely on COW if our
143
+ aio_context_acquire(aio_context);
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
+
144
+
222
+ return MAX(BLOCK_COPY_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
145
+ bdrv_drained_end(state->bs);
223
+}
224
+
146
+
225
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
147
+ aio_context_release(aio_context);
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
}
148
}
246
149
247
+int64_t block_copy_cluster_size(BlockCopyState *s)
150
/* external snapshot private data */
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
--
151
--
304
2.31.1
152
2.14.3
305
153
306
154
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The dirty bitmap actions in qmp_transaction have not used AioContext
2
since the dirty bitmap locking discipline was introduced in commit
3
2119882c7eb7e2c612b24fc0c8d86f5887d6f1c3 ("block: introduce
4
dirty_bitmap_mutex"). Remove the unused field.
2
5
3
We are going to publish copy-before-write filter. So, user should be
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
able to create it with blockdev-add first, specifying both filtered and
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
target children. And then do blockdev-reopen, to actually insert the
8
Reviewed-by: Eric Blake <eblake@redhat.com>
6
filter where needed.
9
Message-id: 20171206144550.22295-7-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
blockdev.c | 13 -------------
13
1 file changed, 13 deletions(-)
7
14
8
Currently, filter unshares write permission unconditionally on source
15
diff --git a/blockdev.c b/blockdev.c
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
16
index XXXXXXX..XXXXXXX 100644
26
--- a/block/copy-before-write.c
17
--- a/blockdev.c
27
+++ b/block/copy-before-write.c
18
+++ b/blockdev.c
28
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
19
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDirtyBitmapState {
29
bdrv_default_perms(bs, c, role, reopen_queue,
20
BlkActionState common;
30
perm, shared, nperm, nshared);
21
BdrvDirtyBitmap *bitmap;
31
22
BlockDriverState *bs;
32
- if (perm & BLK_PERM_WRITE) {
23
- AioContext *aio_context;
33
- *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
24
HBitmap *backup;
34
+ if (!QLIST_EMPTY(&bs->parents)) {
25
bool prepared;
35
+ if (perm & BLK_PERM_WRITE) {
26
} BlockDirtyBitmapState;
36
+ *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
27
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
37
+ }
38
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
39
}
40
- *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
41
}
28
}
29
30
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
31
- /* AioContext is released in .clean() */
42
}
32
}
43
33
44
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
34
static void block_dirty_bitmap_clear_abort(BlkActionState *common)
45
index XXXXXXX..XXXXXXX 100644
35
@@ -XXX,XX +XXX,XX @@ static void block_dirty_bitmap_clear_commit(BlkActionState *common)
46
--- a/tests/qemu-iotests/283.out
36
hbitmap_free(state->backup);
47
+++ b/tests/qemu-iotests/283.out
37
}
48
@@ -XXX,XX +XXX,XX @@
38
49
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
39
-static void block_dirty_bitmap_clear_clean(BlkActionState *common)
50
{"return": {}}
40
-{
51
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
41
- BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
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)."}}
42
- common, common);
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)."}}
43
-
54
44
- if (state->aio_context) {
55
=== copy-before-write filter should be gone after job-finalize ===
45
- aio_context_release(state->aio_context);
46
- }
47
-}
48
-
49
static void abort_prepare(BlkActionState *common, Error **errp)
50
{
51
error_setg(errp, "Transaction aborted using Abort action");
52
@@ -XXX,XX +XXX,XX @@ static const BlkActionOps actions[] = {
53
.prepare = block_dirty_bitmap_clear_prepare,
54
.commit = block_dirty_bitmap_clear_commit,
55
.abort = block_dirty_bitmap_clear_abort,
56
- .clean = block_dirty_bitmap_clear_clean,
57
}
58
};
56
59
57
--
60
--
58
2.31.1
61
2.14.3
59
62
60
63
diff view generated by jsdifflib
1
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
1
Encapsulate IOThread QOM object lookup so that callers don't need to
2
know how and where IOThread objects live.
2
3
3
Include linux/fs.h to avoid the following build failure on uclibc or
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
musl raised since version 6.0.0:
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Message-id: 20171206144550.22295-8-stefanha@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
include/sysemu/iothread.h | 1 +
11
iothread.c | 7 +++++++
12
2 files changed, 8 insertions(+)
5
13
6
../block/export/fuse.c: In function 'fuse_lseek':
14
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
7
../block/export/fuse.c:641:19: error: 'SEEK_HOLE' undeclared (first use in this function)
8
641 | if (whence != SEEK_HOLE && whence != SEEK_DATA) {
9
| ^~~~~~~~~
10
../block/export/fuse.c:641:19: note: each undeclared identifier is reported only once for each function it appears in
11
../block/export/fuse.c:641:42: error: 'SEEK_DATA' undeclared (first use in this function); did you mean 'SEEK_SET'?
12
641 | if (whence != SEEK_HOLE && whence != SEEK_DATA) {
13
| ^~~~~~~~~
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
---
23
block/export/fuse.c | 3 +++
24
1 file changed, 3 insertions(+)
25
26
diff --git a/block/export/fuse.c b/block/export/fuse.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/block/export/fuse.c
16
--- a/include/sysemu/iothread.h
29
+++ b/block/export/fuse.c
17
+++ b/include/sysemu/iothread.h
30
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
#include <fuse.h>
19
OBJECT_CHECK(IOThread, obj, TYPE_IOTHREAD)
32
#include <fuse_lowlevel.h>
20
33
21
char *iothread_get_id(IOThread *iothread);
34
+#ifdef __linux__
22
+IOThread *iothread_by_id(const char *id);
35
+#include <linux/fs.h>
23
AioContext *iothread_get_aio_context(IOThread *iothread);
36
+#endif
24
void iothread_stop_all(void);
37
25
GMainContext *iothread_get_g_main_context(IOThread *iothread);
38
/* Prevent overly long bounce buffer allocations */
26
diff --git a/iothread.c b/iothread.c
39
#define FUSE_MAX_BOUNCE_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024))
27
index XXXXXXX..XXXXXXX 100644
28
--- a/iothread.c
29
+++ b/iothread.c
30
@@ -XXX,XX +XXX,XX @@ void iothread_destroy(IOThread *iothread)
31
{
32
object_unparent(OBJECT(iothread));
33
}
34
+
35
+/* Lookup IOThread by its id. Only finds user-created objects, not internal
36
+ * iothread_create() objects. */
37
+IOThread *iothread_by_id(const char *id)
38
+{
39
+ return IOTHREAD(object_resolve_path_type(id, TYPE_IOTHREAD, NULL));
40
+}
40
--
41
--
41
2.31.1
42
2.14.3
42
43
43
44
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
Currently there is no easy way for iotests to ensure that a BDS is bound
2
to a particular IOThread. Normally the virtio-blk device calls
3
blk_set_aio_context() when dataplane is enabled during guest driver
4
initialization. This never happens in iotests since -machine
5
accel=qtest means there is no guest activity (including device driver
6
initialization).
2
7
3
Move part of bdrv_cbw_append() to new function cbw_open(). It's an
8
This patch adds a QMP command to explicitly assign IOThreads in test
4
intermediate step for adding normal .bdrv_open() handler to the
9
cases. See qapi/block-core.json for a description of the command.
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
10
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20210824083856.17408-15-vsementsov@virtuozzo.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
Message-id: 20171206144550.22295-9-stefanha@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
16
---
13
block/copy-before-write.c | 69 +++++++++++++++++++++++----------------
17
qapi/block-core.json | 36 ++++++++++++++++++++++++++++++++++++
14
1 file changed, 41 insertions(+), 28 deletions(-)
18
blockdev.c | 41 +++++++++++++++++++++++++++++++++++++++++
19
2 files changed, 77 insertions(+)
15
20
16
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
21
diff --git a/qapi/block-core.json b/qapi/block-core.json
17
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
18
--- a/block/copy-before-write.c
23
--- a/qapi/block-core.json
19
+++ b/block/copy-before-write.c
24
+++ b/qapi/block-core.json
20
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
25
@@ -XXX,XX +XXX,XX @@
21
}
26
'data' : { 'parent': 'str',
27
'*child': 'str',
28
'*node': 'str' } }
29
+
30
+##
31
+# @x-blockdev-set-iothread:
32
+#
33
+# Move @node and its children into the @iothread. If @iothread is null then
34
+# move @node and its children into the main loop.
35
+#
36
+# The node must not be attached to a BlockBackend.
37
+#
38
+# @node-name: the name of the block driver node
39
+#
40
+# @iothread: the name of the IOThread object or null for the main loop
41
+#
42
+# Note: this command is experimental and intended for test cases that need
43
+# control over IOThreads only.
44
+#
45
+# Since: 2.12
46
+#
47
+# Example:
48
+#
49
+# 1. Move a node into an IOThread
50
+# -> { "execute": "x-blockdev-set-iothread",
51
+# "arguments": { "node-name": "disk1",
52
+# "iothread": "iothread0" } }
53
+# <- { "return": {} }
54
+#
55
+# 2. Move a node into the main loop
56
+# -> { "execute": "x-blockdev-set-iothread",
57
+# "arguments": { "node-name": "disk1",
58
+# "iothread": null } }
59
+# <- { "return": {} }
60
+#
61
+##
62
+{ 'command': 'x-blockdev-set-iothread',
63
+ 'data' : { 'node-name': 'str',
64
+ 'iothread': 'StrOrNull' } }
65
diff --git a/blockdev.c b/blockdev.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/blockdev.c
68
+++ b/blockdev.c
69
@@ -XXX,XX +XXX,XX @@
70
#include "qapi/qmp/qerror.h"
71
#include "qapi/qobject-output-visitor.h"
72
#include "sysemu/sysemu.h"
73
+#include "sysemu/iothread.h"
74
#include "block/block_int.h"
75
#include "qmp-commands.h"
76
#include "block/trace.h"
77
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
78
return head;
22
}
79
}
23
80
24
+static int cbw_init(BlockDriverState *top, BlockDriverState *source,
81
+void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
25
+ BlockDriverState *target, bool compress, Error **errp)
82
+ Error **errp)
26
+{
83
+{
27
+ BDRVCopyBeforeWriteState *state = top->opaque;
84
+ AioContext *old_context;
85
+ AioContext *new_context;
86
+ BlockDriverState *bs;
28
+
87
+
29
+ top->total_sectors = source->total_sectors;
88
+ bs = bdrv_find_node(node_name);
30
+ top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
89
+ if (!bs) {
31
+ (BDRV_REQ_FUA & source->supported_write_flags);
90
+ error_setg(errp, "Cannot find node %s", node_name);
32
+ top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
91
+ return;
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
+ }
92
+ }
43
+
93
+
44
+ bdrv_ref(source);
94
+ /* If we want to allow more extreme test scenarios this guard could be
45
+ top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
95
+ * removed. For now it protects against accidents. */
46
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
96
+ if (bdrv_has_blk(bs)) {
47
+ errp);
97
+ error_setg(errp, "Node %s is in use", node_name);
48
+ if (!top->file) {
98
+ return;
49
+ error_prepend(errp, "Cannot attach file child: ");
50
+ return -EINVAL;
51
+ }
99
+ }
52
+
100
+
53
+ state->bcs = block_copy_state_new(top->file, state->target, false, compress,
101
+ if (iothread->type == QTYPE_QSTRING) {
54
+ errp);
102
+ IOThread *obj = iothread_by_id(iothread->u.s);
55
+ if (!state->bcs) {
103
+ if (!obj) {
56
+ error_prepend(errp, "Cannot create block-copy-state: ");
104
+ error_setg(errp, "Cannot find iothread %s", iothread->u.s);
57
+ return -EINVAL;
105
+ return;
106
+ }
107
+
108
+ new_context = iothread_get_aio_context(obj);
109
+ } else {
110
+ new_context = qemu_get_aio_context();
58
+ }
111
+ }
59
+
112
+
60
+ return 0;
113
+ old_context = bdrv_get_aio_context(bs);
114
+ aio_context_acquire(old_context);
115
+
116
+ bdrv_set_aio_context(bs, new_context);
117
+
118
+ aio_context_release(old_context);
61
+}
119
+}
62
+
120
+
63
BlockDriver bdrv_cbw_filter = {
121
QemuOptsList qemu_common_drive_opts = {
64
.format_name = "copy-before-write",
122
.name = "drive",
65
.instance_size = sizeof(BDRVCopyBeforeWriteState),
123
.head = QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head),
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
--
124
--
106
2.31.1
125
2.14.3
107
126
108
127
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
QMP 'transaction' blockdev-snapshot-sync with multiple disks in an
2
IOThread is an untested code path. Several bugs have been found in
3
connection with this command. This patch adds a test case to prevent
4
future regressions.
2
5
3
The only caller pass copy_range and compress both false. Let's just
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
drop these arguments.
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Message-id: 20171206144550.22295-10-stefanha@redhat.com
10
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
12
tests/qemu-iotests/202 | 95 ++++++++++++++++++++++++++++++++++++++++++++++
13
tests/qemu-iotests/202.out | 11 ++++++
14
tests/qemu-iotests/group | 1 +
15
3 files changed, 107 insertions(+)
16
create mode 100755 tests/qemu-iotests/202
17
create mode 100644 tests/qemu-iotests/202.out
5
18
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
7
Message-Id: <20210824083856.17408-35-vsementsov@virtuozzo.com>
20
new file mode 100755
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
index XXXXXXX..XXXXXXX
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
22
--- /dev/null
10
---
23
+++ b/tests/qemu-iotests/202
11
include/block/block-copy.h | 1 -
24
@@ -XXX,XX +XXX,XX @@
12
block/block-copy.c | 5 ++---
25
+#!/usr/bin/env python
13
block/copy-before-write.c | 2 +-
26
+#
14
3 files changed, 3 insertions(+), 5 deletions(-)
27
+# Copyright (C) 2017 Red Hat, Inc.
15
28
+#
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
29
+# This program is free software; you can redistribute it and/or modify
30
+# it under the terms of the GNU General Public License as published by
31
+# the Free Software Foundation; either version 2 of the License, or
32
+# (at your option) any later version.
33
+#
34
+# This program is distributed in the hope that it will be useful,
35
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
36
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37
+# GNU General Public License for more details.
38
+#
39
+# You should have received a copy of the GNU General Public License
40
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
41
+#
42
+# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
43
+#
44
+# Check that QMP 'transaction' blockdev-snapshot-sync with multiple drives on a
45
+# single IOThread completes successfully. This particular command triggered a
46
+# hang due to recursive AioContext locking and BDRV_POLL_WHILE(). Protect
47
+# against regressions.
48
+
49
+import iotests
50
+
51
+iotests.verify_image_format(supported_fmts=['qcow2'])
52
+iotests.verify_platform(['linux'])
53
+
54
+with iotests.FilePath('disk0.img') as disk0_img_path, \
55
+ iotests.FilePath('disk1.img') as disk1_img_path, \
56
+ iotests.FilePath('disk0-snap.img') as disk0_snap_img_path, \
57
+ iotests.FilePath('disk1-snap.img') as disk1_snap_img_path, \
58
+ iotests.VM() as vm:
59
+
60
+ img_size = '10M'
61
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size)
62
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size)
63
+
64
+ iotests.log('Launching VM...')
65
+ vm.launch()
66
+
67
+ iotests.log('Adding IOThread...')
68
+ iotests.log(vm.qmp('object-add',
69
+ qom_type='iothread',
70
+ id='iothread0'))
71
+
72
+ iotests.log('Adding blockdevs...')
73
+ iotests.log(vm.qmp('blockdev-add',
74
+ driver=iotests.imgfmt,
75
+ node_name='disk0',
76
+ file={
77
+ 'driver': 'file',
78
+ 'filename': disk0_img_path,
79
+ }))
80
+ iotests.log(vm.qmp('blockdev-add',
81
+ driver=iotests.imgfmt,
82
+ node_name='disk1',
83
+ file={
84
+ 'driver': 'file',
85
+ 'filename': disk1_img_path,
86
+ }))
87
+
88
+ iotests.log('Setting iothread...')
89
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
90
+ node_name='disk0',
91
+ iothread='iothread0'))
92
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
93
+ node_name='disk1',
94
+ iothread='iothread0'))
95
+
96
+ iotests.log('Creating external snapshots...')
97
+ iotests.log(vm.qmp(
98
+ 'transaction',
99
+ actions=[
100
+ {
101
+ 'data': {
102
+ 'node-name': 'disk0',
103
+ 'snapshot-file': disk0_snap_img_path,
104
+ 'snapshot-node-name': 'disk0-snap',
105
+ 'mode': 'absolute-paths',
106
+ 'format': iotests.imgfmt,
107
+ },
108
+ 'type': 'blockdev-snapshot-sync'
109
+ }, {
110
+ 'data': {
111
+ 'node-name': 'disk1',
112
+ 'snapshot-file': disk1_snap_img_path,
113
+ 'snapshot-node-name': 'disk1-snap',
114
+ 'mode': 'absolute-paths',
115
+ 'format': iotests.imgfmt
116
+ },
117
+ 'type': 'blockdev-snapshot-sync'
118
+ }
119
+ ]))
120
diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out
121
new file mode 100644
122
index XXXXXXX..XXXXXXX
123
--- /dev/null
124
+++ b/tests/qemu-iotests/202.out
125
@@ -XXX,XX +XXX,XX @@
126
+Launching VM...
127
+Adding IOThread...
128
+{u'return': {}}
129
+Adding blockdevs...
130
+{u'return': {}}
131
+{u'return': {}}
132
+Setting iothread...
133
+{u'return': {}}
134
+{u'return': {}}
135
+Creating external snapshots...
136
+{u'return': {}}
137
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
17
index XXXXXXX..XXXXXXX 100644
138
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
139
--- a/tests/qemu-iotests/group
19
+++ b/include/block/block-copy.h
140
+++ b/tests/qemu-iotests/group
20
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
141
@@ -XXX,XX +XXX,XX @@
21
typedef struct BlockCopyCallState BlockCopyCallState;
142
197 rw auto quick
22
143
198 rw auto
23
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
144
200 rw auto
24
- bool use_copy_range, bool compress,
145
+202 rw auto quick
25
Error **errp);
26
27
/* Function should be called prior any actual copy request */
28
diff --git a/block/block-copy.c b/block/block-copy.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-copy.c
31
+++ b/block/block-copy.c
32
@@ -XXX,XX +XXX,XX @@ static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
33
}
34
35
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
36
- bool use_copy_range,
37
- bool compress, Error **errp)
38
+ Error **errp)
39
{
40
BlockCopyState *s;
41
int64_t cluster_size;
42
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
43
cluster_size),
44
};
45
46
- block_copy_set_copy_opts(s, use_copy_range, compress);
47
+ block_copy_set_copy_opts(s, false, false);
48
49
ratelimit_init(&s->rate_limit);
50
qemu_co_mutex_init(&s->lock);
51
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/copy-before-write.c
54
+++ b/block/copy-before-write.c
55
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
56
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
57
bs->file->bs->supported_zero_flags);
58
59
- s->bcs = block_copy_state_new(bs->file, s->target, false, false, errp);
60
+ s->bcs = block_copy_state_new(bs->file, s->target, errp);
61
if (!s->bcs) {
62
error_prepend(errp, "Cannot create block-copy-state: ");
63
return -EINVAL;
64
--
146
--
65
2.31.1
147
2.14.3
66
148
67
149
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mark Kanda <mark.kanda@oracle.com>
2
2
3
Add field, so property can declare support for setting the property
3
Depending on the configuration, it can be beneficial to adjust the virtio-blk
4
when device is realized. To be used in the following commit.
4
queue size to something other than the current default of 128. Add a new
5
property to make the queue size configurable.
5
6
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
8
Message-Id: <20210824083856.17408-4-vsementsov@virtuozzo.com>
9
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Ameya More <ameya.more@oracle.com>
11
Message-id: 52e6d742811f10dbd16e996e86cf375b9577c187.1513005190.git.mark.kanda@oracle.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
13
---
11
include/hw/qdev-properties.h | 1 +
14
include/hw/virtio/virtio-blk.h | 1 +
12
hw/core/qdev-properties.c | 6 +++---
15
hw/block/virtio-blk.c | 10 +++++++++-
13
2 files changed, 4 insertions(+), 3 deletions(-)
16
2 files changed, 10 insertions(+), 1 deletion(-)
14
17
15
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
18
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/qdev-properties.h
20
--- a/include/hw/virtio/virtio-blk.h
18
+++ b/include/hw/qdev-properties.h
21
+++ b/include/hw/virtio/virtio-blk.h
19
@@ -XXX,XX +XXX,XX @@ struct PropertyInfo {
22
@@ -XXX,XX +XXX,XX @@ struct VirtIOBlkConf
20
const char *name;
23
uint32_t config_wce;
21
const char *description;
24
uint32_t request_merging;
22
const QEnumLookup *enum_table;
25
uint16_t num_queues;
23
+ bool realized_set_allowed; /* allow setting property on realized device */
26
+ uint16_t queue_size;
24
int (*print)(Object *obj, Property *prop, char *dest, size_t len);
27
};
25
void (*set_default_value)(ObjectProperty *op, const Property *prop);
28
26
ObjectProperty *(*create)(ObjectClass *oc, const char *name,
29
struct VirtIOBlockDataPlane;
27
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
30
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
28
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/core/qdev-properties.c
32
--- a/hw/block/virtio-blk.c
30
+++ b/hw/core/qdev-properties.c
33
+++ b/hw/block/virtio-blk.c
31
@@ -XXX,XX +XXX,XX @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
34
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
32
35
error_setg(errp, "num-queues property must be larger than 0");
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;
36
return;
52
}
37
}
53
38
+ if (!is_power_of_2(conf->queue_size) ||
39
+ conf->queue_size > VIRTQUEUE_MAX_SIZE) {
40
+ error_setg(errp, "invalid queue-size property (%" PRIu16 "), "
41
+ "must be a power of 2 (max %d)",
42
+ conf->queue_size, VIRTQUEUE_MAX_SIZE);
43
+ return;
44
+ }
45
46
blkconf_serial(&conf->conf, &conf->serial);
47
if (!blkconf_apply_backend_options(&conf->conf,
48
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
49
s->sector_mask = (s->conf.conf.logical_block_size / BDRV_SECTOR_SIZE) - 1;
50
51
for (i = 0; i < conf->num_queues; i++) {
52
- virtio_add_queue(vdev, 128, virtio_blk_handle_output);
53
+ virtio_add_queue(vdev, conf->queue_size, virtio_blk_handle_output);
54
}
55
virtio_blk_data_plane_create(vdev, conf, &s->dataplane, &err);
56
if (err != NULL) {
57
@@ -XXX,XX +XXX,XX @@ static Property virtio_blk_properties[] = {
58
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
59
true),
60
DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
61
+ DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 128),
62
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
63
IOThread *),
64
DEFINE_PROP_END_OF_LIST(),
54
--
65
--
55
2.31.1
66
2.14.3
56
67
57
68
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Mark Kanda <mark.kanda@oracle.com>
2
2
3
Refactor the function to replace child at last. Thus we don't need to
3
virtio-blk logical block size should never be larger than physical block
4
revert it and code is simplified.
4
size because it doesn't make sense to have such configurations. QEMU doesn't
5
have a way to effectively express this condition; the best it can do is
6
report the physical block exponent as 0 - indicating the logical block size
7
equals the physical block size.
5
8
6
block-copy state initialization being done before replacing the child
9
This is identical to commit 3da023b5827543ee4c022986ea2ad9d1274410b2
7
doesn't need any drained section.
10
but applied to virtio-blk (instead of virtio-scsi).
8
11
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Signed-off-by: Mark Kanda <mark.kanda@oracle.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
11
Message-Id: <20210824083856.17408-14-vsementsov@virtuozzo.com>
14
Reviewed-by: Ameya More <ameya.more@oracle.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
16
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
17
Message-id: 773169891f9f2deb4cb7c4ef2655580dbe24c1d1.1513005190.git.mark.kanda@oracle.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
19
---
14
block/copy-before-write.c | 33 +++++++++++----------------------
20
hw/block/virtio-blk.c | 7 +++++++
15
1 file changed, 11 insertions(+), 22 deletions(-)
21
1 file changed, 7 insertions(+)
16
22
17
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
23
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
18
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
19
--- a/block/copy-before-write.c
25
--- a/hw/block/virtio-blk.c
20
+++ b/block/copy-before-write.c
26
+++ b/hw/block/virtio-blk.c
21
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
27
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
22
int ret;
28
23
BDRVCopyBeforeWriteState *state;
29
blkconf_blocksizes(&conf->conf);
24
BlockDriverState *top;
30
25
- bool appended = false;
31
+ if (conf->conf.logical_block_size >
26
32
+ conf->conf.physical_block_size) {
27
assert(source->total_sectors == target->total_sectors);
33
+ error_setg(errp,
28
34
+ "logical_block_size > physical_block_size not supported");
29
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
35
+ return;
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
+ }
36
+ }
71
+
37
+
72
+ *bcs = state->bcs;
38
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
73
39
sizeof(struct virtio_blk_config));
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
40
90
--
41
--
91
2.31.1
42
2.14.3
92
43
93
44
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Add function to transactionally replace bs inside BdrvChild.
3
BDRV_POLL_WHILE() does not support recursive AioContext locking. It
4
only releases the AioContext lock once regardless of how many times the
5
caller has acquired it. This results in a hang since the IOThread does
6
not make progress while the AioContext is still locked.
4
7
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
The following steps trigger the hang:
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
7
Message-Id: <20210824083856.17408-2-vsementsov@virtuozzo.com>
10
$ qemu-system-x86_64 -M accel=kvm -m 1G -cpu host \
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
-object iothread,id=iothread0 \
12
-device virtio-scsi-pci,iothread=iothread0 \
13
-drive if=none,id=drive0,file=test.img,format=raw \
14
-device scsi-hd,drive=drive0 \
15
-drive if=none,id=drive1,file=test.img,format=raw \
16
-device scsi-hd,drive=drive1
17
$ qemu-system-x86_64 ...same options... \
18
-incoming tcp::1234
19
(qemu) migrate tcp:127.0.0.1:1234
20
...hang...
21
22
Tested-by: Stefan Hajnoczi <stefanha@redhat.com>
23
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Message-id: 20171207201320.19284-2-stefanha@redhat.com
26
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
27
---
10
include/block/block.h | 2 ++
28
block.c | 14 +++++++++++---
11
block.c | 31 +++++++++++++++++++++++++++++++
29
1 file changed, 11 insertions(+), 3 deletions(-)
12
2 files changed, 33 insertions(+)
13
30
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
31
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
33
--- a/block.c
30
+++ b/block.c
34
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ out:
35
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
36
BdrvNextIterator it;
37
int ret = 0;
38
int pass;
39
+ GSList *aio_ctxs = NULL, *ctx;
40
41
for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
42
- aio_context_acquire(bdrv_get_aio_context(bs));
43
+ AioContext *aio_context = bdrv_get_aio_context(bs);
44
+
45
+ if (!g_slist_find(aio_ctxs, aio_context)) {
46
+ aio_ctxs = g_slist_prepend(aio_ctxs, aio_context);
47
+ aio_context_acquire(aio_context);
48
+ }
49
}
50
51
/* We do two passes of inactivation. The first pass calls to drivers'
52
@@ -XXX,XX +XXX,XX @@ int bdrv_inactivate_all(void)
53
}
54
55
out:
56
- for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
57
- aio_context_release(bdrv_get_aio_context(bs));
58
+ for (ctx = aio_ctxs; ctx != NULL; ctx = ctx->next) {
59
+ AioContext *aio_context = ctx->data;
60
+ aio_context_release(aio_context);
61
}
62
+ g_slist_free(aio_ctxs);
63
32
return ret;
64
return ret;
33
}
65
}
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
--
66
--
70
2.31.1
67
2.14.3
71
68
72
69
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
See the patch for why nested AioContext locking is no longer allowed.
2
2
3
Silences a new pylint warning. The dangers of *not* doing this are
3
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
somewhat unclear; I believe the file object gets garbage collected
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
eventually, but possibly the way in which it happens is
5
Message-id: 20171207201320.19284-3-stefanha@redhat.com
6
non-deterministic. Maybe this is a valid warning, but if there are
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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
---
7
---
14
tests/qemu-iotests/iotests.py | 7 ++++---
8
docs/devel/multiple-iothreads.txt | 7 ++++---
15
1 file changed, 4 insertions(+), 3 deletions(-)
9
1 file changed, 4 insertions(+), 3 deletions(-)
16
10
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
11
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
13
--- a/docs/devel/multiple-iothreads.txt
20
+++ b/tests/qemu-iotests/iotests.py
14
+++ b/docs/devel/multiple-iothreads.txt
21
@@ -XXX,XX +XXX,XX @@ def notrun(reason):
15
@@ -XXX,XX +XXX,XX @@
22
# Each test in qemu-iotests has a number ("seq")
16
-Copyright (c) 2014 Red Hat Inc.
23
seq = os.path.basename(sys.argv[0])
17
+Copyright (c) 2014-2017 Red Hat Inc.
24
18
25
- open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
19
This work is licensed under the terms of the GNU GPL, version 2 or later. See
26
+ with open('%s/%s.notrun' % (output_dir, seq), 'w') as outfile:
20
the COPYING file in the top-level directory.
27
+ outfile.write(reason + '\n')
21
@@ -XXX,XX +XXX,XX @@ aio_context_acquire()/aio_context_release() for mutual exclusion. Once the
28
logger.warning("%s not run: %s", seq, reason)
22
context is acquired no other thread can access it or run event loop iterations
29
sys.exit(0)
23
in this AioContext.
30
24
31
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
25
-aio_context_acquire()/aio_context_release() calls may be nested. This
32
# Each test in qemu-iotests has a number ("seq")
26
-means you can call them if you're not sure whether #2 applies.
33
seq = os.path.basename(sys.argv[0])
27
+Legacy code sometimes nests aio_context_acquire()/aio_context_release() calls.
34
28
+Do not use nesting anymore, it is incompatible with the BDRV_POLL_WHILE() macro
35
- open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
29
+used in the block layer and can lead to hangs.
36
- ' [case not run] ' + reason + '\n')
30
37
+ with open('%s/%s.casenotrun' % (output_dir, seq), 'a') as outfile:
31
There is currently no lock ordering rule if a thread needs to acquire multiple
38
+ outfile.write(' [case not run] ' + reason + '\n')
32
AioContexts simultaneously. Therefore, it is only safe for code holding the
39
40
def _verify_image_format(supported_fmts: Sequence[str] = (),
41
unsupported_fmts: Sequence[str] = ()) -> None:
42
--
33
--
43
2.31.1
34
2.14.3
44
35
45
36
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
When a node is already associated with a BlockBackend the
2
x-blockdev-set-iothread command refuses to set the IOThread. This is to
3
prevent accidentally changing the IOThread when the nodes are in use.
2
4
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
When the nodes are created with -drive they automatically get a
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
BlockBackend. In that case we know nothing is using them yet and it's
5
Acked-by: Markus Armbruster <armbru@redhat.com>
7
safe to set the IOThread. Add a force boolean to override the check.
6
Message-Id: <20210824083856.17408-23-vsementsov@virtuozzo.com>
8
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Message-id: 20171207201320.19284-4-stefanha@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
13
---
9
qapi/block-core.json | 25 +++++++++++++++++++++++--
14
qapi/block-core.json | 6 +++++-
10
1 file changed, 23 insertions(+), 2 deletions(-)
15
blockdev.c | 11 ++++++-----
16
2 files changed, 11 insertions(+), 6 deletions(-)
11
17
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
18
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
20
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
21
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
22
@@ -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
#
23
#
22
# Since: 2.9
24
# @iothread: the name of the IOThread object or null for the main loop
23
##
25
#
24
{ 'enum': 'BlockdevDriver',
26
+# @force: true if the node and its children should be moved when a BlockBackend
25
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
27
+# is already attached
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
+#
28
+#
40
+# Driver specific block device options for the copy-before-write driver,
29
# Note: this command is experimental and intended for test cases that need
41
+# which does so called copy-before-write operations: when data is
30
# control over IOThreads only.
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
#
31
#
59
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
60
'bochs': 'BlockdevOptionsGenericFormat',
33
##
61
'cloop': 'BlockdevOptionsGenericFormat',
34
{ 'command': 'x-blockdev-set-iothread',
62
'compress': 'BlockdevOptionsGenericFormat',
35
'data' : { 'node-name': 'str',
63
+ 'copy-before-write':'BlockdevOptionsCbw',
36
- 'iothread': 'StrOrNull' } }
64
'copy-on-read':'BlockdevOptionsCor',
37
+ 'iothread': 'StrOrNull',
65
'dmg': 'BlockdevOptionsGenericFormat',
38
+ '*force': 'bool' } }
66
'file': 'BlockdevOptionsFile',
39
diff --git a/blockdev.c b/blockdev.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/blockdev.c
42
+++ b/blockdev.c
43
@@ -XXX,XX +XXX,XX @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp)
44
}
45
46
void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
47
- Error **errp)
48
+ bool has_force, bool force, Error **errp)
49
{
50
AioContext *old_context;
51
AioContext *new_context;
52
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
53
return;
54
}
55
56
- /* If we want to allow more extreme test scenarios this guard could be
57
- * removed. For now it protects against accidents. */
58
- if (bdrv_has_blk(bs)) {
59
- error_setg(errp, "Node %s is in use", node_name);
60
+ /* Protects against accidents. */
61
+ if (!(has_force && force) && bdrv_has_blk(bs)) {
62
+ error_setg(errp, "Node %s is associated with a BlockBackend and could "
63
+ "be in use (use force=true to override this check)",
64
+ node_name);
65
return;
66
}
67
67
--
68
--
68
2.31.1
69
2.14.3
69
70
70
71
diff view generated by jsdifflib
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
The VM.add_object() method can be used to add IOThreads or memory
2
backend objects.
2
3
3
When using -valgrind on the script tests, it generates a log file
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
4
in $TEST_DIR that is either read (if valgrind finds problems) or
5
Reviewed-by: Eric Blake <eblake@redhat.com>
5
otherwise deleted. Provide the same exact behavior when using
6
Message-id: 20171207201320.19284-5-stefanha@redhat.com
6
-valgrind on the python tests.
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
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
---
8
---
14
tests/qemu-iotests/iotests.py | 11 +++++++++++
9
tests/qemu-iotests/iotests.py | 5 +++++
15
1 file changed, 11 insertions(+)
10
1 file changed, 5 insertions(+)
16
11
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
14
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
15
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def __init__(self, path_suffix=''):
16
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
22
sock_dir=sock_dir, qmp_timer=timer)
17
socket_scm_helper=socket_scm_helper)
23
self._num_drives = 0
18
self._num_drives = 0
24
19
25
+ def _post_shutdown(self) -> None:
20
+ def add_object(self, opts):
26
+ super()._post_shutdown()
21
+ self._args.append('-object')
27
+ if not qemu_valgrind or not self._popen:
22
+ self._args.append(opts)
28
+ return
23
+ return self
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
+
24
+
36
def add_object(self, opts):
25
def add_device(self, opts):
37
self._args.append('-object')
26
self._args.append('-device')
38
self._args.append(opts)
27
self._args.append(opts)
39
--
28
--
40
2.31.1
29
2.14.3
41
30
42
31
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
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
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 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
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
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
There is a small chance that iothread_stop() hangs as follows:
2
2
3
We'll need a possibility to set compress and use_copy_range options
3
Thread 3 (Thread 0x7f63eba5f700 (LWP 16105)):
4
after initialization of the state. So make corresponding part of
4
#0 0x00007f64012c09b6 in ppoll () at /lib64/libc.so.6
5
block_copy_state_new() separate and public.
5
#1 0x000055959992eac9 in ppoll (__ss=0x0, __timeout=0x0, __nfds=<optimized out>, __fds=<optimized out>) at /usr/include/bits/poll2.h:77
6
#2 0x000055959992eac9 in qemu_poll_ns (fds=<optimized out>, nfds=<optimized out>, timeout=<optimized out>) at util/qemu-timer.c:322
7
#3 0x0000559599930711 in aio_poll (ctx=0x55959bdb83c0, blocking=blocking@entry=true) at util/aio-posix.c:629
8
#4 0x00005595996806fe in iothread_run (opaque=0x55959bd78400) at iothread.c:59
9
#5 0x00007f640159f609 in start_thread () at /lib64/libpthread.so.0
10
#6 0x00007f64012cce6f in clone () at /lib64/libc.so.6
6
11
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Thread 1 (Thread 0x7f640b45b280 (LWP 16103)):
8
Message-Id: <20210824083856.17408-8-vsementsov@virtuozzo.com>
13
#0 0x00007f64015a0b6d in pthread_join () at /lib64/libpthread.so.0
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
#1 0x00005595999332ef in qemu_thread_join (thread=<optimized out>) at util/qemu-thread-posix.c:547
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
#2 0x00005595996808ae in iothread_stop (iothread=<optimized out>) at iothread.c:91
16
#3 0x000055959968094d in iothread_stop_iter (object=<optimized out>, opaque=<optimized out>) at iothread.c:102
17
#4 0x0000559599857d97 in do_object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0, recurse=recurse@entry=false) at qom/object.c:852
18
#5 0x0000559599859477 in object_child_foreach (obj=obj@entry=0x55959bdb8100, fn=fn@entry=0x559599680930 <iothread_stop_iter>, opaque=opaque@entry=0x0) at qom/object.c:867
19
#6 0x0000559599680a6e in iothread_stop_all () at iothread.c:341
20
#7 0x000055959955b1d5 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4913
21
22
The relevant code from iothread_run() is:
23
24
while (!atomic_read(&iothread->stopping)) {
25
aio_poll(iothread->ctx, true);
26
27
and iothread_stop():
28
29
iothread->stopping = true;
30
aio_notify(iothread->ctx);
31
...
32
qemu_thread_join(&iothread->thread);
33
34
The following scenario can occur:
35
36
1. IOThread:
37
while (!atomic_read(&iothread->stopping)) -> stopping=false
38
39
2. Main loop:
40
iothread->stopping = true;
41
aio_notify(iothread->ctx);
42
43
3. IOThread:
44
aio_poll(iothread->ctx, true); -> hang
45
46
The bug is explained by the AioContext->notify_me doc comments:
47
48
"If this field is 0, everything (file descriptors, bottom halves,
49
timers) will be re-evaluated before the next blocking poll(), thus the
50
event_notifier_set call can be skipped."
51
52
The problem is that "everything" does not include checking
53
iothread->stopping. This means iothread_run() will block in aio_poll()
54
if aio_notify() was called just before aio_poll().
55
56
This patch fixes the hang by replacing aio_notify() with
57
aio_bh_schedule_oneshot(). This makes aio_poll() or g_main_loop_run()
58
to return.
59
60
Implementing this properly required a new bool running flag. The new
61
flag prevents races that are tricky if we try to use iothread->stopping.
62
Now iothread->stopping is purely for iothread_stop() and
63
iothread->running is purely for the iothread_run() thread.
64
65
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
66
Reviewed-by: Eric Blake <eblake@redhat.com>
67
Message-id: 20171207201320.19284-6-stefanha@redhat.com
68
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
69
---
12
include/block/block-copy.h | 3 +++
70
include/sysemu/iothread.h | 3 ++-
13
block/block-copy.c | 49 ++++++++++++++++++++++----------------
71
iothread.c | 20 +++++++++++++++-----
14
2 files changed, 32 insertions(+), 20 deletions(-)
72
2 files changed, 17 insertions(+), 6 deletions(-)
15
73
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
74
diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h
17
index XXXXXXX..XXXXXXX 100644
75
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
76
--- a/include/sysemu/iothread.h
19
+++ b/include/block/block-copy.h
77
+++ b/include/sysemu/iothread.h
20
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
78
@@ -XXX,XX +XXX,XX @@ typedef struct {
21
int64_t cluster_size, bool use_copy_range,
79
GOnce once;
22
bool compress, Error **errp);
80
QemuMutex init_done_lock;
23
81
QemuCond init_done_cond; /* is thread initialization done? */
24
+/* Function should be called prior any actual copy request */
82
- bool stopping;
25
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
83
+ bool stopping; /* has iothread_stop() been called? */
26
+ bool compress);
84
+ bool running; /* should iothread_run() continue? */
27
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
85
int thread_id;
28
86
29
void block_copy_state_free(BlockCopyState *s);
87
/* AioContext poll parameters */
30
diff --git a/block/block-copy.c b/block/block-copy.c
88
diff --git a/iothread.c b/iothread.c
31
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
32
--- a/block/block-copy.c
90
--- a/iothread.c
33
+++ b/block/block-copy.c
91
+++ b/iothread.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
92
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
35
target->bs->bl.max_transfer));
93
qemu_cond_signal(&iothread->init_done_cond);
94
qemu_mutex_unlock(&iothread->init_done_lock);
95
96
- while (!atomic_read(&iothread->stopping)) {
97
+ while (iothread->running) {
98
aio_poll(iothread->ctx, true);
99
100
if (atomic_read(&iothread->worker_context)) {
101
@@ -XXX,XX +XXX,XX @@ static void *iothread_run(void *opaque)
102
return NULL;
36
}
103
}
37
104
38
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
105
+/* Runs in iothread_run() thread */
39
+ bool compress)
106
+static void iothread_stop_bh(void *opaque)
40
+{
107
+{
41
+ /* Keep BDRV_REQ_SERIALISING set (or not set) in block_copy_state_new() */
108
+ IOThread *iothread = opaque;
42
+ s->write_flags = (s->write_flags & BDRV_REQ_SERIALISING) |
43
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
44
+
109
+
45
+ if (s->max_transfer < s->cluster_size) {
110
+ iothread->running = false; /* stop iothread_run() */
46
+ /*
111
+
47
+ * copy_range does not respect max_transfer. We don't want to bother
112
+ if (iothread->main_loop) {
48
+ * with requests smaller than block-copy cluster size, so fallback to
113
+ g_main_loop_quit(iothread->main_loop);
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
+ }
114
+ }
63
+}
115
+}
64
+
116
+
65
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
117
void iothread_stop(IOThread *iothread)
66
int64_t cluster_size, bool use_copy_range,
118
{
67
bool compress, Error **errp)
119
if (!iothread->ctx || iothread->stopping) {
68
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
120
return;
69
.copy_bitmap = copy_bitmap,
121
}
70
.cluster_size = cluster_size,
122
iothread->stopping = true;
71
.len = bdrv_dirty_bitmap_size(copy_bitmap),
123
- aio_notify(iothread->ctx);
72
- .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0) |
124
- if (atomic_read(&iothread->main_loop)) {
73
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
125
- g_main_loop_quit(iothread->main_loop);
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
- }
126
- }
99
+ block_copy_set_copy_opts(s, use_copy_range, compress);
127
+ aio_bh_schedule_oneshot(iothread->ctx, iothread_stop_bh, iothread);
100
128
qemu_thread_join(&iothread->thread);
101
ratelimit_init(&s->rate_limit);
129
}
102
qemu_co_mutex_init(&s->lock);
130
131
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
132
char *name, *thread_name;
133
134
iothread->stopping = false;
135
+ iothread->running = true;
136
iothread->thread_id = -1;
137
iothread->ctx = aio_context_new(&local_error);
138
if (!iothread->ctx) {
103
--
139
--
104
2.31.1
140
2.14.3
105
141
106
142
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
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
One more step closer to real .bdrv_open() handler: use more usual names
4
for bs being initialized and its state.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-16-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
block/copy-before-write.c | 29 ++++++++++++++---------------
12
1 file changed, 14 insertions(+), 15 deletions(-)
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 @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
19
}
20
}
21
22
-static int cbw_init(BlockDriverState *top, BlockDriverState *source,
23
+static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
24
BlockDriverState *target, bool compress, Error **errp)
25
{
26
- BDRVCopyBeforeWriteState *state = top->opaque;
27
+ BDRVCopyBeforeWriteState *s = bs->opaque;
28
29
- top->total_sectors = source->total_sectors;
30
- top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
31
+ bs->total_sectors = source->total_sectors;
32
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
33
(BDRV_REQ_FUA & source->supported_write_flags);
34
- top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
35
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
36
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
37
source->supported_zero_flags);
38
39
bdrv_ref(target);
40
- state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
41
- BDRV_CHILD_DATA, errp);
42
- if (!state->target) {
43
+ s->target = bdrv_attach_child(bs, target, "target", &child_of_bds,
44
+ BDRV_CHILD_DATA, errp);
45
+ if (!s->target) {
46
error_prepend(errp, "Cannot attach target child: ");
47
return -EINVAL;
48
}
49
50
bdrv_ref(source);
51
- top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
52
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
53
- errp);
54
- if (!top->file) {
55
+ bs->file = bdrv_attach_child(bs, source, "file", &child_of_bds,
56
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
57
+ errp);
58
+ if (!bs->file) {
59
error_prepend(errp, "Cannot attach file child: ");
60
return -EINVAL;
61
}
62
63
- state->bcs = block_copy_state_new(top->file, state->target, false, compress,
64
- errp);
65
- if (!state->bcs) {
66
+ s->bcs = block_copy_state_new(bs->file, s->target, false, compress, errp);
67
+ if (!s->bcs) {
68
error_prepend(errp, "Cannot create block-copy-state: ");
69
return -EINVAL;
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
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
- 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
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
This test case will prevent future regressions with savevm and
2
IOThreads.
2
3
3
New fleecing method becomes available: copy-before-write filter.
4
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Message-id: 20171207201320.19284-7-stefanha@redhat.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
tests/qemu-iotests/203 | 59 ++++++++++++++++++++++++++++++++++++++++++++++
10
tests/qemu-iotests/203.out | 6 +++++
11
tests/qemu-iotests/group | 1 +
12
3 files changed, 66 insertions(+)
13
create mode 100755 tests/qemu-iotests/203
14
create mode 100644 tests/qemu-iotests/203.out
4
15
5
Actually we don't need backup job to setup image fleecing. Add test
16
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
6
for new recommended way of image fleecing.
17
new file mode 100755
7
18
index XXXXXXX..XXXXXXX
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
19
--- /dev/null
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
+++ b/tests/qemu-iotests/203
10
Message-Id: <20210824083856.17408-34-vsementsov@virtuozzo.com>
21
@@ -XXX,XX +XXX,XX @@
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
22
+#!/usr/bin/env python
12
---
23
+#
13
tests/qemu-iotests/tests/image-fleecing | 50 +++++++++-----
24
+# Copyright (C) 2017 Red Hat, Inc.
14
tests/qemu-iotests/tests/image-fleecing.out | 72 +++++++++++++++++++++
25
+#
15
2 files changed, 107 insertions(+), 15 deletions(-)
26
+# This program is free software; you can redistribute it and/or modify
16
27
+# it under the terms of the GNU General Public License as published by
17
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
28
+# the Free Software Foundation; either version 2 of the License, or
18
index XXXXXXX..XXXXXXX 100755
29
+# (at your option) any later version.
19
--- a/tests/qemu-iotests/tests/image-fleecing
30
+#
20
+++ b/tests/qemu-iotests/tests/image-fleecing
31
+# This program is distributed in the hope that it will be useful,
21
@@ -XXX,XX +XXX,XX @@ remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
32
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
('0xdc', '32M', '32k'), # Left-end of partial-right [2]
33
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
('0xcd', '0x3ff0000', '64k')] # patterns[3]
34
+# GNU General Public License for more details.
24
35
+#
25
-def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
36
+# You should have received a copy of the GNU General Public License
26
+def do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm):
37
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
27
log('--- Setting up images ---')
38
+#
28
log('')
39
+# Creator/Owner: Stefan Hajnoczi <stefanha@redhat.com>
29
40
+#
30
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
41
+# Check that QMP 'migrate' with multiple drives on a single IOThread completes
31
42
+# successfully. This particular command triggered a hang in the source QEMU
32
src_node = 'source'
43
+# process due to recursive AioContext locking in bdrv_invalidate_all() and
33
tmp_node = 'temp'
44
+# BDRV_POLL_WHILE().
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
+
45
+
57
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value='fl-cbw'))
46
+import iotests
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
+
47
+
93
log(vm.qmp('nbd-server-stop'))
48
+iotests.verify_image_format(supported_fmts=['qcow2'])
94
log(vm.qmp('blockdev-del', node_name=tmp_node))
49
+iotests.verify_platform(['linux'])
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
+
50
+
110
51
+with iotests.FilePath('disk0.img') as disk0_img_path, \
111
+log('=== Test backup(sync=none) based fleecing ===\n')
52
+ iotests.FilePath('disk1.img') as disk1_img_path, \
112
+test(False)
53
+ iotests.VM() as vm:
113
54
+
114
-test()
55
+ img_size = '10M'
115
+log('=== Test filter based fleecing ===\n')
56
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk0_img_path, img_size)
116
+test(True)
57
+ iotests.qemu_img_pipe('create', '-f', iotests.imgfmt, disk1_img_path, img_size)
117
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
58
+
59
+ iotests.log('Launching VM...')
60
+ (vm.add_object('iothread,id=iothread0')
61
+ .add_drive(disk0_img_path, 'node-name=drive0-node', interface='none')
62
+ .add_drive(disk1_img_path, 'node-name=drive1-node', interface='none')
63
+ .launch())
64
+
65
+ iotests.log('Setting IOThreads...')
66
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
67
+ node_name='drive0-node', iothread='iothread0',
68
+ force=True))
69
+ iotests.log(vm.qmp('x-blockdev-set-iothread',
70
+ node_name='drive1-node', iothread='iothread0',
71
+ force=True))
72
+
73
+ iotests.log('Starting migration...')
74
+ iotests.log(vm.qmp('migrate', uri='exec:cat >/dev/null'))
75
+ while True:
76
+ vm.get_qmp_event(wait=60.0)
77
+ result = vm.qmp('query-migrate')
78
+ status = result.get('return', {}).get('status', None)
79
+ if status == 'completed':
80
+ break
81
diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out
82
new file mode 100644
83
index XXXXXXX..XXXXXXX
84
--- /dev/null
85
+++ b/tests/qemu-iotests/203.out
86
@@ -XXX,XX +XXX,XX @@
87
+Launching VM...
88
+Setting IOThreads...
89
+{u'return': {}}
90
+{u'return': {}}
91
+Starting migration...
92
+{u'return': {}}
93
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
118
index XXXXXXX..XXXXXXX 100644
94
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qemu-iotests/tests/image-fleecing.out
95
--- a/tests/qemu-iotests/group
120
+++ b/tests/qemu-iotests/tests/image-fleecing.out
96
+++ b/tests/qemu-iotests/group
121
@@ -XXX,XX +XXX,XX @@
97
@@ -XXX,XX +XXX,XX @@
122
+=== Test backup(sync=none) based fleecing ===
98
198 rw auto
123
+
99
200 rw auto
124
--- Setting up images ---
100
202 rw auto quick
125
101
+203 rw auto
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
--
102
--
202
2.31.1
103
2.14.3
203
104
204
105
diff view generated by jsdifflib