1
The following changes since commit ec397e90d21269037280633b6058d1f280e27667:
1
The following changes since commit c1eb2ddf0f8075faddc5f7c3d39feae3e8e9d6b4:
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
Update version for v8.0.0 release (2023-04-19 17:27:13 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/XanClic/qemu.git tags/pull-block-2021-09-01
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to ebd979c74e2b8a7275090475df36dde4ab858320:
9
for you to fetch changes up to 36e5e9b22abe56aa00ca067851555ad8127a7966:
10
10
11
block/file-win32: add reopen handlers (2021-09-01 14:38:08 +0200)
11
tracing: install trace events file only if necessary (2023-04-20 07:39:43 -0400)
12
13
----------------------------------------------------------------
14
Pull request
15
16
Sam Li's zoned storage work and fixes I collected during the 8.0 freeze.
17
18
----------------------------------------------------------------
19
20
Carlos Santos (1):
21
tracing: install trace events file only if necessary
22
23
Philippe Mathieu-Daudé (1):
24
block/dmg: Declare a type definition for DMG uncompress function
25
26
Sam Li (17):
27
block/block-common: add zoned device structs
28
block/file-posix: introduce helper functions for sysfs attributes
29
block/block-backend: add block layer APIs resembling Linux
30
ZonedBlockDevice ioctls
31
block/raw-format: add zone operations to pass through requests
32
block: add zoned BlockDriver check to block layer
33
iotests: test new zone operations
34
block: add some trace events for new block layer APIs
35
docs/zoned-storage: add zoned device documentation
36
file-posix: add tracking of the zone write pointers
37
block: introduce zone append write for zoned devices
38
qemu-iotests: test zone append operation
39
block: add some trace events for zone append
40
include: update virtio_blk headers to v6.3-rc1
41
virtio-blk: add zoned storage emulation for zoned devices
42
block: add accounting for zone append operation
43
virtio-blk: add some trace events for zoned emulation
44
docs/zoned-storage:add zoned emulation use case
45
46
Thomas De Schampheleire (1):
47
tracetool: use relative paths for '#line' preprocessor directives
48
49
docs/devel/index-api.rst | 1 +
50
docs/devel/zoned-storage.rst | 62 ++
51
qapi/block-core.json | 68 +-
52
qapi/block.json | 4 +
53
meson.build | 4 +
54
block/dmg.h | 8 +-
55
include/block/accounting.h | 1 +
56
include/block/block-common.h | 57 ++
57
include/block/block-io.h | 13 +
58
include/block/block_int-common.h | 37 +
59
include/block/raw-aio.h | 8 +-
60
include/standard-headers/drm/drm_fourcc.h | 12 +
61
include/standard-headers/linux/ethtool.h | 48 +-
62
include/standard-headers/linux/fuse.h | 45 +-
63
include/standard-headers/linux/pci_regs.h | 1 +
64
include/standard-headers/linux/vhost_types.h | 2 +
65
include/standard-headers/linux/virtio_blk.h | 105 +++
66
include/sysemu/block-backend-io.h | 27 +
67
linux-headers/asm-arm64/kvm.h | 1 +
68
linux-headers/asm-x86/kvm.h | 34 +-
69
linux-headers/linux/kvm.h | 9 +
70
linux-headers/linux/vfio.h | 15 +-
71
linux-headers/linux/vhost.h | 8 +
72
block.c | 19 +
73
block/block-backend.c | 193 ++++++
74
block/dmg.c | 7 +-
75
block/file-posix.c | 677 +++++++++++++++++--
76
block/io.c | 68 ++
77
block/io_uring.c | 4 +
78
block/linux-aio.c | 3 +
79
block/qapi-sysemu.c | 11 +
80
block/qapi.c | 18 +
81
block/raw-format.c | 26 +
82
hw/block/virtio-blk-common.c | 2 +
83
hw/block/virtio-blk.c | 405 +++++++++++
84
hw/virtio/virtio-qmp.c | 2 +
85
qemu-io-cmds.c | 224 ++++++
86
block/trace-events | 4 +
87
docs/system/qemu-block-drivers.rst.inc | 6 +
88
hw/block/trace-events | 7 +
89
scripts/tracetool/backend/ftrace.py | 4 +-
90
scripts/tracetool/backend/log.py | 4 +-
91
scripts/tracetool/backend/syslog.py | 4 +-
92
tests/qemu-iotests/tests/zoned | 105 +++
93
tests/qemu-iotests/tests/zoned.out | 69 ++
94
trace/meson.build | 2 +-
95
46 files changed, 2353 insertions(+), 81 deletions(-)
96
create mode 100644 docs/devel/zoned-storage.rst
97
create mode 100755 tests/qemu-iotests/tests/zoned
98
create mode 100644 tests/qemu-iotests/tests/zoned.out
99
100
--
101
2.39.2
12
102
13
103
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
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
When using -valgrind on the script tests, it generates a log file
4
in $TEST_DIR that is either read (if valgrind finds problems) or
5
otherwise deleted. Provide the same exact behavior when using
6
-valgrind on the python tests.
7
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20210809090114.64834-13-eesposit@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 11 +++++++++++
15
1 file changed, 11 insertions(+)
16
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def __init__(self, path_suffix=''):
22
sock_dir=sock_dir, qmp_timer=timer)
23
self._num_drives = 0
24
25
+ def _post_shutdown(self) -> None:
26
+ super()._post_shutdown()
27
+ if not qemu_valgrind or not self._popen:
28
+ return
29
+ valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
30
+ if self.exitcode() == 99:
31
+ with open(valgrind_filename) as f:
32
+ print(f.read())
33
+ else:
34
+ os.remove(valgrind_filename)
35
+
36
def add_object(self, opts):
37
self._args.append('-object')
38
self._args.append(opts)
39
--
40
2.31.1
41
42
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
If -gdb and -valgrind are both defined, return an error.
4
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210809090114.64834-14-eesposit@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
tests/qemu-iotests/iotests.py | 6 +++++-
12
1 file changed, 5 insertions(+), 1 deletion(-)
13
14
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/qemu-iotests/iotests.py
17
+++ b/tests/qemu-iotests/iotests.py
18
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
19
def __init__(self, path_suffix=''):
20
name = "qemu%s-%d" % (path_suffix, os.getpid())
21
timer = 15.0 if not (qemu_gdb or qemu_valgrind) else None
22
- super().__init__(qemu_prog, qemu_opts, wrapper=qemu_gdb,
23
+ if qemu_gdb and qemu_valgrind:
24
+ sys.stderr.write('gdb and valgrind are mutually exclusive\n')
25
+ sys.exit(1)
26
+ wrapper = qemu_gdb if qemu_gdb else qemu_valgrind
27
+ super().__init__(qemu_prog, qemu_opts, wrapper=wrapper,
28
name=name,
29
base_temp_dir=test_dir,
30
socket_scm_helper=socket_scm_helper,
31
--
32
2.31.1
33
34
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Message-Id: <20210809090114.64834-15-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
docs/devel/testing.rst | 6 ++++++
10
1 file changed, 6 insertions(+)
11
12
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/testing.rst
15
+++ b/docs/devel/testing.rst
16
@@ -XXX,XX +XXX,XX @@ a failing test:
17
If the ``-gdb`` option is not used, ``$GDB_OPTIONS`` is ignored,
18
regardless of whether it is set or not.
19
20
+* ``-valgrind`` attaches a valgrind instance to QEMU. If it detects
21
+ warnings, it will print and save the log in
22
+ ``$TEST_DIR/<valgrind_pid>.valgrind``.
23
+ The final command line will be ``valgrind --log-file=$TEST_DIR/
24
+ <valgrind_pid>.valgrind --error-exitcode=99 $QEMU ...``
25
+
26
* ``-d`` (debug) just increases the logging verbosity, showing
27
for example the QMP commands and answers.
28
29
--
30
2.31.1
31
32
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Using the flag -p, allow the qemu binary to print to stdout.
4
5
Also create the common function _close_qemu_log_file() to
6
avoid accessing machine.py private fields directly and have
7
duplicate code.
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20210809090114.64834-16-eesposit@redhat.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
15
python/qemu/machine/machine.py | 9 ++++++---
16
tests/qemu-iotests/check | 4 +++-
17
tests/qemu-iotests/iotests.py | 8 ++++++++
18
tests/qemu-iotests/testenv.py | 9 +++++++--
19
4 files changed, 24 insertions(+), 6 deletions(-)
20
21
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
22
index XXXXXXX..XXXXXXX 100644
23
--- a/python/qemu/machine/machine.py
24
+++ b/python/qemu/machine/machine.py
25
@@ -XXX,XX +XXX,XX @@ def _post_launch(self) -> None:
26
if self._qmp_connection:
27
self._qmp.accept(self._qmp_timer)
28
29
+ def _close_qemu_log_file(self) -> None:
30
+ if self._qemu_log_file is not None:
31
+ self._qemu_log_file.close()
32
+ self._qemu_log_file = None
33
+
34
def _post_shutdown(self) -> None:
35
"""
36
Called to cleanup the VM instance after the process has exited.
37
@@ -XXX,XX +XXX,XX @@ def _post_shutdown(self) -> None:
38
self._qmp.close()
39
self._qmp_connection = None
40
41
- if self._qemu_log_file is not None:
42
- self._qemu_log_file.close()
43
- self._qemu_log_file = None
44
+ self._close_qemu_log_file()
45
46
self._load_io_log()
47
48
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
49
index XXXXXXX..XXXXXXX 100755
50
--- a/tests/qemu-iotests/check
51
+++ b/tests/qemu-iotests/check
52
@@ -XXX,XX +XXX,XX @@ def make_argparser() -> argparse.ArgumentParser:
53
help='pretty print output for make check')
54
55
p.add_argument('-d', dest='debug', action='store_true', help='debug')
56
+ p.add_argument('-p', dest='print', action='store_true',
57
+ help='redirects qemu\'s stdout and stderr to the test output')
58
p.add_argument('-gdb', action='store_true',
59
help="start gdbserver with $GDB_OPTIONS options \
60
('localhost:12345' if $GDB_OPTIONS is empty)")
61
@@ -XXX,XX +XXX,XX @@ if __name__ == '__main__':
62
aiomode=args.aiomode, cachemode=args.cachemode,
63
imgopts=args.imgopts, misalign=args.misalign,
64
debug=args.debug, valgrind=args.valgrind,
65
- gdb=args.gdb)
66
+ gdb=args.gdb, qprint=args.print)
67
68
if len(sys.argv) > 1 and sys.argv[-len(args.tests)-1] == '--':
69
if not args.tests:
70
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tests/qemu-iotests/iotests.py
73
+++ b/tests/qemu-iotests/iotests.py
74
@@ -XXX,XX +XXX,XX @@
75
if gdb_qemu_env:
76
qemu_gdb = ['gdbserver'] + gdb_qemu_env.strip().split(' ')
77
78
+qemu_print = os.environ.get('PRINT_QEMU', False)
79
+
80
imgfmt = os.environ.get('IMGFMT', 'raw')
81
imgproto = os.environ.get('IMGPROTO', 'file')
82
output_dir = os.environ.get('OUTPUT_DIR', '.')
83
@@ -XXX,XX +XXX,XX @@ def _post_shutdown(self) -> None:
84
else:
85
os.remove(valgrind_filename)
86
87
+ def _pre_launch(self) -> None:
88
+ super()._pre_launch()
89
+ if qemu_print:
90
+ # set QEMU binary output to stdout
91
+ self._close_qemu_log_file()
92
+
93
def add_object(self, opts):
94
self._args.append('-object')
95
self._args.append(opts)
96
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
97
index XXXXXXX..XXXXXXX 100644
98
--- a/tests/qemu-iotests/testenv.py
99
+++ b/tests/qemu-iotests/testenv.py
100
@@ -XXX,XX +XXX,XX @@ class TestEnv(ContextManager['TestEnv']):
101
'AIOMODE', 'CACHEMODE', 'VALGRIND_QEMU',
102
'CACHEMODE_IS_DEFAULT', 'IMGFMT_GENERIC', 'IMGOPTSSYNTAX',
103
'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_',
104
- 'GDB_OPTIONS']
105
+ 'GDB_OPTIONS', 'PRINT_QEMU']
106
107
def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
108
if self.debug:
109
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
110
misalign: bool = False,
111
debug: bool = False,
112
valgrind: bool = False,
113
- gdb: bool = False) -> None:
114
+ gdb: bool = False,
115
+ qprint: bool = False) -> None:
116
self.imgfmt = imgfmt
117
self.imgproto = imgproto
118
self.aiomode = aiomode
119
@@ -XXX,XX +XXX,XX @@ def __init__(self, imgfmt: str, imgproto: str, aiomode: str,
120
self.misalign = misalign
121
self.debug = debug
122
123
+ if qprint:
124
+ self.print_qemu = 'y'
125
+
126
if gdb:
127
self.gdb_options = os.getenv('GDB_OPTIONS', DEF_GDB_OPTIONS)
128
if not self.gdb_options:
129
@@ -XXX,XX +XXX,XX @@ def print_env(self) -> None:
130
SOCKET_SCM_HELPER -- {SOCKET_SCM_HELPER}
131
GDB_OPTIONS -- {GDB_OPTIONS}
132
VALGRIND_QEMU -- {VALGRIND_QEMU}
133
+PRINT_QEMU_OUTPUT -- {PRINT_QEMU}
134
"""
135
136
args = collections.defaultdict(str, self.get_env())
137
--
138
2.31.1
139
140
diff view generated by jsdifflib
Deleted patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
1
3
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Message-Id: <20210809090114.64834-17-eesposit@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
---
9
docs/devel/testing.rst | 4 ++++
10
1 file changed, 4 insertions(+)
11
12
diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
13
index XXXXXXX..XXXXXXX 100644
14
--- a/docs/devel/testing.rst
15
+++ b/docs/devel/testing.rst
16
@@ -XXX,XX +XXX,XX @@ a failing test:
17
* ``-d`` (debug) just increases the logging verbosity, showing
18
for example the QMP commands and answers.
19
20
+* ``-p`` (print) redirects QEMU’s stdout and stderr to the test output,
21
+ instead of saving it into a log file in
22
+ ``$TEST_DIR/qemu-machine-<random_string>``.
23
+
24
Test case groups
25
----------------
26
27
--
28
2.31.1
29
30
diff view generated by jsdifflib
Deleted patch
1
From: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
2
1
3
Signed-off-by: Mao Zhongyi <maozhongyi@cmss.chinamobile.com>
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
12
--- a/block/monitor/block-hmp-cmds.c
13
+++ b/block/monitor/block-hmp-cmds.c
14
@@ -XXX,XX +XXX,XX @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
15
16
if (!filename) {
17
error_setg(&err, QERR_MISSING_PARAMETER, "target");
18
- hmp_handle_error(mon, err);
19
- return;
20
+ goto end;
21
}
22
qmp_drive_mirror(&mirror, &err);
23
+end:
24
hmp_handle_error(mon, err);
25
}
26
27
@@ -XXX,XX +XXX,XX @@ void hmp_drive_backup(Monitor *mon, const QDict *qdict)
28
29
if (!filename) {
30
error_setg(&err, QERR_MISSING_PARAMETER, "target");
31
- hmp_handle_error(mon, err);
32
- return;
33
+ goto end;
34
}
35
36
qmp_drive_backup(&backup, &err);
37
+end:
38
hmp_handle_error(mon, err);
39
}
40
41
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
42
* will be taken internally. Today it's actually required.
43
*/
44
error_setg(&err, QERR_MISSING_PARAMETER, "snapshot-file");
45
- hmp_handle_error(mon, err);
46
- return;
47
+ goto end;
48
}
49
50
mode = reuse ? NEW_IMAGE_MODE_EXISTING : NEW_IMAGE_MODE_ABSOLUTE_PATHS;
51
@@ -XXX,XX +XXX,XX @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
52
filename, false, NULL,
53
!!format, format,
54
true, mode, &err);
55
+end:
56
hmp_handle_error(mon, err);
57
}
58
59
--
60
2.31.1
61
62
diff view generated by jsdifflib
1
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Include linux/fs.h to avoid the following build failure on uclibc or
3
Signed-off-by: Sam Li <faithilikerun@gmail.com>
4
musl raised since version 6.0.0:
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
6
Reviewed-by: Hannes Reinecke <hare@suse.de>
7
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
8
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
Message-id: 20230324090605.28361-2-faithilikerun@gmail.com
10
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
11
<philmd@linaro.org>.
12
--Stefan]
13
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
14
---
15
include/block/block-common.h | 43 ++++++++++++++++++++++++++++++++++++
16
1 file changed, 43 insertions(+)
5
17
6
../block/export/fuse.c: In function 'fuse_lseek':
18
diff --git a/include/block/block-common.h b/include/block/block-common.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
19
index XXXXXXX..XXXXXXX 100644
28
--- a/block/export/fuse.c
20
--- a/include/block/block-common.h
29
+++ b/block/export/fuse.c
21
+++ b/include/block/block-common.h
30
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDriver BlockDriver;
31
#include <fuse.h>
23
typedef struct BdrvChild BdrvChild;
32
#include <fuse_lowlevel.h>
24
typedef struct BdrvChildClass BdrvChildClass;
33
25
34
+#ifdef __linux__
26
+typedef enum BlockZoneOp {
35
+#include <linux/fs.h>
27
+ BLK_ZO_OPEN,
36
+#endif
28
+ BLK_ZO_CLOSE,
37
29
+ BLK_ZO_FINISH,
38
/* Prevent overly long bounce buffer allocations */
30
+ BLK_ZO_RESET,
39
#define FUSE_MAX_BOUNCE_BYTES (MIN(BDRV_REQUEST_MAX_BYTES, 64 * 1024 * 1024))
31
+} BlockZoneOp;
32
+
33
+typedef enum BlockZoneModel {
34
+ BLK_Z_NONE = 0x0, /* Regular block device */
35
+ BLK_Z_HM = 0x1, /* Host-managed zoned block device */
36
+ BLK_Z_HA = 0x2, /* Host-aware zoned block device */
37
+} BlockZoneModel;
38
+
39
+typedef enum BlockZoneState {
40
+ BLK_ZS_NOT_WP = 0x0,
41
+ BLK_ZS_EMPTY = 0x1,
42
+ BLK_ZS_IOPEN = 0x2,
43
+ BLK_ZS_EOPEN = 0x3,
44
+ BLK_ZS_CLOSED = 0x4,
45
+ BLK_ZS_RDONLY = 0xD,
46
+ BLK_ZS_FULL = 0xE,
47
+ BLK_ZS_OFFLINE = 0xF,
48
+} BlockZoneState;
49
+
50
+typedef enum BlockZoneType {
51
+ BLK_ZT_CONV = 0x1, /* Conventional random writes supported */
52
+ BLK_ZT_SWR = 0x2, /* Sequential writes required */
53
+ BLK_ZT_SWP = 0x3, /* Sequential writes preferred */
54
+} BlockZoneType;
55
+
56
+/*
57
+ * Zone descriptor data structure.
58
+ * Provides information on a zone with all position and size values in bytes.
59
+ */
60
+typedef struct BlockZoneDescriptor {
61
+ uint64_t start;
62
+ uint64_t length;
63
+ uint64_t cap;
64
+ uint64_t wp;
65
+ BlockZoneType type;
66
+ BlockZoneState state;
67
+} BlockZoneDescriptor;
68
+
69
typedef struct BlockDriverInfo {
70
/* in bytes, 0 if irrelevant */
71
int cluster_size;
40
--
72
--
41
2.31.1
73
2.39.2
42
74
43
75
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Move part of bdrv_cbw_append() to new function cbw_open(). It's an
3
Use get_sysfs_str_val() to get the string value of device
4
intermediate step for adding normal .bdrv_open() handler to the
4
zoned model. Then get_sysfs_zoned_model() can convert it to
5
filter. With this commit no logic is changed, but we have a function
5
BlockZoneModel type of QEMU.
6
which will be turned into .bdrv_open() handler in future commit.
6
7
7
Use get_sysfs_long_val() to get the long value of zoned device
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
information.
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
10
Message-Id: <20210824083856.17408-15-vsementsov@virtuozzo.com>
10
Signed-off-by: Sam Li <faithilikerun@gmail.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Reviewed-by: Hannes Reinecke <hare@suse.de>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
14
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
15
Acked-by: Kevin Wolf <kwolf@redhat.com>
16
Message-id: 20230324090605.28361-3-faithilikerun@gmail.com
17
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
18
<philmd@linaro.org>.
19
--Stefan]
20
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
21
---
13
block/copy-before-write.c | 69 +++++++++++++++++++++++----------------
22
include/block/block_int-common.h | 3 +
14
1 file changed, 41 insertions(+), 28 deletions(-)
23
block/file-posix.c | 130 ++++++++++++++++++++++---------
15
24
2 files changed, 95 insertions(+), 38 deletions(-)
16
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
25
26
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
17
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
18
--- a/block/copy-before-write.c
28
--- a/include/block/block_int-common.h
19
+++ b/block/copy-before-write.c
29
+++ b/include/block/block_int-common.h
20
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
30
@@ -XXX,XX +XXX,XX @@ typedef struct BlockLimits {
21
}
31
* an explicit monitor command to load the disk inside the guest).
32
*/
33
bool has_variable_length;
34
+
35
+ /* device zone model */
36
+ BlockZoneModel zoned;
37
} BlockLimits;
38
39
typedef struct BdrvOpBlocker BdrvOpBlocker;
40
diff --git a/block/file-posix.c b/block/file-posix.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/file-posix.c
43
+++ b/block/file-posix.c
44
@@ -XXX,XX +XXX,XX @@ static int hdev_get_max_hw_transfer(int fd, struct stat *st)
45
#endif
22
}
46
}
23
47
24
+static int cbw_init(BlockDriverState *top, BlockDriverState *source,
48
-static int hdev_get_max_segments(int fd, struct stat *st)
25
+ BlockDriverState *target, bool compress, Error **errp)
49
+/*
50
+ * Get a sysfs attribute value as character string.
51
+ */
52
+static int get_sysfs_str_val(struct stat *st, const char *attribute,
53
+ char **val) {
54
+#ifdef CONFIG_LINUX
55
+ g_autofree char *sysfspath = NULL;
56
+ int ret;
57
+ size_t len;
58
+
59
+ if (!S_ISBLK(st->st_mode)) {
60
+ return -ENOTSUP;
61
+ }
62
+
63
+ sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/%s",
64
+ major(st->st_rdev), minor(st->st_rdev),
65
+ attribute);
66
+ ret = g_file_get_contents(sysfspath, val, &len, NULL);
67
+ if (ret == -1) {
68
+ return -ENOENT;
69
+ }
70
+
71
+ /* The file is ended with '\n' */
72
+ char *p;
73
+ p = *val;
74
+ if (*(p + len - 1) == '\n') {
75
+ *(p + len - 1) = '\0';
76
+ }
77
+ return ret;
78
+#else
79
+ return -ENOTSUP;
80
+#endif
81
+}
82
+
83
+static int get_sysfs_zoned_model(struct stat *st, BlockZoneModel *zoned)
26
+{
84
+{
27
+ BDRVCopyBeforeWriteState *state = top->opaque;
85
+ g_autofree char *val = NULL;
28
+
86
+ int ret;
29
+ top->total_sectors = source->total_sectors;
87
+
30
+ top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
88
+ ret = get_sysfs_str_val(st, "zoned", &val);
31
+ (BDRV_REQ_FUA & source->supported_write_flags);
89
+ if (ret < 0) {
32
+ top->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
90
+ return ret;
33
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
91
+ }
34
+ source->supported_zero_flags);
92
+
35
+
93
+ if (strcmp(val, "host-managed") == 0) {
36
+ bdrv_ref(target);
94
+ *zoned = BLK_Z_HM;
37
+ state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
95
+ } else if (strcmp(val, "host-aware") == 0) {
38
+ BDRV_CHILD_DATA, errp);
96
+ *zoned = BLK_Z_HA;
39
+ if (!state->target) {
97
+ } else if (strcmp(val, "none") == 0) {
40
+ error_prepend(errp, "Cannot attach target child: ");
98
+ *zoned = BLK_Z_NONE;
41
+ return -EINVAL;
99
+ } else {
42
+ }
100
+ return -ENOTSUP;
43
+
101
+ }
44
+ bdrv_ref(source);
45
+ top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
46
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
47
+ errp);
48
+ if (!top->file) {
49
+ error_prepend(errp, "Cannot attach file child: ");
50
+ return -EINVAL;
51
+ }
52
+
53
+ state->bcs = block_copy_state_new(top->file, state->target, false, compress,
54
+ errp);
55
+ if (!state->bcs) {
56
+ error_prepend(errp, "Cannot create block-copy-state: ");
57
+ return -EINVAL;
58
+ }
59
+
60
+ return 0;
102
+ return 0;
61
+}
103
+}
62
+
104
+
63
BlockDriver bdrv_cbw_filter = {
105
+/*
64
.format_name = "copy-before-write",
106
+ * Get a sysfs attribute value as a long integer.
65
.instance_size = sizeof(BDRVCopyBeforeWriteState),
107
+ */
66
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
108
+static long get_sysfs_long_val(struct stat *st, const char *attribute)
67
error_prepend(errp, "Cannot open driver: ");
109
{
68
return NULL;
110
#ifdef CONFIG_LINUX
111
- char buf[32];
112
+ g_autofree char *str = NULL;
113
const char *end;
114
- char *sysfspath = NULL;
115
+ long val;
116
+ int ret;
117
+
118
+ ret = get_sysfs_str_val(st, attribute, &str);
119
+ if (ret < 0) {
120
+ return ret;
121
+ }
122
+
123
+ /* The file is ended with '\n', pass 'end' to accept that. */
124
+ ret = qemu_strtol(str, &end, 10, &val);
125
+ if (ret == 0 && end && *end == '\0') {
126
+ ret = val;
127
+ }
128
+ return ret;
129
+#else
130
+ return -ENOTSUP;
131
+#endif
132
+}
133
+
134
+static int hdev_get_max_segments(int fd, struct stat *st)
135
+{
136
+#ifdef CONFIG_LINUX
137
int ret;
138
- int sysfd = -1;
139
- long max_segments;
140
141
if (S_ISCHR(st->st_mode)) {
142
if (ioctl(fd, SG_GET_SG_TABLESIZE, &ret) == 0) {
143
@@ -XXX,XX +XXX,XX @@ static int hdev_get_max_segments(int fd, struct stat *st)
144
}
145
return -ENOTSUP;
69
}
146
}
70
-
147
-
71
state = top->opaque;
148
- if (!S_ISBLK(st->st_mode)) {
72
- top->total_sectors = source->total_sectors;
149
- return -ENOTSUP;
73
- top->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
150
- }
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
-
151
-
79
- bdrv_ref(target);
152
- sysfspath = g_strdup_printf("/sys/dev/block/%u:%u/queue/max_segments",
80
- state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
153
- major(st->st_rdev), minor(st->st_rdev));
81
- BDRV_CHILD_DATA, errp);
154
- sysfd = open(sysfspath, O_RDONLY);
82
- if (!state->target) {
155
- if (sysfd == -1) {
83
- error_prepend(errp, "Cannot attach target child: ");
156
- ret = -errno;
84
- goto fail;
157
- goto out;
85
- }
158
- }
86
159
- ret = RETRY_ON_EINTR(read(sysfd, buf, sizeof(buf) - 1));
87
- bdrv_ref(source);
160
- if (ret < 0) {
88
- top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
161
- ret = -errno;
89
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
162
- goto out;
90
- errp);
163
- } else if (ret == 0) {
91
- if (!top->file) {
164
- ret = -EIO;
92
- error_prepend(errp, "Cannot attach file child: ");
165
- goto out;
93
- goto fail;
166
- }
167
- buf[ret] = 0;
168
- /* The file is ended with '\n', pass 'end' to accept that. */
169
- ret = qemu_strtol(buf, &end, 10, &max_segments);
170
- if (ret == 0 && end && *end == '\n') {
171
- ret = max_segments;
94
- }
172
- }
95
-
173
-
96
- state->bcs = block_copy_state_new(top->file, state->target, false, compress,
174
-out:
97
- errp);
175
- if (sysfd != -1) {
98
- if (!state->bcs) {
176
- close(sysfd);
99
- error_prepend(errp, "Cannot create block-copy-state: ");
177
- }
100
+ ret = cbw_init(top, source, target, compress, errp);
178
- g_free(sysfspath);
179
- return ret;
180
+ return get_sysfs_long_val(st, "max_segments");
181
#else
182
return -ENOTSUP;
183
#endif
184
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
185
{
186
BDRVRawState *s = bs->opaque;
187
struct stat st;
188
+ int ret;
189
+ BlockZoneModel zoned;
190
191
s->needs_alignment = raw_needs_alignment(bs);
192
raw_probe_alignment(bs, s->fd, errp);
193
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
194
bs->bl.max_hw_iov = ret;
195
}
196
}
197
+
198
+ ret = get_sysfs_zoned_model(&st, &zoned);
101
+ if (ret < 0) {
199
+ if (ret < 0) {
102
goto fail;
200
+ zoned = BLK_Z_NONE;
103
}
201
+ }
104
202
+ bs->bl.zoned = zoned;
203
}
204
205
static int check_for_dasd(int fd)
105
--
206
--
106
2.31.1
207
2.39.2
107
208
108
209
diff view generated by jsdifflib
1
From: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Make 'qemu-img commit' work on Windows.
3
Add zoned device option to host_device BlockDriver. It will be presented only
4
for zoned host block devices. By adding zone management operations to the
5
host_block_device BlockDriver, users can use the new block layer APIs
6
including Report Zone and four zone management operations
7
(open, close, finish, reset, reset_all).
4
8
5
Command 'commit' requires reopening backing file in RW mode. So,
9
Qemu-io uses the new APIs to perform zoned storage commands of the device:
6
add reopen prepare/commit/abort handlers and change dwShareMode
10
zone_report(zrp), zone_open(zo), zone_close(zc), zone_reset(zrs),
7
for CreateFile call in order to allow further read/write reopening.
11
zone_finish(zf).
8
12
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/418
13
For example, to test zone_report, use following command:
14
$ ./build/qemu-io --image-opts -n driver=host_device, filename=/dev/nullb0
15
-c "zrp offset nr_zones"
10
16
11
Suggested-by: Hanna Reitz <hreitz@redhat.com>
17
Signed-off-by: Sam Li <faithilikerun@gmail.com>
12
Signed-off-by: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
18
Reviewed-by: Hannes Reinecke <hare@suse.de>
13
Tested-by: Helge Konetzka <hk@zapateado.de>
19
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
14
Message-Id: <20210825173625.19415-1-viktor.prutyanov@phystech.edu>
20
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
21
Acked-by: Kevin Wolf <kwolf@redhat.com>
22
Message-id: 20230324090605.28361-4-faithilikerun@gmail.com
23
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
24
<philmd@linaro.org> and remove spurious ret = -errno in
25
raw_co_zone_mgmt().
26
--Stefan]
27
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
28
---
17
block/file-win32.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
29
meson.build | 4 +
18
1 file changed, 100 insertions(+), 1 deletion(-)
30
include/block/block-io.h | 9 +
31
include/block/block_int-common.h | 21 ++
32
include/block/raw-aio.h | 6 +-
33
include/sysemu/block-backend-io.h | 18 ++
34
block/block-backend.c | 133 +++++++++++++
35
block/file-posix.c | 306 +++++++++++++++++++++++++++++-
36
block/io.c | 41 ++++
37
qemu-io-cmds.c | 149 +++++++++++++++
38
9 files changed, 684 insertions(+), 3 deletions(-)
19
39
20
diff --git a/block/file-win32.c b/block/file-win32.c
40
diff --git a/meson.build b/meson.build
21
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
22
--- a/block/file-win32.c
42
--- a/meson.build
23
+++ b/block/file-win32.c
43
+++ b/meson.build
24
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
44
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed())
25
QEMUWin32AIOState *aio;
45
# has_header
26
} BDRVRawState;
46
config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h'))
27
47
config_host_data.set('CONFIG_LINUX_MAGIC_H', cc.has_header('linux/magic.h'))
28
+typedef struct BDRVRawReopenState {
48
+config_host_data.set('CONFIG_BLKZONED', cc.has_header('linux/blkzoned.h'))
29
+ HANDLE hfile;
49
config_host_data.set('CONFIG_VALGRIND_H', cc.has_header('valgrind/valgrind.h'))
30
+} BDRVRawReopenState;
50
config_host_data.set('HAVE_BTRFS_H', cc.has_header('linux/btrfs.h'))
31
+
51
config_host_data.set('HAVE_DRM_H', cc.has_header('libdrm/drm.h'))
32
/*
52
@@ -XXX,XX +XXX,XX @@ config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
33
* Read/writes the data to/from a given linear buffer.
53
config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
34
*
54
cc.has_member('struct stat', 'st_atim',
35
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
55
prefix: '#include <sys/stat.h>'))
56
+config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
57
+ cc.has_member('struct blk_zone', 'capacity',
58
+ prefix: '#include <linux/blkzoned.h>'))
59
60
# has_type
61
config_host_data.set('CONFIG_IOVEC',
62
diff --git a/include/block/block-io.h b/include/block/block-io.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/block/block-io.h
65
+++ b/include/block/block-io.h
66
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_flush(BlockDriverState *bs);
67
int coroutine_fn GRAPH_RDLOCK bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
68
int64_t bytes);
69
70
+/* Report zone information of zone block device. */
71
+int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_report(BlockDriverState *bs,
72
+ int64_t offset,
73
+ unsigned int *nr_zones,
74
+ BlockZoneDescriptor *zones);
75
+int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_mgmt(BlockDriverState *bs,
76
+ BlockZoneOp op,
77
+ int64_t offset, int64_t len);
78
+
79
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
80
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
81
int64_t bytes, int64_t *pnum, int64_t *map,
82
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
83
index XXXXXXX..XXXXXXX 100644
84
--- a/include/block/block_int-common.h
85
+++ b/include/block/block_int-common.h
86
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
87
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_load_vmstate)(
88
BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
89
90
+ int coroutine_fn (*bdrv_co_zone_report)(BlockDriverState *bs,
91
+ int64_t offset, unsigned int *nr_zones,
92
+ BlockZoneDescriptor *zones);
93
+ int coroutine_fn (*bdrv_co_zone_mgmt)(BlockDriverState *bs, BlockZoneOp op,
94
+ int64_t offset, int64_t len);
95
+
96
/* removable device specific */
97
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
98
BlockDriverState *bs);
99
@@ -XXX,XX +XXX,XX @@ typedef struct BlockLimits {
100
101
/* device zone model */
102
BlockZoneModel zoned;
103
+
104
+ /* zone size expressed in bytes */
105
+ uint32_t zone_size;
106
+
107
+ /* total number of zones */
108
+ uint32_t nr_zones;
109
+
110
+ /* maximum sectors of a zone append write operation */
111
+ int64_t max_append_sectors;
112
+
113
+ /* maximum number of open zones */
114
+ int64_t max_open_zones;
115
+
116
+ /* maximum number of active zones */
117
+ int64_t max_active_zones;
118
} BlockLimits;
119
120
typedef struct BdrvOpBlocker BdrvOpBlocker;
121
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
122
index XXXXXXX..XXXXXXX 100644
123
--- a/include/block/raw-aio.h
124
+++ b/include/block/raw-aio.h
125
@@ -XXX,XX +XXX,XX @@
126
#define QEMU_AIO_WRITE_ZEROES 0x0020
127
#define QEMU_AIO_COPY_RANGE 0x0040
128
#define QEMU_AIO_TRUNCATE 0x0080
129
+#define QEMU_AIO_ZONE_REPORT 0x0100
130
+#define QEMU_AIO_ZONE_MGMT 0x0200
131
#define QEMU_AIO_TYPE_MASK \
132
(QEMU_AIO_READ | \
133
QEMU_AIO_WRITE | \
134
@@ -XXX,XX +XXX,XX @@
135
QEMU_AIO_DISCARD | \
136
QEMU_AIO_WRITE_ZEROES | \
137
QEMU_AIO_COPY_RANGE | \
138
- QEMU_AIO_TRUNCATE)
139
+ QEMU_AIO_TRUNCATE | \
140
+ QEMU_AIO_ZONE_REPORT | \
141
+ QEMU_AIO_ZONE_MGMT)
142
143
/* AIO flags */
144
#define QEMU_AIO_MISALIGNED 0x1000
145
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
146
index XXXXXXX..XXXXXXX 100644
147
--- a/include/sysemu/block-backend-io.h
148
+++ b/include/sysemu/block-backend-io.h
149
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwritev(BlockBackend *blk, int64_t offset,
150
BlockCompletionFunc *cb, void *opaque);
151
BlockAIOCB *blk_aio_flush(BlockBackend *blk,
152
BlockCompletionFunc *cb, void *opaque);
153
+BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset,
154
+ unsigned int *nr_zones,
155
+ BlockZoneDescriptor *zones,
156
+ BlockCompletionFunc *cb, void *opaque);
157
+BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
158
+ int64_t offset, int64_t len,
159
+ BlockCompletionFunc *cb, void *opaque);
160
BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes,
161
BlockCompletionFunc *cb, void *opaque);
162
void blk_aio_cancel_async(BlockAIOCB *acb);
163
@@ -XXX,XX +XXX,XX @@ int co_wrapper_mixed blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
164
int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
165
int64_t bytes, BdrvRequestFlags flags);
166
167
+int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
168
+ unsigned int *nr_zones,
169
+ BlockZoneDescriptor *zones);
170
+int co_wrapper_mixed blk_zone_report(BlockBackend *blk, int64_t offset,
171
+ unsigned int *nr_zones,
172
+ BlockZoneDescriptor *zones);
173
+int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
174
+ int64_t offset, int64_t len);
175
+int co_wrapper_mixed blk_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
176
+ int64_t offset, int64_t len);
177
+
178
int co_wrapper_mixed blk_pdiscard(BlockBackend *blk, int64_t offset,
179
int64_t bytes);
180
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
181
diff --git a/block/block-backend.c b/block/block-backend.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/block/block-backend.c
184
+++ b/block/block-backend.c
185
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_flush(BlockBackend *blk)
186
return ret;
187
}
188
189
+static void coroutine_fn blk_aio_zone_report_entry(void *opaque)
190
+{
191
+ BlkAioEmAIOCB *acb = opaque;
192
+ BlkRwCo *rwco = &acb->rwco;
193
+
194
+ rwco->ret = blk_co_zone_report(rwco->blk, rwco->offset,
195
+ (unsigned int*)acb->bytes,rwco->iobuf);
196
+ blk_aio_complete(acb);
197
+}
198
+
199
+BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset,
200
+ unsigned int *nr_zones,
201
+ BlockZoneDescriptor *zones,
202
+ BlockCompletionFunc *cb, void *opaque)
203
+{
204
+ BlkAioEmAIOCB *acb;
205
+ Coroutine *co;
206
+ IO_CODE();
207
+
208
+ blk_inc_in_flight(blk);
209
+ acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
210
+ acb->rwco = (BlkRwCo) {
211
+ .blk = blk,
212
+ .offset = offset,
213
+ .iobuf = zones,
214
+ .ret = NOT_DONE,
215
+ };
216
+ acb->bytes = (int64_t)nr_zones,
217
+ acb->has_returned = false;
218
+
219
+ co = qemu_coroutine_create(blk_aio_zone_report_entry, acb);
220
+ aio_co_enter(blk_get_aio_context(blk), co);
221
+
222
+ acb->has_returned = true;
223
+ if (acb->rwco.ret != NOT_DONE) {
224
+ replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
225
+ blk_aio_complete_bh, acb);
226
+ }
227
+
228
+ return &acb->common;
229
+}
230
+
231
+static void coroutine_fn blk_aio_zone_mgmt_entry(void *opaque)
232
+{
233
+ BlkAioEmAIOCB *acb = opaque;
234
+ BlkRwCo *rwco = &acb->rwco;
235
+
236
+ rwco->ret = blk_co_zone_mgmt(rwco->blk, (BlockZoneOp)rwco->iobuf,
237
+ rwco->offset, acb->bytes);
238
+ blk_aio_complete(acb);
239
+}
240
+
241
+BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
242
+ int64_t offset, int64_t len,
243
+ BlockCompletionFunc *cb, void *opaque) {
244
+ BlkAioEmAIOCB *acb;
245
+ Coroutine *co;
246
+ IO_CODE();
247
+
248
+ blk_inc_in_flight(blk);
249
+ acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
250
+ acb->rwco = (BlkRwCo) {
251
+ .blk = blk,
252
+ .offset = offset,
253
+ .iobuf = (void *)op,
254
+ .ret = NOT_DONE,
255
+ };
256
+ acb->bytes = len;
257
+ acb->has_returned = false;
258
+
259
+ co = qemu_coroutine_create(blk_aio_zone_mgmt_entry, acb);
260
+ aio_co_enter(blk_get_aio_context(blk), co);
261
+
262
+ acb->has_returned = true;
263
+ if (acb->rwco.ret != NOT_DONE) {
264
+ replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
265
+ blk_aio_complete_bh, acb);
266
+ }
267
+
268
+ return &acb->common;
269
+}
270
+
271
+/*
272
+ * Send a zone_report command.
273
+ * offset is a byte offset from the start of the device. No alignment
274
+ * required for offset.
275
+ * nr_zones represents IN maximum and OUT actual.
276
+ */
277
+int coroutine_fn blk_co_zone_report(BlockBackend *blk, int64_t offset,
278
+ unsigned int *nr_zones,
279
+ BlockZoneDescriptor *zones)
280
+{
281
+ int ret;
282
+ IO_CODE();
283
+
284
+ blk_inc_in_flight(blk); /* increase before waiting */
285
+ blk_wait_while_drained(blk);
286
+ if (!blk_is_available(blk)) {
287
+ blk_dec_in_flight(blk);
288
+ return -ENOMEDIUM;
289
+ }
290
+ ret = bdrv_co_zone_report(blk_bs(blk), offset, nr_zones, zones);
291
+ blk_dec_in_flight(blk);
292
+ return ret;
293
+}
294
+
295
+/*
296
+ * Send a zone_management command.
297
+ * op is the zone operation;
298
+ * offset is the byte offset from the start of the zoned device;
299
+ * len is the maximum number of bytes the command should operate on. It
300
+ * should be aligned with the device zone size.
301
+ */
302
+int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
303
+ int64_t offset, int64_t len)
304
+{
305
+ int ret;
306
+ IO_CODE();
307
+
308
+ blk_inc_in_flight(blk);
309
+ blk_wait_while_drained(blk);
310
+
311
+ ret = blk_check_byte_request(blk, offset, len);
312
+ if (ret < 0) {
313
+ blk_dec_in_flight(blk);
314
+ return ret;
315
+ }
316
+
317
+ ret = bdrv_co_zone_mgmt(blk_bs(blk), op, offset, len);
318
+ blk_dec_in_flight(blk);
319
+ return ret;
320
+}
321
+
322
void blk_drain(BlockBackend *blk)
323
{
324
BlockDriverState *bs = blk_bs(blk);
325
diff --git a/block/file-posix.c b/block/file-posix.c
326
index XXXXXXX..XXXXXXX 100644
327
--- a/block/file-posix.c
328
+++ b/block/file-posix.c
329
@@ -XXX,XX +XXX,XX @@
330
#include <sys/param.h>
331
#include <sys/syscall.h>
332
#include <sys/vfs.h>
333
+#if defined(CONFIG_BLKZONED)
334
+#include <linux/blkzoned.h>
335
+#endif
336
#include <linux/cdrom.h>
337
#include <linux/fd.h>
338
#include <linux/fs.h>
339
@@ -XXX,XX +XXX,XX @@ typedef struct RawPosixAIOData {
340
PreallocMode prealloc;
341
Error **errp;
342
} truncate;
343
+ struct {
344
+ unsigned int *nr_zones;
345
+ BlockZoneDescriptor *zones;
346
+ } zone_report;
347
+ struct {
348
+ unsigned long op;
349
+ } zone_mgmt;
350
};
351
} RawPosixAIOData;
352
353
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
354
zoned = BLK_Z_NONE;
36
}
355
}
37
356
bs->bl.zoned = zoned;
38
s->hfile = CreateFile(filename, access_flags,
357
+ if (zoned != BLK_Z_NONE) {
39
- FILE_SHARE_READ, NULL,
358
+ /*
40
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
359
+ * The zoned device must at least have zone size and nr_zones fields.
41
OPEN_EXISTING, overlapped, NULL);
360
+ */
42
if (s->hfile == INVALID_HANDLE_VALUE) {
361
+ ret = get_sysfs_long_val(&st, "chunk_sectors");
43
int err = GetLastError();
362
+ if (ret < 0) {
44
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv,
363
+ error_setg_errno(errp, -ret, "Unable to read chunk_sectors "
45
return raw_co_create(&options, errp);
364
+ "sysfs attribute");
365
+ goto out;
366
+ } else if (!ret) {
367
+ error_setg(errp, "Read 0 from chunk_sectors sysfs attribute");
368
+ goto out;
369
+ }
370
+ bs->bl.zone_size = ret << BDRV_SECTOR_BITS;
371
+
372
+ ret = get_sysfs_long_val(&st, "nr_zones");
373
+ if (ret < 0) {
374
+ error_setg_errno(errp, -ret, "Unable to read nr_zones "
375
+ "sysfs attribute");
376
+ goto out;
377
+ } else if (!ret) {
378
+ error_setg(errp, "Read 0 from nr_zones sysfs attribute");
379
+ goto out;
380
+ }
381
+ bs->bl.nr_zones = ret;
382
+
383
+ ret = get_sysfs_long_val(&st, "zone_append_max_bytes");
384
+ if (ret > 0) {
385
+ bs->bl.max_append_sectors = ret >> BDRV_SECTOR_BITS;
386
+ }
387
+
388
+ ret = get_sysfs_long_val(&st, "max_open_zones");
389
+ if (ret >= 0) {
390
+ bs->bl.max_open_zones = ret;
391
+ }
392
+
393
+ ret = get_sysfs_long_val(&st, "max_active_zones");
394
+ if (ret >= 0) {
395
+ bs->bl.max_active_zones = ret;
396
+ }
397
+ return;
398
+ }
399
+out:
400
+ bs->bl.zoned = BLK_Z_NONE;
46
}
401
}
47
402
48
+static int raw_reopen_prepare(BDRVReopenState *state,
403
static int check_for_dasd(int fd)
49
+ BlockReopenQueue *queue, Error **errp)
404
@@ -XXX,XX +XXX,XX @@ static int hdev_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz)
50
+{
405
BDRVRawState *s = bs->opaque;
51
+ BDRVRawState *s = state->bs->opaque;
406
int ret;
52
+ BDRVRawReopenState *rs;
407
53
+ int access_flags;
408
- /* If DASD, get blocksizes */
54
+ DWORD overlapped;
409
+ /* If DASD or zoned devices, get blocksizes */
55
+ int ret = 0;
410
if (check_for_dasd(s->fd) < 0) {
56
+
411
- return -ENOTSUP;
57
+ if (s->type != FTYPE_FILE) {
412
+ /* zoned devices are not DASD */
58
+ error_setg(errp, "Can only reopen files");
413
+ if (bs->bl.zoned == BLK_Z_NONE) {
414
+ return -ENOTSUP;
415
+ }
416
}
417
ret = probe_logical_blocksize(s->fd, &bsz->log);
418
if (ret < 0) {
419
@@ -XXX,XX +XXX,XX @@ static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
420
}
421
#endif
422
423
+/*
424
+ * parse_zone - Fill a zone descriptor
425
+ */
426
+#if defined(CONFIG_BLKZONED)
427
+static inline int parse_zone(struct BlockZoneDescriptor *zone,
428
+ const struct blk_zone *blkz) {
429
+ zone->start = blkz->start << BDRV_SECTOR_BITS;
430
+ zone->length = blkz->len << BDRV_SECTOR_BITS;
431
+ zone->wp = blkz->wp << BDRV_SECTOR_BITS;
432
+
433
+#ifdef HAVE_BLK_ZONE_REP_CAPACITY
434
+ zone->cap = blkz->capacity << BDRV_SECTOR_BITS;
435
+#else
436
+ zone->cap = blkz->len << BDRV_SECTOR_BITS;
437
+#endif
438
+
439
+ switch (blkz->type) {
440
+ case BLK_ZONE_TYPE_SEQWRITE_REQ:
441
+ zone->type = BLK_ZT_SWR;
442
+ break;
443
+ case BLK_ZONE_TYPE_SEQWRITE_PREF:
444
+ zone->type = BLK_ZT_SWP;
445
+ break;
446
+ case BLK_ZONE_TYPE_CONVENTIONAL:
447
+ zone->type = BLK_ZT_CONV;
448
+ break;
449
+ default:
450
+ error_report("Unsupported zone type: 0x%x", blkz->type);
451
+ return -ENOTSUP;
452
+ }
453
+
454
+ switch (blkz->cond) {
455
+ case BLK_ZONE_COND_NOT_WP:
456
+ zone->state = BLK_ZS_NOT_WP;
457
+ break;
458
+ case BLK_ZONE_COND_EMPTY:
459
+ zone->state = BLK_ZS_EMPTY;
460
+ break;
461
+ case BLK_ZONE_COND_IMP_OPEN:
462
+ zone->state = BLK_ZS_IOPEN;
463
+ break;
464
+ case BLK_ZONE_COND_EXP_OPEN:
465
+ zone->state = BLK_ZS_EOPEN;
466
+ break;
467
+ case BLK_ZONE_COND_CLOSED:
468
+ zone->state = BLK_ZS_CLOSED;
469
+ break;
470
+ case BLK_ZONE_COND_READONLY:
471
+ zone->state = BLK_ZS_RDONLY;
472
+ break;
473
+ case BLK_ZONE_COND_FULL:
474
+ zone->state = BLK_ZS_FULL;
475
+ break;
476
+ case BLK_ZONE_COND_OFFLINE:
477
+ zone->state = BLK_ZS_OFFLINE;
478
+ break;
479
+ default:
480
+ error_report("Unsupported zone state: 0x%x", blkz->cond);
481
+ return -ENOTSUP;
482
+ }
483
+ return 0;
484
+}
485
+#endif
486
+
487
+#if defined(CONFIG_BLKZONED)
488
+static int handle_aiocb_zone_report(void *opaque)
489
+{
490
+ RawPosixAIOData *aiocb = opaque;
491
+ int fd = aiocb->aio_fildes;
492
+ unsigned int *nr_zones = aiocb->zone_report.nr_zones;
493
+ BlockZoneDescriptor *zones = aiocb->zone_report.zones;
494
+ /* zoned block devices use 512-byte sectors */
495
+ uint64_t sector = aiocb->aio_offset / 512;
496
+
497
+ struct blk_zone *blkz;
498
+ size_t rep_size;
499
+ unsigned int nrz;
500
+ int ret, n = 0, i = 0;
501
+
502
+ nrz = *nr_zones;
503
+ rep_size = sizeof(struct blk_zone_report) + nrz * sizeof(struct blk_zone);
504
+ g_autofree struct blk_zone_report *rep = NULL;
505
+ rep = g_malloc(rep_size);
506
+
507
+ blkz = (struct blk_zone *)(rep + 1);
508
+ while (n < nrz) {
509
+ memset(rep, 0, rep_size);
510
+ rep->sector = sector;
511
+ rep->nr_zones = nrz - n;
512
+
513
+ do {
514
+ ret = ioctl(fd, BLKREPORTZONE, rep);
515
+ } while (ret != 0 && errno == EINTR);
516
+ if (ret != 0) {
517
+ error_report("%d: ioctl BLKREPORTZONE at %" PRId64 " failed %d",
518
+ fd, sector, errno);
519
+ return -errno;
520
+ }
521
+
522
+ if (!rep->nr_zones) {
523
+ break;
524
+ }
525
+
526
+ for (i = 0; i < rep->nr_zones; i++, n++) {
527
+ ret = parse_zone(&zones[n], &blkz[i]);
528
+ if (ret != 0) {
529
+ return ret;
530
+ }
531
+
532
+ /* The next report should start after the last zone reported */
533
+ sector = blkz[i].start + blkz[i].len;
534
+ }
535
+ }
536
+
537
+ *nr_zones = n;
538
+ return 0;
539
+}
540
+#endif
541
+
542
+#if defined(CONFIG_BLKZONED)
543
+static int handle_aiocb_zone_mgmt(void *opaque)
544
+{
545
+ RawPosixAIOData *aiocb = opaque;
546
+ int fd = aiocb->aio_fildes;
547
+ uint64_t sector = aiocb->aio_offset / 512;
548
+ int64_t nr_sectors = aiocb->aio_nbytes / 512;
549
+ struct blk_zone_range range;
550
+ int ret;
551
+
552
+ /* Execute the operation */
553
+ range.sector = sector;
554
+ range.nr_sectors = nr_sectors;
555
+ do {
556
+ ret = ioctl(fd, aiocb->zone_mgmt.op, &range);
557
+ } while (ret != 0 && errno == EINTR);
558
+
559
+ return ret;
560
+}
561
+#endif
562
+
563
static int handle_aiocb_copy_range(void *opaque)
564
{
565
RawPosixAIOData *aiocb = opaque;
566
@@ -XXX,XX +XXX,XX @@ static void raw_account_discard(BDRVRawState *s, uint64_t nbytes, int ret)
567
}
568
}
569
570
+/*
571
+ * zone report - Get a zone block device's information in the form
572
+ * of an array of zone descriptors.
573
+ * zones is an array of zone descriptors to hold zone information on reply;
574
+ * offset can be any byte within the entire size of the device;
575
+ * nr_zones is the maxium number of sectors the command should operate on.
576
+ */
577
+#if defined(CONFIG_BLKZONED)
578
+static int coroutine_fn raw_co_zone_report(BlockDriverState *bs, int64_t offset,
579
+ unsigned int *nr_zones,
580
+ BlockZoneDescriptor *zones) {
581
+ BDRVRawState *s = bs->opaque;
582
+ RawPosixAIOData acb = (RawPosixAIOData) {
583
+ .bs = bs,
584
+ .aio_fildes = s->fd,
585
+ .aio_type = QEMU_AIO_ZONE_REPORT,
586
+ .aio_offset = offset,
587
+ .zone_report = {
588
+ .nr_zones = nr_zones,
589
+ .zones = zones,
590
+ },
591
+ };
592
+
593
+ return raw_thread_pool_submit(bs, handle_aiocb_zone_report, &acb);
594
+}
595
+#endif
596
+
597
+/*
598
+ * zone management operations - Execute an operation on a zone
599
+ */
600
+#if defined(CONFIG_BLKZONED)
601
+static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
602
+ int64_t offset, int64_t len) {
603
+ BDRVRawState *s = bs->opaque;
604
+ RawPosixAIOData acb;
605
+ int64_t zone_size, zone_size_mask;
606
+ const char *op_name;
607
+ unsigned long zo;
608
+ int ret;
609
+ int64_t capacity = bs->total_sectors << BDRV_SECTOR_BITS;
610
+
611
+ zone_size = bs->bl.zone_size;
612
+ zone_size_mask = zone_size - 1;
613
+ if (offset & zone_size_mask) {
614
+ error_report("sector offset %" PRId64 " is not aligned to zone size "
615
+ "%" PRId64 "", offset / 512, zone_size / 512);
59
+ return -EINVAL;
616
+ return -EINVAL;
60
+ }
617
+ }
61
+
618
+
62
+ rs = g_new0(BDRVRawReopenState, 1);
619
+ if (((offset + len) < capacity && len & zone_size_mask) ||
63
+
620
+ offset + len > capacity) {
64
+ /*
621
+ error_report("number of sectors %" PRId64 " is not aligned to zone size"
65
+ * We do not support changing any options (only flags). By leaving
622
+ " %" PRId64 "", len / 512, zone_size / 512);
66
+ * all options in state->options, we tell the generic reopen code
623
+ return -EINVAL;
67
+ * that we do not support changing any of them, so it will verify
624
+ }
68
+ * that their values did not change.
625
+
69
+ */
626
+ switch (op) {
70
+
627
+ case BLK_ZO_OPEN:
71
+ raw_parse_flags(state->flags, s->aio != NULL, &access_flags, &overlapped);
628
+ op_name = "BLKOPENZONE";
72
+ rs->hfile = CreateFile(state->bs->filename, access_flags,
629
+ zo = BLKOPENZONE;
73
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
630
+ break;
74
+ OPEN_EXISTING, overlapped, NULL);
631
+ case BLK_ZO_CLOSE:
75
+
632
+ op_name = "BLKCLOSEZONE";
76
+ if (rs->hfile == INVALID_HANDLE_VALUE) {
633
+ zo = BLKCLOSEZONE;
77
+ int err = GetLastError();
634
+ break;
78
+
635
+ case BLK_ZO_FINISH:
79
+ error_setg_win32(errp, err, "Could not reopen '%s'",
636
+ op_name = "BLKFINISHZONE";
80
+ state->bs->filename);
637
+ zo = BLKFINISHZONE;
81
+ if (err == ERROR_ACCESS_DENIED) {
638
+ break;
82
+ ret = -EACCES;
639
+ case BLK_ZO_RESET:
83
+ } else {
640
+ op_name = "BLKRESETZONE";
84
+ ret = -EINVAL;
641
+ zo = BLKRESETZONE;
642
+ break;
643
+ default:
644
+ error_report("Unsupported zone op: 0x%x", op);
645
+ return -ENOTSUP;
646
+ }
647
+
648
+ acb = (RawPosixAIOData) {
649
+ .bs = bs,
650
+ .aio_fildes = s->fd,
651
+ .aio_type = QEMU_AIO_ZONE_MGMT,
652
+ .aio_offset = offset,
653
+ .aio_nbytes = len,
654
+ .zone_mgmt = {
655
+ .op = zo,
656
+ },
657
+ };
658
+
659
+ ret = raw_thread_pool_submit(bs, handle_aiocb_zone_mgmt, &acb);
660
+ if (ret != 0) {
661
+ error_report("ioctl %s failed %d", op_name, ret);
662
+ }
663
+
664
+ return ret;
665
+}
666
+#endif
667
+
668
static coroutine_fn int
669
raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes,
670
bool blkdev)
671
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
672
#ifdef __linux__
673
.bdrv_co_ioctl = hdev_co_ioctl,
674
#endif
675
+
676
+ /* zoned device */
677
+#if defined(CONFIG_BLKZONED)
678
+ /* zone management operations */
679
+ .bdrv_co_zone_report = raw_co_zone_report,
680
+ .bdrv_co_zone_mgmt = raw_co_zone_mgmt,
681
+#endif
682
};
683
684
#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
685
diff --git a/block/io.c b/block/io.c
686
index XXXXXXX..XXXXXXX 100644
687
--- a/block/io.c
688
+++ b/block/io.c
689
@@ -XXX,XX +XXX,XX @@ out:
690
return co.ret;
691
}
692
693
+int coroutine_fn bdrv_co_zone_report(BlockDriverState *bs, int64_t offset,
694
+ unsigned int *nr_zones,
695
+ BlockZoneDescriptor *zones)
696
+{
697
+ BlockDriver *drv = bs->drv;
698
+ CoroutineIOCompletion co = {
699
+ .coroutine = qemu_coroutine_self(),
700
+ };
701
+ IO_CODE();
702
+
703
+ bdrv_inc_in_flight(bs);
704
+ if (!drv || !drv->bdrv_co_zone_report || bs->bl.zoned == BLK_Z_NONE) {
705
+ co.ret = -ENOTSUP;
706
+ goto out;
707
+ }
708
+ co.ret = drv->bdrv_co_zone_report(bs, offset, nr_zones, zones);
709
+out:
710
+ bdrv_dec_in_flight(bs);
711
+ return co.ret;
712
+}
713
+
714
+int coroutine_fn bdrv_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
715
+ int64_t offset, int64_t len)
716
+{
717
+ BlockDriver *drv = bs->drv;
718
+ CoroutineIOCompletion co = {
719
+ .coroutine = qemu_coroutine_self(),
720
+ };
721
+ IO_CODE();
722
+
723
+ bdrv_inc_in_flight(bs);
724
+ if (!drv || !drv->bdrv_co_zone_mgmt || bs->bl.zoned == BLK_Z_NONE) {
725
+ co.ret = -ENOTSUP;
726
+ goto out;
727
+ }
728
+ co.ret = drv->bdrv_co_zone_mgmt(bs, op, offset, len);
729
+out:
730
+ bdrv_dec_in_flight(bs);
731
+ return co.ret;
732
+}
733
+
734
void *qemu_blockalign(BlockDriverState *bs, size_t size)
735
{
736
IO_CODE();
737
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
738
index XXXXXXX..XXXXXXX 100644
739
--- a/qemu-io-cmds.c
740
+++ b/qemu-io-cmds.c
741
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t flush_cmd = {
742
.oneline = "flush all in-core file state to disk",
743
};
744
745
+static inline int64_t tosector(int64_t bytes)
746
+{
747
+ return bytes >> BDRV_SECTOR_BITS;
748
+}
749
+
750
+static int zone_report_f(BlockBackend *blk, int argc, char **argv)
751
+{
752
+ int ret;
753
+ int64_t offset;
754
+ unsigned int nr_zones;
755
+
756
+ ++optind;
757
+ offset = cvtnum(argv[optind]);
758
+ ++optind;
759
+ nr_zones = cvtnum(argv[optind]);
760
+
761
+ g_autofree BlockZoneDescriptor *zones = NULL;
762
+ zones = g_new(BlockZoneDescriptor, nr_zones);
763
+ ret = blk_zone_report(blk, offset, &nr_zones, zones);
764
+ if (ret < 0) {
765
+ printf("zone report failed: %s\n", strerror(-ret));
766
+ } else {
767
+ for (int i = 0; i < nr_zones; ++i) {
768
+ printf("start: 0x%" PRIx64 ", len 0x%" PRIx64 ", "
769
+ "cap"" 0x%" PRIx64 ", wptr 0x%" PRIx64 ", "
770
+ "zcond:%u, [type: %u]\n",
771
+ tosector(zones[i].start), tosector(zones[i].length),
772
+ tosector(zones[i].cap), tosector(zones[i].wp),
773
+ zones[i].state, zones[i].type);
85
+ }
774
+ }
86
+ goto fail;
775
+ }
87
+ }
88
+
89
+ if (s->aio) {
90
+ ret = win32_aio_attach(s->aio, rs->hfile);
91
+ if (ret < 0) {
92
+ error_setg_errno(errp, -ret, "Could not enable AIO");
93
+ CloseHandle(rs->hfile);
94
+ goto fail;
95
+ }
96
+ }
97
+
98
+ state->opaque = rs;
99
+
100
+ return 0;
101
+
102
+fail:
103
+ g_free(rs);
104
+ state->opaque = NULL;
105
+
106
+ return ret;
776
+ return ret;
107
+}
777
+}
108
+
778
+
109
+static void raw_reopen_commit(BDRVReopenState *state)
779
+static const cmdinfo_t zone_report_cmd = {
110
+{
780
+ .name = "zone_report",
111
+ BDRVRawState *s = state->bs->opaque;
781
+ .altname = "zrp",
112
+ BDRVRawReopenState *rs = state->opaque;
782
+ .cfunc = zone_report_f,
113
+
783
+ .argmin = 2,
114
+ assert(rs != NULL);
784
+ .argmax = 2,
115
+
785
+ .args = "offset number",
116
+ CloseHandle(s->hfile);
786
+ .oneline = "report zone information",
117
+ s->hfile = rs->hfile;
787
+};
118
+
788
+
119
+ g_free(rs);
789
+static int zone_open_f(BlockBackend *blk, int argc, char **argv)
120
+ state->opaque = NULL;
790
+{
121
+}
791
+ int ret;
122
+
792
+ int64_t offset, len;
123
+static void raw_reopen_abort(BDRVReopenState *state)
793
+ ++optind;
124
+{
794
+ offset = cvtnum(argv[optind]);
125
+ BDRVRawReopenState *rs = state->opaque;
795
+ ++optind;
126
+
796
+ len = cvtnum(argv[optind]);
127
+ if (!rs) {
797
+ ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
128
+ return;
798
+ if (ret < 0) {
129
+ }
799
+ printf("zone open failed: %s\n", strerror(-ret));
130
+
800
+ }
131
+ if (rs->hfile != INVALID_HANDLE_VALUE) {
801
+ return ret;
132
+ CloseHandle(rs->hfile);
802
+}
133
+ }
803
+
134
+
804
+static const cmdinfo_t zone_open_cmd = {
135
+ g_free(rs);
805
+ .name = "zone_open",
136
+ state->opaque = NULL;
806
+ .altname = "zo",
137
+}
807
+ .cfunc = zone_open_f,
138
+
808
+ .argmin = 2,
139
static QemuOptsList raw_create_opts = {
809
+ .argmax = 2,
140
.name = "raw-create-opts",
810
+ .args = "offset len",
141
.head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head),
811
+ .oneline = "explicit open a range of zones in zone block device",
142
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
812
+};
143
.bdrv_co_create_opts = raw_co_create_opts,
813
+
144
.bdrv_has_zero_init = bdrv_has_zero_init_1,
814
+static int zone_close_f(BlockBackend *blk, int argc, char **argv)
145
815
+{
146
+ .bdrv_reopen_prepare = raw_reopen_prepare,
816
+ int ret;
147
+ .bdrv_reopen_commit = raw_reopen_commit,
817
+ int64_t offset, len;
148
+ .bdrv_reopen_abort = raw_reopen_abort,
818
+ ++optind;
149
+
819
+ offset = cvtnum(argv[optind]);
150
.bdrv_aio_preadv = raw_aio_preadv,
820
+ ++optind;
151
.bdrv_aio_pwritev = raw_aio_pwritev,
821
+ len = cvtnum(argv[optind]);
152
.bdrv_aio_flush = raw_aio_flush,
822
+ ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
823
+ if (ret < 0) {
824
+ printf("zone close failed: %s\n", strerror(-ret));
825
+ }
826
+ return ret;
827
+}
828
+
829
+static const cmdinfo_t zone_close_cmd = {
830
+ .name = "zone_close",
831
+ .altname = "zc",
832
+ .cfunc = zone_close_f,
833
+ .argmin = 2,
834
+ .argmax = 2,
835
+ .args = "offset len",
836
+ .oneline = "close a range of zones in zone block device",
837
+};
838
+
839
+static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
840
+{
841
+ int ret;
842
+ int64_t offset, len;
843
+ ++optind;
844
+ offset = cvtnum(argv[optind]);
845
+ ++optind;
846
+ len = cvtnum(argv[optind]);
847
+ ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
848
+ if (ret < 0) {
849
+ printf("zone finish failed: %s\n", strerror(-ret));
850
+ }
851
+ return ret;
852
+}
853
+
854
+static const cmdinfo_t zone_finish_cmd = {
855
+ .name = "zone_finish",
856
+ .altname = "zf",
857
+ .cfunc = zone_finish_f,
858
+ .argmin = 2,
859
+ .argmax = 2,
860
+ .args = "offset len",
861
+ .oneline = "finish a range of zones in zone block device",
862
+};
863
+
864
+static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
865
+{
866
+ int ret;
867
+ int64_t offset, len;
868
+ ++optind;
869
+ offset = cvtnum(argv[optind]);
870
+ ++optind;
871
+ len = cvtnum(argv[optind]);
872
+ ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
873
+ if (ret < 0) {
874
+ printf("zone reset failed: %s\n", strerror(-ret));
875
+ }
876
+ return ret;
877
+}
878
+
879
+static const cmdinfo_t zone_reset_cmd = {
880
+ .name = "zone_reset",
881
+ .altname = "zrs",
882
+ .cfunc = zone_reset_f,
883
+ .argmin = 2,
884
+ .argmax = 2,
885
+ .args = "offset len",
886
+ .oneline = "reset a zone write pointer in zone block device",
887
+};
888
+
889
static int truncate_f(BlockBackend *blk, int argc, char **argv);
890
static const cmdinfo_t truncate_cmd = {
891
.name = "truncate",
892
@@ -XXX,XX +XXX,XX @@ static void __attribute((constructor)) init_qemuio_commands(void)
893
qemuio_add_command(&aio_write_cmd);
894
qemuio_add_command(&aio_flush_cmd);
895
qemuio_add_command(&flush_cmd);
896
+ qemuio_add_command(&zone_report_cmd);
897
+ qemuio_add_command(&zone_open_cmd);
898
+ qemuio_add_command(&zone_close_cmd);
899
+ qemuio_add_command(&zone_finish_cmd);
900
+ qemuio_add_command(&zone_reset_cmd);
901
qemuio_add_command(&truncate_cmd);
902
qemuio_add_command(&length_cmd);
903
qemuio_add_command(&info_cmd);
153
--
904
--
154
2.31.1
905
2.39.2
155
906
156
907
diff view generated by jsdifflib
1
From: Stefan Hajnoczi <stefanha@redhat.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
The following command-line fails due to a permissions conflict:
3
raw-format driver usually sits on top of file-posix driver. It needs to
4
pass through requests of zone commands.
4
5
5
$ qemu-storage-daemon \
6
Signed-off-by: Sam Li <faithilikerun@gmail.com>
6
--blockdev driver=nvme,node-name=nvme0,device=0000:08:00.0,namespace=1 \
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
--blockdev driver=raw,node-name=l1-1,file=nvme0,offset=0,size=1073741824 \
8
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
8
--blockdev driver=raw,node-name=l1-2,file=nvme0,offset=1073741824,size=1073741824 \
9
Reviewed-by: Hannes Reinecke <hare@suse.de>
9
--nbd-server addr.type=unix,addr.path=/tmp/nbd.sock,max-connections=2 \
10
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
10
--export type=nbd,id=nbd-l1-1,node-name=l1-1,name=l1-1,writable=on \
11
Acked-by: Kevin Wolf <kwolf@redhat.com>
11
--export type=nbd,id=nbd-l1-2,node-name=l1-2,name=l1-2,writable=on
12
Message-id: 20230324090605.28361-5-faithilikerun@gmail.com
12
13
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
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
<philmd@linaro.org>.
14
15
--Stefan]
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>
16
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
---
17
---
35
block/raw-format.c | 21 ++++++++++++++++++++-
18
block/raw-format.c | 17 +++++++++++++++++
36
1 file changed, 20 insertions(+), 1 deletion(-)
19
1 file changed, 17 insertions(+)
37
20
38
diff --git a/block/raw-format.c b/block/raw-format.c
21
diff --git a/block/raw-format.c b/block/raw-format.c
39
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
40
--- a/block/raw-format.c
23
--- a/block/raw-format.c
41
+++ b/block/raw-format.c
24
+++ b/block/raw-format.c
42
@@ -XXX,XX +XXX,XX @@ static void raw_cancel_in_flight(BlockDriverState *bs)
25
@@ -XXX,XX +XXX,XX @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
43
bdrv_cancel_in_flight(bs->file->bs);
26
return bdrv_co_pdiscard(bs->file, offset, bytes);
44
}
27
}
45
28
46
+static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
29
+static int coroutine_fn GRAPH_RDLOCK
47
+ BdrvChildRole role,
30
+raw_co_zone_report(BlockDriverState *bs, int64_t offset,
48
+ BlockReopenQueue *reopen_queue,
31
+ unsigned int *nr_zones,
49
+ uint64_t parent_perm, uint64_t parent_shared,
32
+ BlockZoneDescriptor *zones)
50
+ uint64_t *nperm, uint64_t *nshared)
51
+{
33
+{
52
+ bdrv_default_perms(bs, c, role, reopen_queue, parent_perm,
34
+ return bdrv_co_zone_report(bs->file->bs, offset, nr_zones, zones);
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
+}
35
+}
64
+
36
+
65
BlockDriver bdrv_raw = {
37
+static int coroutine_fn GRAPH_RDLOCK
66
.format_name = "raw",
38
+raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
67
.instance_size = sizeof(BDRVRawState),
39
+ int64_t offset, int64_t len)
40
+{
41
+ return bdrv_co_zone_mgmt(bs->file->bs, op, offset, len);
42
+}
43
+
44
static int64_t coroutine_fn GRAPH_RDLOCK
45
raw_co_getlength(BlockDriverState *bs)
46
{
68
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
47
@@ -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,
48
.bdrv_co_pwritev = &raw_co_pwritev,
49
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
50
.bdrv_co_pdiscard = &raw_co_pdiscard,
51
+ .bdrv_co_zone_report = &raw_co_zone_report,
52
+ .bdrv_co_zone_mgmt = &raw_co_zone_mgmt,
53
.bdrv_co_block_status = &raw_co_block_status,
54
.bdrv_co_copy_range_from = &raw_co_copy_range_from,
55
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
77
--
56
--
78
2.31.1
57
2.39.2
79
58
80
59
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Silences a new pylint warning. The dangers of *not* doing this are
4
somewhat unclear; I believe the file object gets garbage collected
5
eventually, but possibly the way in which it happens is
6
non-deterministic. Maybe this is a valid warning, but if there are
7
consequences of not doing it, I am not aware of them at present.
8
9
Signed-off-by: John Snow <jsnow@redhat.com>
10
Message-Id: <20210720173336.1876937-2-jsnow@redhat.com>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
tests/qemu-iotests/iotests.py | 7 ++++---
15
1 file changed, 4 insertions(+), 3 deletions(-)
16
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
20
+++ b/tests/qemu-iotests/iotests.py
21
@@ -XXX,XX +XXX,XX @@ def notrun(reason):
22
# Each test in qemu-iotests has a number ("seq")
23
seq = os.path.basename(sys.argv[0])
24
25
- open('%s/%s.notrun' % (output_dir, seq), 'w').write(reason + '\n')
26
+ with open('%s/%s.notrun' % (output_dir, seq), 'w') as outfile:
27
+ outfile.write(reason + '\n')
28
logger.warning("%s not run: %s", seq, reason)
29
sys.exit(0)
30
31
@@ -XXX,XX +XXX,XX @@ def case_notrun(reason):
32
# Each test in qemu-iotests has a number ("seq")
33
seq = os.path.basename(sys.argv[0])
34
35
- open('%s/%s.casenotrun' % (output_dir, seq), 'a').write(
36
- ' [case not run] ' + reason + '\n')
37
+ with open('%s/%s.casenotrun' % (output_dir, seq), 'a') as outfile:
38
+ outfile.write(' [case not run] ' + reason + '\n')
39
40
def _verify_image_format(supported_fmts: Sequence[str] = (),
41
unsupported_fmts: Sequence[str] = ()) -> None:
42
--
43
2.31.1
44
45
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
Avoids a warning from pylint not to use open() outside of a
4
with-statement, and is ... probably more portable anyway. Not that I
5
think we care too much about running tests *on* Windows, but... eh.
6
7
Signed-off-by: John Snow <jsnow@redhat.com>
8
Message-Id: <20210720173336.1876937-3-jsnow@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
tests/qemu-iotests/iotests.py | 14 +++++++-------
13
1 file changed, 7 insertions(+), 7 deletions(-)
14
15
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/iotests.py
18
+++ b/tests/qemu-iotests/iotests.py
19
@@ -XXX,XX +XXX,XX @@ def qemu_io_silent(*args):
20
default_args = qemu_io_args
21
22
args = default_args + list(args)
23
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'))
24
- if exitcode < 0:
25
+ result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False)
26
+ if result.returncode < 0:
27
sys.stderr.write('qemu-io received signal %i: %s\n' %
28
- (-exitcode, ' '.join(args)))
29
- return exitcode
30
+ (-result.returncode, ' '.join(args)))
31
+ return result.returncode
32
33
def qemu_io_silent_check(*args):
34
'''Run qemu-io and return the true if subprocess returned 0'''
35
args = qemu_io_args + list(args)
36
- exitcode = subprocess.call(args, stdout=open('/dev/null', 'w'),
37
- stderr=subprocess.STDOUT)
38
- return exitcode == 0
39
+ result = subprocess.run(args, stdout=subprocess.DEVNULL,
40
+ stderr=subprocess.STDOUT, check=False)
41
+ return result.returncode == 0
42
43
class QemuIoInteractive:
44
def __init__(self, *args):
45
--
46
2.31.1
47
48
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
We need an ability to insert filters above top block node, attached to
3
Putting zoned/non-zoned BlockDrivers on top of each other is not
4
block device. It can't be achieved with blockdev-reopen command. So, we
4
allowed.
5
want do it with help of qom-set.
6
5
7
Intended usage:
6
Signed-off-by: Sam Li <faithilikerun@gmail.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Hannes Reinecke <hare@suse.de>
9
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
10
Acked-by: Kevin Wolf <kwolf@redhat.com>
11
Message-id: 20230324090605.28361-6-faithilikerun@gmail.com
12
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
13
<philmd@linaro.org> and clarify that the check is about zoned
14
BlockDrivers.
15
--Stefan]
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
include/block/block_int-common.h | 5 +++++
19
block.c | 19 +++++++++++++++++++
20
block/file-posix.c | 12 ++++++++++++
21
block/raw-format.c | 1 +
22
4 files changed, 37 insertions(+)
8
23
9
Assume there is a node A that is attached to some guest device.
24
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
10
11
1. blockdev-add to create a filter node B that has A as its child.
12
13
2. qom-set to change the node attached to the guest device’s
14
BlockBackend from A to B.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-Id: <20210824083856.17408-5-vsementsov@virtuozzo.com>
19
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
20
---
21
hw/core/qdev-properties-system.c | 43 +++++++++++++++++++++++---------
22
1 file changed, 31 insertions(+), 12 deletions(-)
23
24
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
25
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/core/qdev-properties-system.c
26
--- a/include/block/block_int-common.h
27
+++ b/hw/core/qdev-properties-system.c
27
+++ b/include/block/block_int-common.h
28
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
29
29
*/
30
static bool check_prop_still_unset(Object *obj, const char *name,
30
bool is_format;
31
const void *old_val, const char *new_val,
31
32
- Error **errp)
32
+ /*
33
+ bool allow_override, Error **errp)
33
+ * Set to true if the BlockDriver supports zoned children.
34
{
34
+ */
35
const GlobalProperty *prop = qdev_find_global_prop(obj, name);
35
+ bool supports_zoned_children;
36
36
+
37
- if (!old_val) {
37
/*
38
+ if (!old_val || (!prop && allow_override)) {
38
* Drivers not implementing bdrv_parse_filename nor bdrv_open should have
39
return true;
39
* this field set to true, except ones that are defined only by their
40
}
40
diff --git a/block.c b/block.c
41
41
index XXXXXXX..XXXXXXX 100644
42
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
42
--- a/block.c
43
BlockBackend *blk;
43
+++ b/block.c
44
bool blk_created = false;
44
@@ -XXX,XX +XXX,XX @@ void bdrv_add_child(BlockDriverState *parent_bs, BlockDriverState *child_bs,
45
int ret;
46
+ BlockDriverState *bs;
47
+ AioContext *ctx;
48
49
if (!visit_type_str(v, name, &str, errp)) {
50
return;
45
return;
51
}
46
}
52
47
53
- /*
48
+ /*
54
- * TODO Should this really be an error? If no, the old value
49
+ * Non-zoned block drivers do not follow zoned storage constraints
55
- * needs to be released before we store the new one.
50
+ * (i.e. sequential writes to zones). Refuse mixing zoned and non-zoned
56
- */
51
+ * drivers in a graph.
57
- if (!check_prop_still_unset(obj, name, *ptr, str, errp)) {
52
+ */
58
+ if (!check_prop_still_unset(obj, name, *ptr, str, true, errp)) {
53
+ if (!parent_bs->drv->supports_zoned_children &&
54
+ child_bs->bl.zoned == BLK_Z_HM) {
55
+ /*
56
+ * The host-aware model allows zoned storage constraints and random
57
+ * write. Allow mixing host-aware and non-zoned drivers. Using
58
+ * host-aware device as a regular device.
59
+ */
60
+ error_setg(errp, "Cannot add a %s child to a %s parent",
61
+ child_bs->bl.zoned == BLK_Z_HM ? "zoned" : "non-zoned",
62
+ parent_bs->drv->supports_zoned_children ?
63
+ "support zoned children" : "not support zoned children");
59
+ return;
64
+ return;
60
+ }
65
+ }
61
+
66
+
62
+ if (*ptr) {
67
if (!QLIST_EMPTY(&child_bs->parents)) {
63
+ /* BlockBackend alread exists. So, we want to change attached node */
68
error_setg(errp, "The node %s already has a parent",
64
+ blk = *ptr;
69
child_bs->node_name);
65
+ ctx = blk_get_aio_context(blk);
70
diff --git a/block/file-posix.c b/block/file-posix.c
66
+ bs = bdrv_lookup_bs(NULL, str, errp);
71
index XXXXXXX..XXXXXXX 100644
67
+ if (!bs) {
72
--- a/block/file-posix.c
68
+ return;
73
+++ b/block/file-posix.c
69
+ }
74
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
70
+
75
goto fail;
71
+ if (ctx != bdrv_get_aio_context(bs)) {
76
}
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
}
77
}
81
78
+#ifdef CONFIG_BLKZONED
82
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
79
+ /*
83
80
+ * The kernel page cache does not reliably work for writes to SWR zones
84
blk = blk_by_name(str);
81
+ * of zoned block device because it can not guarantee the order of writes.
85
if (!blk) {
82
+ */
86
- BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
83
+ if ((bs->bl.zoned != BLK_Z_NONE) &&
87
+ bs = bdrv_lookup_bs(NULL, str, NULL);
84
+ (!(s->open_flags & O_DIRECT))) {
88
if (bs) {
85
+ error_setg(errp, "The driver supports zoned devices, and it requires "
89
/*
86
+ "cache.direct=on, which was not specified.");
90
* If the device supports iothreads, it will make sure to move the
87
+ return -EINVAL; /* No host kernel page cache */
91
@@ -XXX,XX +XXX,XX @@ static void set_drive_helper(Object *obj, Visitor *v, const char *name,
88
+ }
92
* aware of iothreads require their BlockBackends to be in the main
89
+#endif
93
* AioContext.
90
94
*/
91
if (S_ISBLK(st.st_mode)) {
95
- AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
92
#ifdef __linux__
96
- qemu_get_aio_context();
93
diff --git a/block/raw-format.c b/block/raw-format.c
97
+ ctx = iothread ? bdrv_get_aio_context(bs) : qemu_get_aio_context();
94
index XXXXXXX..XXXXXXX 100644
98
blk = blk_new(ctx, 0, BLK_PERM_ALL);
95
--- a/block/raw-format.c
99
blk_created = true;
96
+++ b/block/raw-format.c
100
97
@@ -XXX,XX +XXX,XX @@ static void raw_child_perm(BlockDriverState *bs, BdrvChild *c,
101
@@ -XXX,XX +XXX,XX @@ static void release_drive(Object *obj, const char *name, void *opaque)
98
BlockDriver bdrv_raw = {
102
const PropertyInfo qdev_prop_drive = {
99
.format_name = "raw",
103
.name = "str",
100
.instance_size = sizeof(BDRVRawState),
104
.description = "Node name or ID of a block device to use as a backend",
101
+ .supports_zoned_children = true,
105
+ .realized_set_allowed = true,
102
.bdrv_probe = &raw_probe,
106
.get = get_drive,
103
.bdrv_reopen_prepare = &raw_reopen_prepare,
107
.set = set_drive,
104
.bdrv_reopen_commit = &raw_reopen_commit,
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
--
105
--
136
2.31.1
106
2.39.2
137
107
138
108
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
We are going to add a test-case with some behavior modifications. So,
3
The new block layer APIs of zoned block devices can be tested by:
4
let's prepare a function to be reused.
4
$ tests/qemu-iotests/check zoned
5
Run each zone operation on a newly created null_blk device
6
and see whether it outputs the same zone information.
5
7
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Sam Li <faithilikerun@gmail.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20210824083856.17408-33-vsementsov@virtuozzo.com>
10
Acked-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20230324090605.28361-7-faithilikerun@gmail.com
12
[Adjust commit message prefix as suggested by Philippe Mathieu-Daudé
13
<philmd@linaro.org>.
14
--Stefan]
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
16
---
11
tests/qemu-iotests/tests/image-fleecing | 19 +++++++++++++------
17
tests/qemu-iotests/tests/zoned | 89 ++++++++++++++++++++++++++++++
12
1 file changed, 13 insertions(+), 6 deletions(-)
18
tests/qemu-iotests/tests/zoned.out | 53 ++++++++++++++++++
19
2 files changed, 142 insertions(+)
20
create mode 100755 tests/qemu-iotests/tests/zoned
21
create mode 100644 tests/qemu-iotests/tests/zoned.out
13
22
14
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
23
diff --git a/tests/qemu-iotests/tests/zoned b/tests/qemu-iotests/tests/zoned
15
index XXXXXXX..XXXXXXX 100755
24
new file mode 100755
16
--- a/tests/qemu-iotests/tests/image-fleecing
25
index XXXXXXX..XXXXXXX
17
+++ b/tests/qemu-iotests/tests/image-fleecing
26
--- /dev/null
18
@@ -XXX,XX +XXX,XX @@ remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
27
+++ b/tests/qemu-iotests/tests/zoned
19
('0xdc', '32M', '32k'), # Left-end of partial-right [2]
28
@@ -XXX,XX +XXX,XX @@
20
('0xcd', '0x3ff0000', '64k')] # patterns[3]
29
+#!/usr/bin/env bash
21
30
+#
22
-with iotests.FilePath('base.img') as base_img_path, \
31
+# Test zone management operations.
23
- iotests.FilePath('fleece.img') as fleece_img_path, \
32
+#
24
- iotests.FilePath('nbd.sock',
33
+
25
- base_dir=iotests.sock_dir) as nbd_sock_path, \
34
+seq="$(basename $0)"
26
- iotests.VM() as vm:
35
+echo "QA output created by $seq"
27
-
36
+status=1 # failure is the default!
28
+def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
37
+
29
log('--- Setting up images ---')
38
+_cleanup()
30
log('')
39
+{
31
40
+ _cleanup_test_img
32
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
41
+ sudo -n rmmod null_blk
33
42
+}
34
log('')
43
+trap "_cleanup; exit \$status" 0 1 2 3 15
35
log('Done')
44
+
45
+# get standard environment, filters and checks
46
+. ../common.rc
47
+. ../common.filter
48
+. ../common.qemu
49
+
50
+# This test only runs on Linux hosts with raw image files.
51
+_supported_fmt raw
52
+_supported_proto file
53
+_supported_os Linux
54
+
55
+sudo -n true || \
56
+ _notrun 'Password-less sudo required'
57
+
58
+IMG="--image-opts -n driver=host_device,filename=/dev/nullb0"
59
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
60
+
61
+echo "Testing a null_blk device:"
62
+echo "case 1: if the operations work"
63
+sudo -n modprobe null_blk nr_devices=1 zoned=1
64
+sudo -n chmod 0666 /dev/nullb0
65
+
66
+echo "(1) report the first zone:"
67
+$QEMU_IO $IMG -c "zrp 0 1"
68
+echo
69
+echo "report the first 10 zones"
70
+$QEMU_IO $IMG -c "zrp 0 10"
71
+echo
72
+echo "report the last zone:"
73
+$QEMU_IO $IMG -c "zrp 0x3e70000000 2" # 0x3e70000000 / 512 = 0x1f380000
74
+echo
75
+echo
76
+echo "(2) opening the first zone"
77
+$QEMU_IO $IMG -c "zo 0 268435456" # 268435456 / 512 = 524288
78
+echo "report after:"
79
+$QEMU_IO $IMG -c "zrp 0 1"
80
+echo
81
+echo "opening the second zone"
82
+$QEMU_IO $IMG -c "zo 268435456 268435456" #
83
+echo "report after:"
84
+$QEMU_IO $IMG -c "zrp 268435456 1"
85
+echo
86
+echo "opening the last zone"
87
+$QEMU_IO $IMG -c "zo 0x3e70000000 268435456"
88
+echo "report after:"
89
+$QEMU_IO $IMG -c "zrp 0x3e70000000 2"
90
+echo
91
+echo
92
+echo "(3) closing the first zone"
93
+$QEMU_IO $IMG -c "zc 0 268435456"
94
+echo "report after:"
95
+$QEMU_IO $IMG -c "zrp 0 1"
96
+echo
97
+echo "closing the last zone"
98
+$QEMU_IO $IMG -c "zc 0x3e70000000 268435456"
99
+echo "report after:"
100
+$QEMU_IO $IMG -c "zrp 0x3e70000000 2"
101
+echo
102
+echo
103
+echo "(4) finishing the second zone"
104
+$QEMU_IO $IMG -c "zf 268435456 268435456"
105
+echo "After finishing a zone:"
106
+$QEMU_IO $IMG -c "zrp 268435456 1"
107
+echo
108
+echo
109
+echo "(5) resetting the second zone"
110
+$QEMU_IO $IMG -c "zrs 268435456 268435456"
111
+echo "After resetting a zone:"
112
+$QEMU_IO $IMG -c "zrp 268435456 1"
113
+
114
+# success, all done
115
+echo "*** done"
116
+rm -f $seq.full
117
+status=0
118
diff --git a/tests/qemu-iotests/tests/zoned.out b/tests/qemu-iotests/tests/zoned.out
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/tests/qemu-iotests/tests/zoned.out
123
@@ -XXX,XX +XXX,XX @@
124
+QA output created by zoned
125
+Testing a null_blk device:
126
+case 1: if the operations work
127
+(1) report the first zone:
128
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
129
+
130
+report the first 10 zones
131
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
132
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:1, [type: 2]
133
+start: 0x100000, len 0x80000, cap 0x80000, wptr 0x100000, zcond:1, [type: 2]
134
+start: 0x180000, len 0x80000, cap 0x80000, wptr 0x180000, zcond:1, [type: 2]
135
+start: 0x200000, len 0x80000, cap 0x80000, wptr 0x200000, zcond:1, [type: 2]
136
+start: 0x280000, len 0x80000, cap 0x80000, wptr 0x280000, zcond:1, [type: 2]
137
+start: 0x300000, len 0x80000, cap 0x80000, wptr 0x300000, zcond:1, [type: 2]
138
+start: 0x380000, len 0x80000, cap 0x80000, wptr 0x380000, zcond:1, [type: 2]
139
+start: 0x400000, len 0x80000, cap 0x80000, wptr 0x400000, zcond:1, [type: 2]
140
+start: 0x480000, len 0x80000, cap 0x80000, wptr 0x480000, zcond:1, [type: 2]
141
+
142
+report the last zone:
143
+start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:1, [type: 2]
36
+
144
+
37
+
145
+
38
+def test():
146
+(2) opening the first zone
39
+ with iotests.FilePath('base.img') as base_img_path, \
147
+report after:
40
+ iotests.FilePath('fleece.img') as fleece_img_path, \
148
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:3, [type: 2]
41
+ iotests.FilePath('nbd.sock',
149
+
42
+ base_dir=iotests.sock_dir) as nbd_sock_path, \
150
+opening the second zone
43
+ iotests.VM() as vm:
151
+report after:
44
+ do_test(base_img_path, fleece_img_path, nbd_sock_path, vm)
152
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:3, [type: 2]
153
+
154
+opening the last zone
155
+report after:
156
+start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:3, [type: 2]
45
+
157
+
46
+
158
+
47
+test()
159
+(3) closing the first zone
160
+report after:
161
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
162
+
163
+closing the last zone
164
+report after:
165
+start: 0x1f380000, len 0x80000, cap 0x80000, wptr 0x1f380000, zcond:1, [type: 2]
166
+
167
+
168
+(4) finishing the second zone
169
+After finishing a zone:
170
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x100000, zcond:14, [type: 2]
171
+
172
+
173
+(5) resetting the second zone
174
+After resetting a zone:
175
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:1, [type: 2]
176
+*** done
48
--
177
--
49
2.31.1
178
2.39.2
50
179
51
180
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
The only caller pass copy_range and compress both false. Let's just
3
Signed-off-by: Sam Li <faithilikerun@gmail.com>
4
drop these arguments.
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
6
Acked-by: Kevin Wolf <kwolf@redhat.com>
7
Message-id: 20230324090605.28361-8-faithilikerun@gmail.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
block/file-posix.c | 3 +++
11
block/trace-events | 2 ++
12
2 files changed, 5 insertions(+)
5
13
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
14
diff --git a/block/file-posix.c b/block/file-posix.c
7
Message-Id: <20210824083856.17408-35-vsementsov@virtuozzo.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/block/block-copy.h | 1 -
12
block/block-copy.c | 5 ++---
13
block/copy-before-write.c | 2 +-
14
3 files changed, 3 insertions(+), 5 deletions(-)
15
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
16
--- a/block/file-posix.c
19
+++ b/include/block/block-copy.h
17
+++ b/block/file-posix.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_report(BlockDriverState *bs, int64_t offset,
21
typedef struct BlockCopyCallState BlockCopyCallState;
19
},
22
20
};
23
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
21
24
- bool use_copy_range, bool compress,
22
+ trace_zbd_zone_report(bs, *nr_zones, offset >> BDRV_SECTOR_BITS);
25
Error **errp);
23
return raw_thread_pool_submit(bs, handle_aiocb_zone_report, &acb);
26
24
}
27
/* Function should be called prior any actual copy request */
25
#endif
28
diff --git a/block/block-copy.c b/block/block-copy.c
26
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
27
},
28
};
29
30
+ trace_zbd_zone_mgmt(bs, op_name, offset >> BDRV_SECTOR_BITS,
31
+ len >> BDRV_SECTOR_BITS);
32
ret = raw_thread_pool_submit(bs, handle_aiocb_zone_mgmt, &acb);
33
if (ret != 0) {
34
error_report("ioctl %s failed %d", op_name, ret);
35
diff --git a/block/trace-events b/block/trace-events
29
index XXXXXXX..XXXXXXX 100644
36
index XXXXXXX..XXXXXXX 100644
30
--- a/block/block-copy.c
37
--- a/block/trace-events
31
+++ b/block/block-copy.c
38
+++ b/block/trace-events
32
@@ -XXX,XX +XXX,XX @@ static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
39
@@ -XXX,XX +XXX,XX @@ file_FindEjectableOpticalMedia(const char *media) "Matching using %s"
33
}
40
file_setup_cdrom(const char *partition) "Using %s as optical disc"
34
41
file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d"
35
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
42
file_flush_fdatasync_failed(int err) "errno %d"
36
- bool use_copy_range,
43
+zbd_zone_report(void *bs, unsigned int nr_zones, int64_t sector) "bs %p report %d zones starting at sector offset 0x%" PRIx64 ""
37
- bool compress, Error **errp)
44
+zbd_zone_mgmt(void *bs, const char *op_name, int64_t sector, int64_t len) "bs %p %s starts at sector offset 0x%" PRIx64 " over a range of 0x%" PRIx64 " sectors"
38
+ Error **errp)
45
39
{
46
# ssh.c
40
BlockCopyState *s;
47
sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)"
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
--
48
--
65
2.31.1
49
2.39.2
66
67
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Define scsi device to operate with it by qom-set in further patch.
3
Add the documentation about the zoned device support to virtio-blk
4
emulation.
4
5
5
Give a new node-name to source block node, to not look like device
6
Signed-off-by: Sam Li <faithilikerun@gmail.com>
6
name.
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
9
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
10
Acked-by: Kevin Wolf <kwolf@redhat.com>
11
Message-id: 20230324090605.28361-9-faithilikerun@gmail.com
12
[Add index-api.rst to fix "zoned-storage.rst:document isn't included in
13
any toctree" error.
14
--Stefan]
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
17
docs/devel/index-api.rst | 1 +
18
docs/devel/zoned-storage.rst | 43 ++++++++++++++++++++++++++
19
docs/system/qemu-block-drivers.rst.inc | 6 ++++
20
3 files changed, 50 insertions(+)
21
create mode 100644 docs/devel/zoned-storage.rst
7
22
8
Job now don't want to work without giving explicit id, so, let's call
23
diff --git a/docs/devel/index-api.rst b/docs/devel/index-api.rst
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
24
index XXXXXXX..XXXXXXX 100644
73
--- a/tests/qemu-iotests/tests/image-fleecing.out
25
--- a/docs/devel/index-api.rst
74
+++ b/tests/qemu-iotests/tests/image-fleecing.out
26
+++ b/docs/devel/index-api.rst
75
@@ -XXX,XX +XXX,XX @@ read -P0 0x3fe0000 64k
27
@@ -XXX,XX +XXX,XX @@ generated from in-code annotations to function prototypes.
76
--- Cleanup ---
28
memory
77
29
modules
78
{"return": {}}
30
ui
79
-{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
31
+ zoned-storage
80
+{"data": {"device": "fleecing", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
32
diff --git a/docs/devel/zoned-storage.rst b/docs/devel/zoned-storage.rst
81
{"return": {}}
33
new file mode 100644
82
{"return": {}}
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/docs/devel/zoned-storage.rst
37
@@ -XXX,XX +XXX,XX @@
38
+=============
39
+zoned-storage
40
+=============
41
+
42
+Zoned Block Devices (ZBDs) divide the LBA space into block regions called zones
43
+that are larger than the LBA size. They can only allow sequential writes, which
44
+can reduce write amplification in SSDs, and potentially lead to higher
45
+throughput and increased capacity. More details about ZBDs can be found at:
46
+
47
+https://zonedstorage.io/docs/introduction/zoned-storage
48
+
49
+1. Block layer APIs for zoned storage
50
+-------------------------------------
51
+QEMU block layer supports three zoned storage models:
52
+- BLK_Z_HM: The host-managed zoned model only allows sequential writes access
53
+to zones. It supports ZBD-specific I/O commands that can be used by a host to
54
+manage the zones of a device.
55
+- BLK_Z_HA: The host-aware zoned model allows random write operations in
56
+zones, making it backward compatible with regular block devices.
57
+- BLK_Z_NONE: The non-zoned model has no zones support. It includes both
58
+regular and drive-managed ZBD devices. ZBD-specific I/O commands are not
59
+supported.
60
+
61
+The block device information resides inside BlockDriverState. QEMU uses
62
+BlockLimits struct(BlockDriverState::bl) that is continuously accessed by the
63
+block layer while processing I/O requests. A BlockBackend has a root pointer to
64
+a BlockDriverState graph(for example, raw format on top of file-posix). The
65
+zoned storage information can be propagated from the leaf BlockDriverState all
66
+the way up to the BlockBackend. If the zoned storage model in file-posix is
67
+set to BLK_Z_HM, then block drivers will declare support for zoned host device.
68
+
69
+The block layer APIs support commands needed for zoned storage devices,
70
+including report zones, four zone operations, and zone append.
71
+
72
+2. Emulating zoned storage controllers
73
+--------------------------------------
74
+When the BlockBackend's BlockLimits model reports a zoned storage device, users
75
+like the virtio-blk emulation or the qemu-io-cmds.c utility can use block layer
76
+APIs for zoned storage emulation or testing.
77
+
78
+For example, to test zone_report on a null_blk device using qemu-io is:
79
+$ path/to/qemu-io --image-opts -n driver=host_device,filename=/dev/nullb0
80
+-c "zrp offset nr_zones"
81
diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc
82
index XXXXXXX..XXXXXXX 100644
83
--- a/docs/system/qemu-block-drivers.rst.inc
84
+++ b/docs/system/qemu-block-drivers.rst.inc
85
@@ -XXX,XX +XXX,XX @@ Hard disks
86
you may corrupt your host data (use the ``-snapshot`` command
87
line option or modify the device permissions accordingly).
88
89
+Zoned block devices
90
+ Zoned block devices can be passed through to the guest if the emulated storage
91
+ controller supports zoned storage. Use ``--blockdev host_device,
92
+ node-name=drive0,filename=/dev/nullb0,cache.direct=on`` to pass through
93
+ ``/dev/nullb0`` as ``drive0``.
94
+
95
Windows
96
^^^^^^^
83
97
84
--
98
--
85
2.31.1
99
2.39.2
86
87
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
New fleecing method becomes available: copy-before-write filter.
3
Introduce the BdrvDmgUncompressFunc type defintion. To emphasis
4
dmg_uncompress_bz2 and dmg_uncompress_lzfse are pointer to functions,
5
declare them using this new typedef.
4
6
5
Actually we don't need backup job to setup image fleecing. Add test
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
for new recommended way of image fleecing.
8
Message-id: 20230320152610.32052-1-philmd@linaro.org
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
11
block/dmg.h | 8 ++++----
12
block/dmg.c | 7 ++-----
13
2 files changed, 6 insertions(+), 9 deletions(-)
7
14
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
diff --git a/block/dmg.h b/block/dmg.h
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-34-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
tests/qemu-iotests/tests/image-fleecing | 50 +++++++++-----
14
tests/qemu-iotests/tests/image-fleecing.out | 72 +++++++++++++++++++++
15
2 files changed, 107 insertions(+), 15 deletions(-)
16
17
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/tests/image-fleecing
20
+++ b/tests/qemu-iotests/tests/image-fleecing
21
@@ -XXX,XX +XXX,XX @@ remainder = [('0xd5', '0x108000', '32k'), # Right-end of partial-left [1]
22
('0xdc', '32M', '32k'), # Left-end of partial-right [2]
23
('0xcd', '0x3ff0000', '64k')] # patterns[3]
24
25
-def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
26
+def do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm):
27
log('--- Setting up images ---')
28
log('')
29
30
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
31
32
src_node = 'source'
33
tmp_node = 'temp'
34
+ qom_path = '/machine/peripheral/sda'
35
vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
36
f'file.filename={base_img_path},node-name={src_node}')
37
vm.add_device('virtio-scsi')
38
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
39
'backing': src_node,
40
}))
41
42
- # Establish COW from source to fleecing node
43
- log(vm.qmp('blockdev-backup',
44
- job_id='fleecing',
45
- device=src_node,
46
- target=tmp_node,
47
- sync='none'))
48
+ # Establish CBW from source to fleecing node
49
+ if use_cbw:
50
+ log(vm.qmp('blockdev-add', {
51
+ 'driver': 'copy-before-write',
52
+ 'node-name': 'fl-cbw',
53
+ 'file': src_node,
54
+ 'target': tmp_node
55
+ }))
56
+
57
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value='fl-cbw'))
58
+ else:
59
+ log(vm.qmp('blockdev-backup',
60
+ job_id='fleecing',
61
+ device=src_node,
62
+ target=tmp_node,
63
+ sync='none'))
64
65
log('')
66
log('--- Setting up NBD Export ---')
67
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
68
for p in overwrite:
69
cmd = 'write -P%s %s %s' % p
70
log(cmd)
71
- log(vm.hmp_qemu_io('/machine/peripheral/sda', cmd, qdev=True))
72
+ log(vm.hmp_qemu_io(qom_path, cmd, qdev=True))
73
74
log('')
75
log('--- Verifying Data ---')
76
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
77
log('--- Cleanup ---')
78
log('')
79
80
- log(vm.qmp('block-job-cancel', device='fleecing'))
81
- e = vm.event_wait('BLOCK_JOB_CANCELLED')
82
- assert e is not None
83
- log(e, filters=[iotests.filter_qmp_event])
84
+ if use_cbw:
85
+ log(vm.qmp('qom-set', path=qom_path, property='drive', value=src_node))
86
+ log(vm.qmp('blockdev-del', node_name='fl-cbw'))
87
+ else:
88
+ log(vm.qmp('block-job-cancel', device='fleecing'))
89
+ e = vm.event_wait('BLOCK_JOB_CANCELLED')
90
+ assert e is not None
91
+ log(e, filters=[iotests.filter_qmp_event])
92
+
93
log(vm.qmp('nbd-server-stop'))
94
log(vm.qmp('blockdev-del', node_name=tmp_node))
95
vm.shutdown()
96
@@ -XXX,XX +XXX,XX @@ def do_test(base_img_path, fleece_img_path, nbd_sock_path, vm):
97
log('Done')
98
99
100
-def test():
101
+def test(use_cbw):
102
with iotests.FilePath('base.img') as base_img_path, \
103
iotests.FilePath('fleece.img') as fleece_img_path, \
104
iotests.FilePath('nbd.sock',
105
base_dir=iotests.sock_dir) as nbd_sock_path, \
106
iotests.VM() as vm:
107
- do_test(base_img_path, fleece_img_path, nbd_sock_path, vm)
108
+ do_test(use_cbw, base_img_path, fleece_img_path, nbd_sock_path, vm)
109
+
110
111
+log('=== Test backup(sync=none) based fleecing ===\n')
112
+test(False)
113
114
-test()
115
+log('=== Test filter based fleecing ===\n')
116
+test(True)
117
diff --git a/tests/qemu-iotests/tests/image-fleecing.out b/tests/qemu-iotests/tests/image-fleecing.out
118
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
119
--- a/tests/qemu-iotests/tests/image-fleecing.out
17
--- a/block/dmg.h
120
+++ b/tests/qemu-iotests/tests/image-fleecing.out
18
+++ b/block/dmg.h
19
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVDMGState {
20
z_stream zstream;
21
} BDRVDMGState;
22
23
-extern int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
24
- char *next_out, unsigned int avail_out);
25
+typedef int BdrvDmgUncompressFunc(char *next_in, unsigned int avail_in,
26
+ char *next_out, unsigned int avail_out);
27
28
-extern int (*dmg_uncompress_lzfse)(char *next_in, unsigned int avail_in,
29
- char *next_out, unsigned int avail_out);
30
+extern BdrvDmgUncompressFunc *dmg_uncompress_bz2;
31
+extern BdrvDmgUncompressFunc *dmg_uncompress_lzfse;
32
33
#endif
34
diff --git a/block/dmg.c b/block/dmg.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/dmg.c
37
+++ b/block/dmg.c
121
@@ -XXX,XX +XXX,XX @@
38
@@ -XXX,XX +XXX,XX @@
122
+=== Test backup(sync=none) based fleecing ===
39
#include "qemu/memalign.h"
123
+
40
#include "dmg.h"
124
--- Setting up images ---
41
125
42
-int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
126
Done
43
- char *next_out, unsigned int avail_out);
127
@@ -XXX,XX +XXX,XX @@ read -P0xdc 32M 32k
44
-
128
read -P0xcd 0x3ff0000 64k
45
-int (*dmg_uncompress_lzfse)(char *next_in, unsigned int avail_in,
129
46
- char *next_out, unsigned int avail_out);
130
Done
47
+BdrvDmgUncompressFunc *dmg_uncompress_bz2;
131
+=== Test filter based fleecing ===
48
+BdrvDmgUncompressFunc *dmg_uncompress_lzfse;
132
+
49
133
+--- Setting up images ---
50
enum {
134
+
51
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
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
--
52
--
202
2.31.1
53
2.39.2
203
54
204
55
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
2
2
3
Actually target of backup(sync=None) is not a final backup target:
3
The event filename is an absolute path. Convert it to a relative path when
4
image fleecing is intended to be used with external tool, which will
4
writing '#line' directives, to preserve reproducibility of the generated
5
copy data from fleecing node to some real backup target.
5
output when different base paths are used.
6
6
7
Also, we are going to add a test case for "push backup with fleecing",
7
Signed-off-by: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
8
where instead of exporting fleecing node by NBD, we'll start a backup
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
job from fleecing node to real backup target.
9
Message-Id: <20230406080045.21696-1-thomas.de_schampheleire@nokia.com>
10
---
11
scripts/tracetool/backend/ftrace.py | 4 +++-
12
scripts/tracetool/backend/log.py | 4 +++-
13
scripts/tracetool/backend/syslog.py | 4 +++-
14
3 files changed, 9 insertions(+), 3 deletions(-)
10
15
11
To avoid confusion, let's rename temporary fleecing node now.
16
diff --git a/scripts/tracetool/backend/ftrace.py b/scripts/tracetool/backend/ftrace.py
12
17
index XXXXXXX..XXXXXXX 100644
13
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
--- a/scripts/tracetool/backend/ftrace.py
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
+++ b/scripts/tracetool/backend/ftrace.py
15
Message-Id: <20210824083856.17408-32-vsementsov@virtuozzo.com>
20
@@ -XXX,XX +XXX,XX @@
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
21
__email__ = "stefanha@redhat.com"
17
---
22
18
tests/qemu-iotests/tests/image-fleecing | 14 +++++++-------
23
19
1 file changed, 7 insertions(+), 7 deletions(-)
24
+import os.path
20
25
+
21
diff --git a/tests/qemu-iotests/tests/image-fleecing b/tests/qemu-iotests/tests/image-fleecing
26
from tracetool import out
22
index XXXXXXX..XXXXXXX 100755
27
23
--- a/tests/qemu-iotests/tests/image-fleecing
28
24
+++ b/tests/qemu-iotests/tests/image-fleecing
29
@@ -XXX,XX +XXX,XX @@ def generate_h(event, group):
25
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
30
args=event.args,
26
log('')
31
event_id="TRACE_" + event.name.upper(),
27
32
event_lineno=event.lineno,
28
src_node = 'source'
33
- event_filename=event.filename,
29
+ tmp_node = 'temp'
34
+ event_filename=os.path.relpath(event.filename),
30
vm.add_blockdev(f'driver={iotests.imgfmt},file.driver=file,'
35
fmt=event.fmt.rstrip("\n"),
31
f'file.filename={base_img_path},node-name={src_node}')
36
argnames=argnames)
32
vm.add_device('virtio-scsi')
37
33
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
38
diff --git a/scripts/tracetool/backend/log.py b/scripts/tracetool/backend/log.py
34
log('--- Setting up Fleecing Graph ---')
39
index XXXXXXX..XXXXXXX 100644
35
log('')
40
--- a/scripts/tracetool/backend/log.py
36
41
+++ b/scripts/tracetool/backend/log.py
37
- tgt_node = 'fleeceNode'
42
@@ -XXX,XX +XXX,XX @@
38
43
__email__ = "stefanha@redhat.com"
39
- # create tgt_node backed by src_node
44
40
+ # create tmp_node backed by src_node
45
41
log(vm.qmp('blockdev-add', {
46
+import os.path
42
'driver': 'qcow2',
47
+
43
- 'node-name': tgt_node,
48
from tracetool import out
44
+ 'node-name': tmp_node,
49
45
'file': {
50
46
'driver': 'file',
51
@@ -XXX,XX +XXX,XX @@ def generate_h(event, group):
47
'filename': fleece_img_path,
52
' }',
48
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
53
cond=cond,
49
log(vm.qmp('blockdev-backup',
54
event_lineno=event.lineno,
50
job_id='fleecing',
55
- event_filename=event.filename,
51
device=src_node,
56
+ event_filename=os.path.relpath(event.filename),
52
- target=tgt_node,
57
name=event.name,
53
+ target=tmp_node,
58
fmt=event.fmt.rstrip("\n"),
54
sync='none'))
59
argnames=argnames)
55
60
diff --git a/scripts/tracetool/backend/syslog.py b/scripts/tracetool/backend/syslog.py
56
log('')
61
index XXXXXXX..XXXXXXX 100644
57
log('--- Setting up NBD Export ---')
62
--- a/scripts/tracetool/backend/syslog.py
58
log('')
63
+++ b/scripts/tracetool/backend/syslog.py
59
64
@@ -XXX,XX +XXX,XX @@
60
- nbd_uri = 'nbd+unix:///%s?socket=%s' % (tgt_node, nbd_sock_path)
65
__email__ = "stefanha@redhat.com"
61
+ nbd_uri = 'nbd+unix:///%s?socket=%s' % (tmp_node, nbd_sock_path)
66
62
log(vm.qmp('nbd-server-start',
67
63
{'addr': { 'type': 'unix',
68
+import os.path
64
'data': { 'path': nbd_sock_path } } }))
69
+
65
70
from tracetool import out
66
- log(vm.qmp('nbd-server-add', device=tgt_node))
71
67
+ log(vm.qmp('nbd-server-add', device=tmp_node))
72
68
73
@@ -XXX,XX +XXX,XX @@ def generate_h(event, group):
69
log('')
74
' }',
70
log('--- Sanity Check ---')
75
cond=cond,
71
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base.img') as base_img_path, \
76
event_lineno=event.lineno,
72
assert e is not None
77
- event_filename=event.filename,
73
log(e, filters=[iotests.filter_qmp_event])
78
+ event_filename=os.path.relpath(event.filename),
74
log(vm.qmp('nbd-server-stop'))
79
name=event.name,
75
- log(vm.qmp('blockdev-del', node_name=tgt_node))
80
fmt=event.fmt.rstrip("\n"),
76
+ log(vm.qmp('blockdev-del', node_name=tmp_node))
81
argnames=argnames)
77
vm.shutdown()
78
79
log('')
80
--
82
--
81
2.31.1
83
2.39.2
82
83
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
One more step closer to .bdrv_open(): use options instead of plain
3
Since Linux doesn't have a user API to issue zone append operations to
4
arguments. Move to bdrv_open_child() calls, native for drive open
4
zoned devices from user space, the file-posix driver is modified to add
5
handlers.
5
zone append emulation using regular writes. To do this, the file-posix
6
driver tracks the wp location of all zones of the device. It uses an
7
array of uint64_t. The most significant bit of each wp location indicates
8
if the zone type is conventional zones.
6
9
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
The zones wp can be changed due to the following operations issued:
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
- zone reset: change the wp to the start offset of that zone
9
Message-Id: <20210824083856.17408-19-vsementsov@virtuozzo.com>
12
- zone finish: change to the end location of that zone
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
- write to a zone
14
- zone append
15
16
Signed-off-by: Sam Li <faithilikerun@gmail.com>
17
Message-id: 20230407081657.17947-2-faithilikerun@gmail.com
18
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
19
---
12
block/copy-before-write.c | 29 +++++++++++++++--------------
20
include/block/block-common.h | 14 +++
13
1 file changed, 15 insertions(+), 14 deletions(-)
21
include/block/block_int-common.h | 5 +
22
block/file-posix.c | 173 ++++++++++++++++++++++++++++++-
23
3 files changed, 189 insertions(+), 3 deletions(-)
14
24
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
25
diff --git a/include/block/block-common.h b/include/block/block-common.h
16
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
27
--- a/include/block/block-common.h
18
+++ b/block/copy-before-write.c
28
+++ b/include/block/block-common.h
19
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
29
@@ -XXX,XX +XXX,XX @@ typedef struct BlockZoneDescriptor {
20
}
30
BlockZoneState state;
31
} BlockZoneDescriptor;
32
33
+/*
34
+ * Track write pointers of a zone in bytes.
35
+ */
36
+typedef struct BlockZoneWps {
37
+ CoMutex colock;
38
+ uint64_t wp[];
39
+} BlockZoneWps;
40
+
41
typedef struct BlockDriverInfo {
42
/* in bytes, 0 if irrelevant */
43
int cluster_size;
44
@@ -XXX,XX +XXX,XX @@ typedef enum {
45
#define BDRV_SECTOR_BITS 9
46
#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
47
48
+/*
49
+ * Get the first most significant bit of wp. If it is zero, then
50
+ * the zone type is SWR.
51
+ */
52
+#define BDRV_ZT_IS_CONV(wp) (wp & (1ULL << 63))
53
+
54
#define BDRV_REQUEST_MAX_SECTORS MIN_CONST(SIZE_MAX >> BDRV_SECTOR_BITS, \
55
INT_MAX >> BDRV_SECTOR_BITS)
56
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
57
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/block/block_int-common.h
60
+++ b/include/block/block_int-common.h
61
@@ -XXX,XX +XXX,XX @@ typedef struct BlockLimits {
62
63
/* maximum number of active zones */
64
int64_t max_active_zones;
65
+
66
+ int64_t write_granularity;
67
} BlockLimits;
68
69
typedef struct BdrvOpBlocker BdrvOpBlocker;
70
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
71
CoMutex bsc_modify_lock;
72
/* Always non-NULL, but must only be dereferenced under an RCU read guard */
73
BdrvBlockStatusCache *block_status_cache;
74
+
75
+ /* array of write pointers' location of each zone in the zoned device. */
76
+ BlockZoneWps *wps;
77
};
78
79
struct BlockBackendRootState {
80
diff --git a/block/file-posix.c b/block/file-posix.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/file-posix.c
83
+++ b/block/file-posix.c
84
@@ -XXX,XX +XXX,XX @@ static int hdev_get_max_segments(int fd, struct stat *st)
85
#endif
21
}
86
}
22
87
23
-static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
88
+#if defined(CONFIG_BLKZONED)
24
- BlockDriverState *target, Error **errp)
89
+/*
25
+static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
90
+ * If the reset_all flag is true, then the wps of zone whose state is
91
+ * not readonly or offline should be all reset to the start sector.
92
+ * Else, take the real wp of the device.
93
+ */
94
+static int get_zones_wp(BlockDriverState *bs, int fd, int64_t offset,
95
+ unsigned int nrz, bool reset_all)
96
+{
97
+ struct blk_zone *blkz;
98
+ size_t rep_size;
99
+ uint64_t sector = offset >> BDRV_SECTOR_BITS;
100
+ BlockZoneWps *wps = bs->wps;
101
+ int j = offset / bs->bl.zone_size;
102
+ int ret, n = 0, i = 0;
103
+ rep_size = sizeof(struct blk_zone_report) + nrz * sizeof(struct blk_zone);
104
+ g_autofree struct blk_zone_report *rep = NULL;
105
+
106
+ rep = g_malloc(rep_size);
107
+ blkz = (struct blk_zone *)(rep + 1);
108
+ while (n < nrz) {
109
+ memset(rep, 0, rep_size);
110
+ rep->sector = sector;
111
+ rep->nr_zones = nrz - n;
112
+
113
+ do {
114
+ ret = ioctl(fd, BLKREPORTZONE, rep);
115
+ } while (ret != 0 && errno == EINTR);
116
+ if (ret != 0) {
117
+ error_report("%d: ioctl BLKREPORTZONE at %" PRId64 " failed %d",
118
+ fd, offset, errno);
119
+ return -errno;
120
+ }
121
+
122
+ if (!rep->nr_zones) {
123
+ break;
124
+ }
125
+
126
+ for (i = 0; i < rep->nr_zones; ++i, ++n, ++j) {
127
+ /*
128
+ * The wp tracking cares only about sequential writes required and
129
+ * sequential write preferred zones so that the wp can advance to
130
+ * the right location.
131
+ * Use the most significant bit of the wp location to indicate the
132
+ * zone type: 0 for SWR/SWP zones and 1 for conventional zones.
133
+ */
134
+ if (blkz[i].type == BLK_ZONE_TYPE_CONVENTIONAL) {
135
+ wps->wp[j] |= 1ULL << 63;
136
+ } else {
137
+ switch(blkz[i].cond) {
138
+ case BLK_ZONE_COND_FULL:
139
+ case BLK_ZONE_COND_READONLY:
140
+ /* Zone not writable */
141
+ wps->wp[j] = (blkz[i].start + blkz[i].len) << BDRV_SECTOR_BITS;
142
+ break;
143
+ case BLK_ZONE_COND_OFFLINE:
144
+ /* Zone not writable nor readable */
145
+ wps->wp[j] = (blkz[i].start) << BDRV_SECTOR_BITS;
146
+ break;
147
+ default:
148
+ if (reset_all) {
149
+ wps->wp[j] = blkz[i].start << BDRV_SECTOR_BITS;
150
+ } else {
151
+ wps->wp[j] = blkz[i].wp << BDRV_SECTOR_BITS;
152
+ }
153
+ break;
154
+ }
155
+ }
156
+ }
157
+ sector = blkz[i - 1].start + blkz[i - 1].len;
158
+ }
159
+
160
+ return 0;
161
+}
162
+
163
+static void update_zones_wp(BlockDriverState *bs, int fd, int64_t offset,
164
+ unsigned int nrz)
165
+{
166
+ if (get_zones_wp(bs, fd, offset, nrz, 0) < 0) {
167
+ error_report("update zone wp failed");
168
+ }
169
+}
170
+#endif
171
+
172
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
26
{
173
{
27
BDRVCopyBeforeWriteState *s = bs->opaque;
174
BDRVRawState *s = bs->opaque;
28
175
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
29
- bdrv_ref(target);
176
if (ret >= 0) {
30
- s->target = bdrv_attach_child(bs, target, "target", &child_of_bds,
177
bs->bl.max_active_zones = ret;
31
- BDRV_CHILD_DATA, errp);
178
}
32
- if (!s->target) {
179
+
33
- error_prepend(errp, "Cannot attach target child: ");
180
+ ret = get_sysfs_long_val(&st, "physical_block_size");
34
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
181
+ if (ret >= 0) {
35
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
182
+ bs->bl.write_granularity = ret;
36
+ false, errp);
183
+ }
37
+ if (!bs->file) {
184
+
185
+ /* The refresh_limits() function can be called multiple times. */
186
+ g_free(bs->wps);
187
+ bs->wps = g_malloc(sizeof(BlockZoneWps) +
188
+ sizeof(int64_t) * bs->bl.nr_zones);
189
+ ret = get_zones_wp(bs, s->fd, 0, bs->bl.nr_zones, 0);
190
+ if (ret < 0) {
191
+ error_setg_errno(errp, -ret, "report wps failed");
192
+ bs->wps = NULL;
193
+ return;
194
+ }
195
+ qemu_co_mutex_init(&bs->wps->colock);
196
return;
197
}
198
out:
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
200
{
201
BDRVRawState *s = bs->opaque;
202
RawPosixAIOData acb;
203
+ int ret;
204
205
if (fd_open(bs) < 0)
206
return -EIO;
207
+#if defined(CONFIG_BLKZONED)
208
+ if (type & QEMU_AIO_WRITE && bs->wps) {
209
+ qemu_co_mutex_lock(&bs->wps->colock);
210
+ }
211
+#endif
212
213
/*
214
* When using O_DIRECT, the request must be aligned to be able to use
215
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
216
} else if (s->use_linux_io_uring) {
217
LuringState *aio = aio_get_linux_io_uring(bdrv_get_aio_context(bs));
218
assert(qiov->size == bytes);
219
- return luring_co_submit(bs, aio, s->fd, offset, qiov, type);
220
+ ret = luring_co_submit(bs, aio, s->fd, offset, qiov, type);
221
+ goto out;
222
#endif
223
#ifdef CONFIG_LINUX_AIO
224
} else if (s->use_linux_aio) {
225
LinuxAioState *aio = aio_get_linux_aio(bdrv_get_aio_context(bs));
226
assert(qiov->size == bytes);
227
- return laio_co_submit(bs, aio, s->fd, offset, qiov, type,
228
+ ret = laio_co_submit(bs, aio, s->fd, offset, qiov, type,
229
s->aio_max_batch);
230
+ goto out;
231
#endif
232
}
233
234
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
235
};
236
237
assert(qiov->size == bytes);
238
- return raw_thread_pool_submit(bs, handle_aiocb_rw, &acb);
239
+ ret = raw_thread_pool_submit(bs, handle_aiocb_rw, &acb);
240
+
241
+out:
242
+#if defined(CONFIG_BLKZONED)
243
+ BlockZoneWps *wps = bs->wps;
244
+ if (ret == 0) {
245
+ if (type & QEMU_AIO_WRITE && wps && bs->bl.zone_size) {
246
+ uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
247
+ if (!BDRV_ZT_IS_CONV(*wp)) {
248
+ /* Advance the wp if needed */
249
+ if (offset + bytes > *wp) {
250
+ *wp = offset + bytes;
251
+ }
252
+ }
253
+ }
254
+ } else {
255
+ if (type & QEMU_AIO_WRITE) {
256
+ update_zones_wp(bs, s->fd, 0, 1);
257
+ }
258
+ }
259
+
260
+ if (type & QEMU_AIO_WRITE && wps) {
261
+ qemu_co_mutex_unlock(&wps->colock);
262
+ }
263
+#endif
264
+ return ret;
265
}
266
267
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, int64_t offset,
268
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
269
BDRVRawState *s = bs->opaque;
270
271
if (s->fd >= 0) {
272
+#if defined(CONFIG_BLKZONED)
273
+ g_free(bs->wps);
274
+#endif
275
qemu_close(s->fd);
276
s->fd = -1;
277
}
278
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
279
const char *op_name;
280
unsigned long zo;
281
int ret;
282
+ BlockZoneWps *wps = bs->wps;
283
int64_t capacity = bs->total_sectors << BDRV_SECTOR_BITS;
284
285
zone_size = bs->bl.zone_size;
286
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
38
return -EINVAL;
287
return -EINVAL;
39
}
288
}
40
289
41
- bdrv_ref(source);
290
+ QEMU_LOCK_GUARD(&wps->colock);
42
- bs->file = bdrv_attach_child(bs, source, "file", &child_of_bds,
291
+ uint32_t i = offset / bs->bl.zone_size;
43
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
292
+ uint32_t nrz = len / bs->bl.zone_size;
44
- errp);
293
+ uint64_t *wp = &wps->wp[i];
45
- if (!bs->file) {
294
+ if (BDRV_ZT_IS_CONV(*wp) && len != capacity) {
46
- error_prepend(errp, "Cannot attach file child: ");
295
+ error_report("zone mgmt operations are not allowed for conventional zones");
47
+ s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
296
+ return -EIO;
48
+ BDRV_CHILD_DATA, false, errp);
297
+ }
49
+ if (!s->target) {
298
+
50
return -EINVAL;
299
switch (op) {
51
}
300
case BLK_ZO_OPEN:
52
301
op_name = "BLKOPENZONE";
53
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
302
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
54
int ret;
303
len >> BDRV_SECTOR_BITS);
55
BDRVCopyBeforeWriteState *state;
304
ret = raw_thread_pool_submit(bs, handle_aiocb_zone_mgmt, &acb);
56
BlockDriverState *top;
305
if (ret != 0) {
57
+ QDict *opts;
306
+ update_zones_wp(bs, s->fd, offset, i);
58
307
error_report("ioctl %s failed %d", op_name, ret);
59
assert(source->total_sectors == target->total_sectors);
308
+ return ret;
60
309
+ }
61
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
310
+
62
}
311
+ if (zo == BLKRESETZONE && len == capacity) {
63
state = top->opaque;
312
+ ret = get_zones_wp(bs, s->fd, 0, bs->bl.nr_zones, 1);
64
313
+ if (ret < 0) {
65
- ret = cbw_init(top, source, target, errp);
314
+ error_report("reporting single wp failed");
66
+ opts = qdict_new();
315
+ return ret;
67
+ qdict_put_str(opts, "file", bdrv_get_node_name(source));
316
+ }
68
+ qdict_put_str(opts, "target", bdrv_get_node_name(target));
317
+ } else if (zo == BLKRESETZONE) {
69
+
318
+ for (int j = 0; j < nrz; ++j) {
70
+ ret = cbw_init(top, opts, errp);
319
+ wp[j] = offset + j * zone_size;
71
+ qobject_unref(opts);
320
+ }
72
if (ret < 0) {
321
+ } else if (zo == BLKFINISHZONE) {
73
goto fail;
322
+ for (int j = 0; j < nrz; ++j) {
74
}
323
+ /* The zoned device allows the last zone smaller that the
324
+ * zone size. */
325
+ wp[j] = MIN(offset + (j + 1) * zone_size, offset + len);
326
+ }
327
}
328
329
return ret;
75
--
330
--
76
2.31.1
331
2.39.2
77
78
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Add function to transactionally replace bs inside BdrvChild.
3
A zone append command is a write operation that specifies the first
4
logical block of a zone as the write position. When writing to a zoned
5
block device using zone append, the byte offset of the call may point at
6
any position within the zone to which the data is being appended. Upon
7
completion the device will respond with the position where the data has
8
been written in the zone.
4
9
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Signed-off-by: Sam Li <faithilikerun@gmail.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
7
Message-Id: <20210824083856.17408-2-vsementsov@virtuozzo.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
Message-id: 20230407081657.17947-3-faithilikerun@gmail.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
15
---
10
include/block/block.h | 2 ++
16
include/block/block-io.h | 4 +++
11
block.c | 31 +++++++++++++++++++++++++++++++
17
include/block/block_int-common.h | 3 ++
12
2 files changed, 33 insertions(+)
18
include/block/raw-aio.h | 4 ++-
19
include/sysemu/block-backend-io.h | 9 +++++
20
block/block-backend.c | 60 +++++++++++++++++++++++++++++++
21
block/file-posix.c | 58 ++++++++++++++++++++++++++----
22
block/io.c | 27 ++++++++++++++
23
block/io_uring.c | 4 +++
24
block/linux-aio.c | 3 ++
25
block/raw-format.c | 8 +++++
26
10 files changed, 172 insertions(+), 8 deletions(-)
13
27
14
diff --git a/include/block/block.h b/include/block/block.h
28
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block.h
30
--- a/include/block/block-io.h
17
+++ b/include/block/block.h
31
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_report(BlockDriverState *bs,
19
Error **errp);
33
int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_mgmt(BlockDriverState *bs,
20
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
34
BlockZoneOp op,
21
Error **errp);
35
int64_t offset, int64_t len);
22
+int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
36
+int coroutine_fn GRAPH_RDLOCK bdrv_co_zone_append(BlockDriverState *bs,
23
+ Error **errp);
37
+ int64_t *offset,
24
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *node_options,
38
+ QEMUIOVector *qiov,
25
int flags, Error **errp);
39
+ BdrvRequestFlags flags);
26
int bdrv_drop_filter(BlockDriverState *bs, Error **errp);
40
27
diff --git a/block.c b/block.c
41
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
28
index XXXXXXX..XXXXXXX 100644
42
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
29
--- a/block.c
43
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
30
+++ b/block.c
44
index XXXXXXX..XXXXXXX 100644
31
@@ -XXX,XX +XXX,XX @@ out:
45
--- a/include/block/block_int-common.h
46
+++ b/include/block/block_int-common.h
47
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
48
BlockZoneDescriptor *zones);
49
int coroutine_fn (*bdrv_co_zone_mgmt)(BlockDriverState *bs, BlockZoneOp op,
50
int64_t offset, int64_t len);
51
+ int coroutine_fn (*bdrv_co_zone_append)(BlockDriverState *bs,
52
+ int64_t *offset, QEMUIOVector *qiov,
53
+ BdrvRequestFlags flags);
54
55
/* removable device specific */
56
bool coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_is_inserted)(
57
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/block/raw-aio.h
60
+++ b/include/block/raw-aio.h
61
@@ -XXX,XX +XXX,XX @@
62
#define QEMU_AIO_TRUNCATE 0x0080
63
#define QEMU_AIO_ZONE_REPORT 0x0100
64
#define QEMU_AIO_ZONE_MGMT 0x0200
65
+#define QEMU_AIO_ZONE_APPEND 0x0400
66
#define QEMU_AIO_TYPE_MASK \
67
(QEMU_AIO_READ | \
68
QEMU_AIO_WRITE | \
69
@@ -XXX,XX +XXX,XX @@
70
QEMU_AIO_COPY_RANGE | \
71
QEMU_AIO_TRUNCATE | \
72
QEMU_AIO_ZONE_REPORT | \
73
- QEMU_AIO_ZONE_MGMT)
74
+ QEMU_AIO_ZONE_MGMT | \
75
+ QEMU_AIO_ZONE_APPEND)
76
77
/* AIO flags */
78
#define QEMU_AIO_MISALIGNED 0x1000
79
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
80
index XXXXXXX..XXXXXXX 100644
81
--- a/include/sysemu/block-backend-io.h
82
+++ b/include/sysemu/block-backend-io.h
83
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_zone_report(BlockBackend *blk, int64_t offset,
84
BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
85
int64_t offset, int64_t len,
86
BlockCompletionFunc *cb, void *opaque);
87
+BlockAIOCB *blk_aio_zone_append(BlockBackend *blk, int64_t *offset,
88
+ QEMUIOVector *qiov, BdrvRequestFlags flags,
89
+ BlockCompletionFunc *cb, void *opaque);
90
BlockAIOCB *blk_aio_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes,
91
BlockCompletionFunc *cb, void *opaque);
92
void blk_aio_cancel_async(BlockAIOCB *acb);
93
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
94
int64_t offset, int64_t len);
95
int co_wrapper_mixed blk_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
96
int64_t offset, int64_t len);
97
+int coroutine_fn blk_co_zone_append(BlockBackend *blk, int64_t *offset,
98
+ QEMUIOVector *qiov,
99
+ BdrvRequestFlags flags);
100
+int co_wrapper_mixed blk_zone_append(BlockBackend *blk, int64_t *offset,
101
+ QEMUIOVector *qiov,
102
+ BdrvRequestFlags flags);
103
104
int co_wrapper_mixed blk_pdiscard(BlockBackend *blk, int64_t offset,
105
int64_t bytes);
106
diff --git a/block/block-backend.c b/block/block-backend.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/block-backend.c
109
+++ b/block/block-backend.c
110
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
111
return &acb->common;
112
}
113
114
+static void coroutine_fn blk_aio_zone_append_entry(void *opaque)
115
+{
116
+ BlkAioEmAIOCB *acb = opaque;
117
+ BlkRwCo *rwco = &acb->rwco;
118
+
119
+ rwco->ret = blk_co_zone_append(rwco->blk, (int64_t *)acb->bytes,
120
+ rwco->iobuf, rwco->flags);
121
+ blk_aio_complete(acb);
122
+}
123
+
124
+BlockAIOCB *blk_aio_zone_append(BlockBackend *blk, int64_t *offset,
125
+ QEMUIOVector *qiov, BdrvRequestFlags flags,
126
+ BlockCompletionFunc *cb, void *opaque) {
127
+ BlkAioEmAIOCB *acb;
128
+ Coroutine *co;
129
+ IO_CODE();
130
+
131
+ blk_inc_in_flight(blk);
132
+ acb = blk_aio_get(&blk_aio_em_aiocb_info, blk, cb, opaque);
133
+ acb->rwco = (BlkRwCo) {
134
+ .blk = blk,
135
+ .ret = NOT_DONE,
136
+ .flags = flags,
137
+ .iobuf = qiov,
138
+ };
139
+ acb->bytes = (int64_t)offset;
140
+ acb->has_returned = false;
141
+
142
+ co = qemu_coroutine_create(blk_aio_zone_append_entry, acb);
143
+ aio_co_enter(blk_get_aio_context(blk), co);
144
+ acb->has_returned = true;
145
+ if (acb->rwco.ret != NOT_DONE) {
146
+ replay_bh_schedule_oneshot_event(blk_get_aio_context(blk),
147
+ blk_aio_complete_bh, acb);
148
+ }
149
+
150
+ return &acb->common;
151
+}
152
+
153
/*
154
* Send a zone_report command.
155
* offset is a byte offset from the start of the device. No alignment
156
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_zone_mgmt(BlockBackend *blk, BlockZoneOp op,
32
return ret;
157
return ret;
33
}
158
}
34
159
35
+/* Not for empty child */
160
+/*
36
+int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
161
+ * Send a zone_append command.
37
+ Error **errp)
162
+ */
163
+int coroutine_fn blk_co_zone_append(BlockBackend *blk, int64_t *offset,
164
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
38
+{
165
+{
39
+ int ret;
166
+ int ret;
40
+ Transaction *tran = tran_new();
167
+ IO_CODE();
41
+ g_autoptr(GHashTable) found = NULL;
168
+
42
+ g_autoptr(GSList) refresh_list = NULL;
169
+ blk_inc_in_flight(blk);
43
+ BlockDriverState *old_bs = child->bs;
170
+ blk_wait_while_drained(blk);
44
+
171
+ if (!blk_is_available(blk)) {
45
+ bdrv_ref(old_bs);
172
+ blk_dec_in_flight(blk);
46
+ bdrv_drained_begin(old_bs);
173
+ return -ENOMEDIUM;
47
+ bdrv_drained_begin(new_bs);
174
+ }
48
+
175
+
49
+ bdrv_replace_child_tran(child, new_bs, tran);
176
+ ret = bdrv_co_zone_append(blk_bs(blk), offset, qiov, flags);
50
+
177
+ blk_dec_in_flight(blk);
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;
178
+ return ret;
64
+}
179
+}
65
+
180
+
66
static void bdrv_delete(BlockDriverState *bs)
181
void blk_drain(BlockBackend *blk)
67
{
182
{
68
assert(bdrv_op_blocker_is_empty(bs));
183
BlockDriverState *bs = blk_bs(blk);
184
diff --git a/block/file-posix.c b/block/file-posix.c
185
index XXXXXXX..XXXXXXX 100644
186
--- a/block/file-posix.c
187
+++ b/block/file-posix.c
188
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVRawState {
189
bool has_write_zeroes:1;
190
bool use_linux_aio:1;
191
bool use_linux_io_uring:1;
192
+ int64_t *offset; /* offset of zone append operation */
193
int page_cache_inconsistent; /* errno from fdatasync failure */
194
bool has_fallocate;
195
bool needs_alignment;
196
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
197
ssize_t len;
198
199
len = RETRY_ON_EINTR(
200
- (aiocb->aio_type & QEMU_AIO_WRITE) ?
201
+ (aiocb->aio_type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) ?
202
qemu_pwritev(aiocb->aio_fildes,
203
aiocb->io.iov,
204
aiocb->io.niov,
205
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
206
ssize_t len;
207
208
while (offset < aiocb->aio_nbytes) {
209
- if (aiocb->aio_type & QEMU_AIO_WRITE) {
210
+ if (aiocb->aio_type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) {
211
len = pwrite(aiocb->aio_fildes,
212
(const char *)buf + offset,
213
aiocb->aio_nbytes - offset,
214
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_rw(void *opaque)
215
}
216
217
nbytes = handle_aiocb_rw_linear(aiocb, buf);
218
- if (!(aiocb->aio_type & QEMU_AIO_WRITE)) {
219
+ if (!(aiocb->aio_type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND))) {
220
char *p = buf;
221
size_t count = aiocb->aio_nbytes, copy;
222
int i;
223
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
224
if (fd_open(bs) < 0)
225
return -EIO;
226
#if defined(CONFIG_BLKZONED)
227
- if (type & QEMU_AIO_WRITE && bs->wps) {
228
+ if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && bs->wps) {
229
qemu_co_mutex_lock(&bs->wps->colock);
230
+ if (type & QEMU_AIO_ZONE_APPEND && bs->bl.zone_size) {
231
+ int index = offset / bs->bl.zone_size;
232
+ offset = bs->wps->wp[index];
233
+ }
234
}
235
#endif
236
237
@@ -XXX,XX +XXX,XX @@ out:
238
#if defined(CONFIG_BLKZONED)
239
BlockZoneWps *wps = bs->wps;
240
if (ret == 0) {
241
- if (type & QEMU_AIO_WRITE && wps && bs->bl.zone_size) {
242
+ if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND))
243
+ && wps && bs->bl.zone_size) {
244
uint64_t *wp = &wps->wp[offset / bs->bl.zone_size];
245
if (!BDRV_ZT_IS_CONV(*wp)) {
246
+ if (type & QEMU_AIO_ZONE_APPEND) {
247
+ *s->offset = *wp;
248
+ }
249
/* Advance the wp if needed */
250
if (offset + bytes > *wp) {
251
*wp = offset + bytes;
252
@@ -XXX,XX +XXX,XX @@ out:
253
}
254
}
255
} else {
256
- if (type & QEMU_AIO_WRITE) {
257
+ if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) {
258
update_zones_wp(bs, s->fd, 0, 1);
259
}
260
}
261
262
- if (type & QEMU_AIO_WRITE && wps) {
263
+ if ((type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) && wps) {
264
qemu_co_mutex_unlock(&wps->colock);
265
}
266
#endif
267
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
268
}
269
#endif
270
271
+#if defined(CONFIG_BLKZONED)
272
+static int coroutine_fn raw_co_zone_append(BlockDriverState *bs,
273
+ int64_t *offset,
274
+ QEMUIOVector *qiov,
275
+ BdrvRequestFlags flags) {
276
+ assert(flags == 0);
277
+ int64_t zone_size_mask = bs->bl.zone_size - 1;
278
+ int64_t iov_len = 0;
279
+ int64_t len = 0;
280
+ BDRVRawState *s = bs->opaque;
281
+ s->offset = offset;
282
+
283
+ if (*offset & zone_size_mask) {
284
+ error_report("sector offset %" PRId64 " is not aligned to zone size "
285
+ "%" PRId32 "", *offset / 512, bs->bl.zone_size / 512);
286
+ return -EINVAL;
287
+ }
288
+
289
+ int64_t wg = bs->bl.write_granularity;
290
+ int64_t wg_mask = wg - 1;
291
+ for (int i = 0; i < qiov->niov; i++) {
292
+ iov_len = qiov->iov[i].iov_len;
293
+ if (iov_len & wg_mask) {
294
+ error_report("len of IOVector[%d] %" PRId64 " is not aligned to "
295
+ "block size %" PRId64 "", i, iov_len, wg);
296
+ return -EINVAL;
297
+ }
298
+ len += iov_len;
299
+ }
300
+
301
+ return raw_co_prw(bs, *offset, len, qiov, QEMU_AIO_ZONE_APPEND);
302
+}
303
+#endif
304
+
305
static coroutine_fn int
306
raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes,
307
bool blkdev)
308
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
309
/* zone management operations */
310
.bdrv_co_zone_report = raw_co_zone_report,
311
.bdrv_co_zone_mgmt = raw_co_zone_mgmt,
312
+ .bdrv_co_zone_append = raw_co_zone_append,
313
#endif
314
};
315
316
diff --git a/block/io.c b/block/io.c
317
index XXXXXXX..XXXXXXX 100644
318
--- a/block/io.c
319
+++ b/block/io.c
320
@@ -XXX,XX +XXX,XX @@ out:
321
return co.ret;
322
}
323
324
+int coroutine_fn bdrv_co_zone_append(BlockDriverState *bs, int64_t *offset,
325
+ QEMUIOVector *qiov,
326
+ BdrvRequestFlags flags)
327
+{
328
+ int ret;
329
+ BlockDriver *drv = bs->drv;
330
+ CoroutineIOCompletion co = {
331
+ .coroutine = qemu_coroutine_self(),
332
+ };
333
+ IO_CODE();
334
+
335
+ ret = bdrv_check_qiov_request(*offset, qiov->size, qiov, 0, NULL);
336
+ if (ret < 0) {
337
+ return ret;
338
+ }
339
+
340
+ bdrv_inc_in_flight(bs);
341
+ if (!drv || !drv->bdrv_co_zone_append || bs->bl.zoned == BLK_Z_NONE) {
342
+ co.ret = -ENOTSUP;
343
+ goto out;
344
+ }
345
+ co.ret = drv->bdrv_co_zone_append(bs, offset, qiov, flags);
346
+out:
347
+ bdrv_dec_in_flight(bs);
348
+ return co.ret;
349
+}
350
+
351
void *qemu_blockalign(BlockDriverState *bs, size_t size)
352
{
353
IO_CODE();
354
diff --git a/block/io_uring.c b/block/io_uring.c
355
index XXXXXXX..XXXXXXX 100644
356
--- a/block/io_uring.c
357
+++ b/block/io_uring.c
358
@@ -XXX,XX +XXX,XX @@ static int luring_do_submit(int fd, LuringAIOCB *luringcb, LuringState *s,
359
io_uring_prep_writev(sqes, fd, luringcb->qiov->iov,
360
luringcb->qiov->niov, offset);
361
break;
362
+ case QEMU_AIO_ZONE_APPEND:
363
+ io_uring_prep_writev(sqes, fd, luringcb->qiov->iov,
364
+ luringcb->qiov->niov, offset);
365
+ break;
366
case QEMU_AIO_READ:
367
io_uring_prep_readv(sqes, fd, luringcb->qiov->iov,
368
luringcb->qiov->niov, offset);
369
diff --git a/block/linux-aio.c b/block/linux-aio.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/block/linux-aio.c
372
+++ b/block/linux-aio.c
373
@@ -XXX,XX +XXX,XX @@ static int laio_do_submit(int fd, struct qemu_laiocb *laiocb, off_t offset,
374
case QEMU_AIO_WRITE:
375
io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset);
376
break;
377
+ case QEMU_AIO_ZONE_APPEND:
378
+ io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset);
379
+ break;
380
case QEMU_AIO_READ:
381
io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
382
break;
383
diff --git a/block/raw-format.c b/block/raw-format.c
384
index XXXXXXX..XXXXXXX 100644
385
--- a/block/raw-format.c
386
+++ b/block/raw-format.c
387
@@ -XXX,XX +XXX,XX @@ raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op,
388
return bdrv_co_zone_mgmt(bs->file->bs, op, offset, len);
389
}
390
391
+static int coroutine_fn GRAPH_RDLOCK
392
+raw_co_zone_append(BlockDriverState *bs,int64_t *offset, QEMUIOVector *qiov,
393
+ BdrvRequestFlags flags)
394
+{
395
+ return bdrv_co_zone_append(bs->file->bs, offset, qiov, flags);
396
+}
397
+
398
static int64_t coroutine_fn GRAPH_RDLOCK
399
raw_co_getlength(BlockDriverState *bs)
400
{
401
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_raw = {
402
.bdrv_co_pdiscard = &raw_co_pdiscard,
403
.bdrv_co_zone_report = &raw_co_zone_report,
404
.bdrv_co_zone_mgmt = &raw_co_zone_mgmt,
405
+ .bdrv_co_zone_append = &raw_co_zone_append,
406
.bdrv_co_block_status = &raw_co_block_status,
407
.bdrv_co_copy_range_from = &raw_co_copy_range_from,
408
.bdrv_co_copy_range_to = &raw_co_copy_range_to,
69
--
409
--
70
2.31.1
410
2.39.2
71
72
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
The main consumer of cluster-size is block-copy. Let's calculate it
3
The patch tests zone append writes by reporting the zone wp after
4
here instead of passing through backup-top.
4
the completion of the call. "zap -p" option can print the sector
5
offset value after completion, which should be the start sector
6
where the append write begins.
5
7
6
We are going to publish copy-before-write filter soon, so it will be
8
Signed-off-by: Sam Li <faithilikerun@gmail.com>
7
created through options. But we don't want for now to make explicit
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
option for cluster-size, let's continue to calculate it automatically.
10
Message-id: 20230407081657.17947-4-faithilikerun@gmail.com
9
So, now is the time to get rid of cluster_size argument for
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
bdrv_cbw_append().
12
---
13
qemu-io-cmds.c | 75 ++++++++++++++++++++++++++++++
14
tests/qemu-iotests/tests/zoned | 16 +++++++
15
tests/qemu-iotests/tests/zoned.out | 16 +++++++
16
3 files changed, 107 insertions(+)
11
17
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
18
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
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
19
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.h
20
--- a/qemu-io-cmds.c
28
+++ b/block/copy-before-write.h
21
+++ b/qemu-io-cmds.c
29
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static const cmdinfo_t zone_reset_cmd = {
30
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
23
.oneline = "reset a zone write pointer in zone block device",
31
BlockDriverState *target,
32
const char *filter_node_name,
33
- uint64_t cluster_size,
34
bool compress,
35
BlockCopyState **bcs,
36
Error **errp);
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block-copy.h
40
+++ b/include/block/block-copy.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyState BlockCopyState;
42
typedef struct BlockCopyCallState BlockCopyCallState;
43
44
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
45
- int64_t cluster_size, bool use_copy_range,
46
- bool compress, Error **errp);
47
+ bool use_copy_range, bool compress,
48
+ Error **errp);
49
50
/* Function should be called prior any actual copy request */
51
void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
52
@@ -XXX,XX +XXX,XX @@ void block_copy_kick(BlockCopyCallState *call_state);
53
void block_copy_call_cancel(BlockCopyCallState *call_state);
54
55
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
56
+int64_t block_copy_cluster_size(BlockCopyState *s);
57
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
58
59
#endif /* BLOCK_COPY_H */
60
diff --git a/block/backup.c b/block/backup.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/backup.c
63
+++ b/block/backup.c
64
@@ -XXX,XX +XXX,XX @@
65
66
#include "block/copy-before-write.h"
67
68
-#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
69
-
70
typedef struct BackupBlockJob {
71
BlockJob common;
72
BlockDriverState *cbw;
73
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver backup_job_driver = {
74
.set_speed = backup_set_speed,
75
};
24
};
76
25
77
-static int64_t backup_calculate_cluster_size(BlockDriverState *target,
26
+static int do_aio_zone_append(BlockBackend *blk, QEMUIOVector *qiov,
78
- Error **errp)
27
+ int64_t *offset, int flags, int *total)
79
-{
28
+{
80
- int ret;
29
+ int async_ret = NOT_DONE;
81
- BlockDriverInfo bdi;
82
- bool target_does_cow = bdrv_backing_chain_next(target);
83
-
84
- /*
85
- * If there is no backing file on the target, we cannot rely on COW if our
86
- * backup cluster size is smaller than the target cluster size. Even for
87
- * targets with a backing file, try to avoid COW if possible.
88
- */
89
- ret = bdrv_get_info(target, &bdi);
90
- if (ret == -ENOTSUP && !target_does_cow) {
91
- /* Cluster size is not defined */
92
- warn_report("The target block device doesn't provide "
93
- "information about the block size and it doesn't have a "
94
- "backing file. The default block size of %u bytes is "
95
- "used. If the actual block size of the target exceeds "
96
- "this default, the backup may be unusable",
97
- BACKUP_CLUSTER_SIZE_DEFAULT);
98
- return BACKUP_CLUSTER_SIZE_DEFAULT;
99
- } else if (ret < 0 && !target_does_cow) {
100
- error_setg_errno(errp, -ret,
101
- "Couldn't determine the cluster size of the target image, "
102
- "which has no backing file");
103
- error_append_hint(errp,
104
- "Aborting, since this may create an unusable destination image\n");
105
- return ret;
106
- } else if (ret < 0 && target_does_cow) {
107
- /* Not fatal; just trudge on ahead. */
108
- return BACKUP_CLUSTER_SIZE_DEFAULT;
109
- }
110
-
111
- return MAX(BACKUP_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
112
-}
113
-
114
BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
115
BlockDriverState *target, int64_t speed,
116
MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap,
117
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
118
return NULL;
119
}
120
121
- cluster_size = backup_calculate_cluster_size(target, errp);
122
- if (cluster_size < 0) {
123
- goto error;
124
- }
125
-
126
if (perf->max_workers < 1) {
127
error_setg(errp, "max-workers must be greater than zero");
128
return NULL;
129
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
130
return NULL;
131
}
132
133
- if (perf->max_chunk && perf->max_chunk < cluster_size) {
134
- error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
135
- "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
136
- return NULL;
137
- }
138
-
139
-
140
if (sync_bitmap) {
141
/* If we need to write to this bitmap, check that we can: */
142
if (bitmap_mode != BITMAP_SYNC_MODE_NEVER &&
143
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
144
goto error;
145
}
146
147
- cbw = bdrv_cbw_append(bs, target, filter_node_name,
148
- cluster_size, false, &bcs, errp);
149
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
150
if (!cbw) {
151
goto error;
152
}
153
154
+ cluster_size = block_copy_cluster_size(bcs);
155
+
30
+
156
+ if (perf->max_chunk && perf->max_chunk < cluster_size) {
31
+ blk_aio_zone_append(blk, offset, qiov, flags, aio_rw_done, &async_ret);
157
+ error_setg(errp, "Required max-chunk (%" PRIi64 ") is less than backup "
32
+ while (async_ret == NOT_DONE) {
158
+ "cluster size (%" PRIi64 ")", perf->max_chunk, cluster_size);
33
+ main_loop_wait(false);
159
+ goto error;
160
+ }
34
+ }
161
+
35
+
162
/* job->len is fixed, so we can't allow resize */
36
+ *total = qiov->size;
163
job = block_job_create(job_id, &backup_job_driver, txn, cbw,
37
+ return async_ret < 0 ? async_ret : 1;
164
0, BLK_PERM_ALL,
38
+}
165
diff --git a/block/block-copy.c b/block/block-copy.c
39
+
166
index XXXXXXX..XXXXXXX 100644
40
+static int zone_append_f(BlockBackend *blk, int argc, char **argv)
167
--- a/block/block-copy.c
168
+++ b/block/block-copy.c
169
@@ -XXX,XX +XXX,XX @@
170
#include "qemu/units.h"
171
#include "qemu/coroutine.h"
172
#include "block/aio_task.h"
173
+#include "qemu/error-report.h"
174
175
#define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB)
176
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
177
#define BLOCK_COPY_MAX_MEM (128 * MiB)
178
#define BLOCK_COPY_MAX_WORKERS 64
179
#define BLOCK_COPY_SLICE_TIME 100000000ULL /* ns */
180
+#define BLOCK_COPY_CLUSTER_SIZE_DEFAULT (1 << 16)
181
182
typedef enum {
183
COPY_READ_WRITE_CLUSTER,
184
@@ -XXX,XX +XXX,XX @@ void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
185
}
186
}
187
188
+static int64_t block_copy_calculate_cluster_size(BlockDriverState *target,
189
+ Error **errp)
190
+{
41
+{
191
+ int ret;
42
+ int ret;
192
+ BlockDriverInfo bdi;
43
+ bool pflag = false;
193
+ bool target_does_cow = bdrv_backing_chain_next(target);
44
+ int flags = 0;
45
+ int total = 0;
46
+ int64_t offset;
47
+ char *buf;
48
+ int c, nr_iov;
49
+ int pattern = 0xcd;
50
+ QEMUIOVector qiov;
194
+
51
+
195
+ /*
52
+ if (optind > argc - 3) {
196
+ * If there is no backing file on the target, we cannot rely on COW if our
53
+ return -EINVAL;
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
+ }
54
+ }
221
+
55
+
222
+ return MAX(BLOCK_COPY_CLUSTER_SIZE_DEFAULT, bdi.cluster_size);
56
+ if ((c = getopt(argc, argv, "p")) != -1) {
57
+ pflag = true;
58
+ }
59
+
60
+ offset = cvtnum(argv[optind]);
61
+ if (offset < 0) {
62
+ print_cvtnum_err(offset, argv[optind]);
63
+ return offset;
64
+ }
65
+ optind++;
66
+ nr_iov = argc - optind;
67
+ buf = create_iovec(blk, &qiov, &argv[optind], nr_iov, pattern,
68
+ flags & BDRV_REQ_REGISTERED_BUF);
69
+ if (buf == NULL) {
70
+ return -EINVAL;
71
+ }
72
+ ret = do_aio_zone_append(blk, &qiov, &offset, flags, &total);
73
+ if (ret < 0) {
74
+ printf("zone append failed: %s\n", strerror(-ret));
75
+ goto out;
76
+ }
77
+
78
+ if (pflag) {
79
+ printf("After zap done, the append sector is 0x%" PRIx64 "\n",
80
+ tosector(offset));
81
+ }
82
+
83
+out:
84
+ qemu_io_free(blk, buf, qiov.size,
85
+ flags & BDRV_REQ_REGISTERED_BUF);
86
+ qemu_iovec_destroy(&qiov);
87
+ return ret;
223
+}
88
+}
224
+
89
+
225
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
90
+static const cmdinfo_t zone_append_cmd = {
226
- int64_t cluster_size, bool use_copy_range,
91
+ .name = "zone_append",
227
+ bool use_copy_range,
92
+ .altname = "zap",
228
bool compress, Error **errp)
93
+ .cfunc = zone_append_f,
229
{
94
+ .argmin = 3,
230
BlockCopyState *s;
95
+ .argmax = 4,
231
+ int64_t cluster_size;
96
+ .args = "offset len [len..]",
232
BdrvDirtyBitmap *copy_bitmap;
97
+ .oneline = "append write a number of bytes at a specified offset",
233
bool is_fleecing;
98
+};
234
235
+ cluster_size = block_copy_calculate_cluster_size(target->bs, errp);
236
+ if (cluster_size < 0) {
237
+ return NULL;
238
+ }
239
+
99
+
240
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
100
static int truncate_f(BlockBackend *blk, int argc, char **argv);
241
errp);
101
static const cmdinfo_t truncate_cmd = {
242
if (!copy_bitmap) {
102
.name = "truncate",
243
@@ -XXX,XX +XXX,XX @@ BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s)
103
@@ -XXX,XX +XXX,XX @@ static void __attribute((constructor)) init_qemuio_commands(void)
244
return s->copy_bitmap;
104
qemuio_add_command(&zone_close_cmd);
245
}
105
qemuio_add_command(&zone_finish_cmd);
246
106
qemuio_add_command(&zone_reset_cmd);
247
+int64_t block_copy_cluster_size(BlockCopyState *s)
107
+ qemuio_add_command(&zone_append_cmd);
248
+{
108
qemuio_add_command(&truncate_cmd);
249
+ return s->cluster_size;
109
qemuio_add_command(&length_cmd);
250
+}
110
qemuio_add_command(&info_cmd);
111
diff --git a/tests/qemu-iotests/tests/zoned b/tests/qemu-iotests/tests/zoned
112
index XXXXXXX..XXXXXXX 100755
113
--- a/tests/qemu-iotests/tests/zoned
114
+++ b/tests/qemu-iotests/tests/zoned
115
@@ -XXX,XX +XXX,XX @@ echo "(5) resetting the second zone"
116
$QEMU_IO $IMG -c "zrs 268435456 268435456"
117
echo "After resetting a zone:"
118
$QEMU_IO $IMG -c "zrp 268435456 1"
119
+echo
120
+echo
121
+echo "(6) append write" # the physical block size of the device is 4096
122
+$QEMU_IO $IMG -c "zrp 0 1"
123
+$QEMU_IO $IMG -c "zap -p 0 0x1000 0x2000"
124
+echo "After appending the first zone firstly:"
125
+$QEMU_IO $IMG -c "zrp 0 1"
126
+$QEMU_IO $IMG -c "zap -p 0 0x1000 0x2000"
127
+echo "After appending the first zone secondly:"
128
+$QEMU_IO $IMG -c "zrp 0 1"
129
+$QEMU_IO $IMG -c "zap -p 268435456 0x1000 0x2000"
130
+echo "After appending the second zone firstly:"
131
+$QEMU_IO $IMG -c "zrp 268435456 1"
132
+$QEMU_IO $IMG -c "zap -p 268435456 0x1000 0x2000"
133
+echo "After appending the second zone secondly:"
134
+$QEMU_IO $IMG -c "zrp 268435456 1"
135
136
# success, all done
137
echo "*** done"
138
diff --git a/tests/qemu-iotests/tests/zoned.out b/tests/qemu-iotests/tests/zoned.out
139
index XXXXXXX..XXXXXXX 100644
140
--- a/tests/qemu-iotests/tests/zoned.out
141
+++ b/tests/qemu-iotests/tests/zoned.out
142
@@ -XXX,XX +XXX,XX @@ start: 0x80000, len 0x80000, cap 0x80000, wptr 0x100000, zcond:14, [type: 2]
143
(5) resetting the second zone
144
After resetting a zone:
145
start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80000, zcond:1, [type: 2]
251
+
146
+
252
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip)
147
+
253
{
148
+(6) append write
254
qatomic_set(&s->skip_unallocated, skip);
149
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x0, zcond:1, [type: 2]
255
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
150
+After zap done, the append sector is 0x0
256
index XXXXXXX..XXXXXXX 100644
151
+After appending the first zone firstly:
257
--- a/block/copy-before-write.c
152
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x18, zcond:2, [type: 2]
258
+++ b/block/copy-before-write.c
153
+After zap done, the append sector is 0x18
259
@@ -XXX,XX +XXX,XX @@
154
+After appending the first zone secondly:
260
typedef struct BDRVCopyBeforeWriteState {
155
+start: 0x0, len 0x80000, cap 0x80000, wptr 0x30, zcond:2, [type: 2]
261
BlockCopyState *bcs;
156
+After zap done, the append sector is 0x80000
262
BdrvChild *target;
157
+After appending the second zone firstly:
263
- int64_t cluster_size;
158
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80018, zcond:2, [type: 2]
264
} BDRVCopyBeforeWriteState;
159
+After zap done, the append sector is 0x80018
265
160
+After appending the second zone secondly:
266
static coroutine_fn int cbw_co_preadv(
161
+start: 0x80000, len 0x80000, cap 0x80000, wptr 0x80030, zcond:2, [type: 2]
267
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
162
*** done
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
--
163
--
304
2.31.1
164
2.39.2
305
306
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
We are going to publish copy-before-write filter to be used in separate
3
Signed-off-by: Sam Li <faithilikerun@gmail.com>
4
of backup. Future step would support bitmap for the filter. But let's
4
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
5
start from full set bitmap.
5
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Message-id: 20230407081657.17947-5-faithilikerun@gmail.com
7
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
9
block/file-posix.c | 3 +++
10
block/trace-events | 2 ++
11
2 files changed, 5 insertions(+)
6
12
7
We have to modify backup, as bitmap is first initialized by
13
diff --git a/block/file-posix.c b/block/file-posix.c
8
copy-before-write filter, and then backup modifies it.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20210824083856.17408-20-vsementsov@virtuozzo.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
15
block/backup.c | 16 +++++++---------
16
block/copy-before-write.c | 4 ++++
17
2 files changed, 11 insertions(+), 9 deletions(-)
18
19
diff --git a/block/backup.c b/block/backup.c
20
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
21
--- a/block/backup.c
15
--- a/block/file-posix.c
22
+++ b/block/backup.c
16
+++ b/block/file-posix.c
23
@@ -XXX,XX +XXX,XX @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
17
@@ -XXX,XX +XXX,XX @@ out:
24
BdrvDirtyBitmap *bcs_bitmap = block_copy_dirty_bitmap(job->bcs);
18
if (!BDRV_ZT_IS_CONV(*wp)) {
25
19
if (type & QEMU_AIO_ZONE_APPEND) {
26
if (job->sync_mode == MIRROR_SYNC_MODE_BITMAP) {
20
*s->offset = *wp;
27
+ bdrv_clear_dirty_bitmap(bcs_bitmap, NULL);
21
+ trace_zbd_zone_append_complete(bs, *s->offset
28
ret = bdrv_dirty_bitmap_merge_internal(bcs_bitmap, job->sync_bitmap,
22
+ >> BDRV_SECTOR_BITS);
29
NULL, true);
23
}
30
assert(ret);
24
/* Advance the wp if needed */
31
- } else {
25
if (offset + bytes > *wp) {
32
- if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
26
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_zone_append(BlockDriverState *bs,
33
- /*
27
len += iov_len;
34
- * We can't hog the coroutine to initialize this thoroughly.
35
- * Set a flag and resume work when we are able to yield safely.
36
- */
37
- block_copy_set_skip_unallocated(job->bcs, true);
38
- }
39
- bdrv_set_dirty_bitmap(bcs_bitmap, 0, job->len);
40
+ } else if (job->sync_mode == MIRROR_SYNC_MODE_TOP) {
41
+ /*
42
+ * We can't hog the coroutine to initialize this thoroughly.
43
+ * Set a flag and resume work when we are able to yield safely.
44
+ */
45
+ block_copy_set_skip_unallocated(job->bcs, true);
46
}
28
}
47
29
48
estimate = bdrv_get_dirty_count(bcs_bitmap);
30
+ trace_zbd_zone_append(bs, *offset >> BDRV_SECTOR_BITS);
49
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
31
return raw_co_prw(bs, *offset, len, qiov, QEMU_AIO_ZONE_APPEND);
32
}
33
#endif
34
diff --git a/block/trace-events b/block/trace-events
50
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
51
--- a/block/copy-before-write.c
36
--- a/block/trace-events
52
+++ b/block/copy-before-write.c
37
+++ b/block/trace-events
53
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
38
@@ -XXX,XX +XXX,XX @@ file_hdev_is_sg(int type, int version) "SG device found: type=%d, version=%d"
54
static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
39
file_flush_fdatasync_failed(int err) "errno %d"
55
{
40
zbd_zone_report(void *bs, unsigned int nr_zones, int64_t sector) "bs %p report %d zones starting at sector offset 0x%" PRIx64 ""
56
BDRVCopyBeforeWriteState *s = bs->opaque;
41
zbd_zone_mgmt(void *bs, const char *op_name, int64_t sector, int64_t len) "bs %p %s starts at sector offset 0x%" PRIx64 " over a range of 0x%" PRIx64 " sectors"
57
+ BdrvDirtyBitmap *copy_bitmap;
42
+zbd_zone_append(void *bs, int64_t sector) "bs %p append at sector offset 0x%" PRIx64 ""
58
43
+zbd_zone_append_complete(void *bs, int64_t sector) "bs %p returns append sector 0x%" PRIx64 ""
59
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
44
60
BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
45
# ssh.c
61
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
46
sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)"
62
return -EINVAL;
63
}
64
65
+ copy_bitmap = block_copy_dirty_bitmap(s->bcs);
66
+ bdrv_set_dirty_bitmap(copy_bitmap, 0, bdrv_dirty_bitmap_size(copy_bitmap));
67
+
68
return 0;
69
}
70
71
--
47
--
72
2.31.1
48
2.39.2
73
74
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Add function to change bs inside blk.
3
Use scripts/update-linux-headers.sh to update headers to 6.3-rc1.
4
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Sam Li <faithilikerun@gmail.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-Id: <20210824083856.17408-3-vsementsov@virtuozzo.com>
7
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
8
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
8
Message-id: 20230407082528.18841-2-faithilikerun@gmail.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
---
10
include/sysemu/block-backend.h | 1 +
11
include/standard-headers/drm/drm_fourcc.h | 12 +++
11
block/block-backend.c | 8 ++++++++
12
include/standard-headers/linux/ethtool.h | 48 ++++++++-
12
2 files changed, 9 insertions(+)
13
include/standard-headers/linux/fuse.h | 45 +++++++-
14
include/standard-headers/linux/pci_regs.h | 1 +
15
include/standard-headers/linux/vhost_types.h | 2 +
16
include/standard-headers/linux/virtio_blk.h | 105 +++++++++++++++++++
17
linux-headers/asm-arm64/kvm.h | 1 +
18
linux-headers/asm-x86/kvm.h | 34 +++++-
19
linux-headers/linux/kvm.h | 9 ++
20
linux-headers/linux/vfio.h | 15 +--
21
linux-headers/linux/vhost.h | 8 ++
22
11 files changed, 270 insertions(+), 10 deletions(-)
13
23
14
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
24
diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h
15
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
16
--- a/include/sysemu/block-backend.h
26
--- a/include/standard-headers/drm/drm_fourcc.h
17
+++ b/include/sysemu/block-backend.h
27
+++ b/include/standard-headers/drm/drm_fourcc.h
18
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public);
28
@@ -XXX,XX +XXX,XX @@ extern "C" {
19
BlockDriverState *blk_bs(BlockBackend *blk);
29
*
20
void blk_remove_bs(BlockBackend *blk);
30
* The authoritative list of format modifier codes is found in
21
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp);
31
* `include/uapi/drm/drm_fourcc.h`
22
+int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp);
32
+ *
23
bool bdrv_has_blk(BlockDriverState *bs);
33
+ * Open Source User Waiver
24
bool bdrv_is_root_node(BlockDriverState *bs);
34
+ * -----------------------
25
int blk_set_perm(BlockBackend *blk, uint64_t perm, uint64_t shared_perm,
35
+ *
26
diff --git a/block/block-backend.c b/block/block-backend.c
36
+ * Because this is the authoritative source for pixel formats and modifiers
27
index XXXXXXX..XXXXXXX 100644
37
+ * referenced by GL, Vulkan extensions and other standards and hence used both
28
--- a/block/block-backend.c
38
+ * by open source and closed source driver stacks, the usual requirement for an
29
+++ b/block/block-backend.c
39
+ * upstream in-kernel or open source userspace user does not apply.
30
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
40
+ *
31
return 0;
41
+ * To ensure, as much as feasible, compatibility across stacks and avoid
32
}
42
+ * confusion with incompatible enumerations stakeholders for all relevant driver
43
+ * stacks should approve additions.
44
*/
45
46
#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
47
diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h
48
index XXXXXXX..XXXXXXX 100644
49
--- a/include/standard-headers/linux/ethtool.h
50
+++ b/include/standard-headers/linux/ethtool.h
51
@@ -XXX,XX +XXX,XX @@ enum ethtool_stringset {
52
    ETH_SS_COUNT
53
};
54
55
+/**
56
+ * enum ethtool_mac_stats_src - source of ethtool MAC statistics
57
+ * @ETHTOOL_MAC_STATS_SRC_AGGREGATE:
58
+ *    if device supports a MAC merge layer, this retrieves the aggregate
59
+ *    statistics of the eMAC and pMAC. Otherwise, it retrieves just the
60
+ *    statistics of the single (express) MAC.
61
+ * @ETHTOOL_MAC_STATS_SRC_EMAC:
62
+ *    if device supports a MM layer, this retrieves the eMAC statistics.
63
+ *    Otherwise, it retrieves the statistics of the single (express) MAC.
64
+ * @ETHTOOL_MAC_STATS_SRC_PMAC:
65
+ *    if device supports a MM layer, this retrieves the pMAC statistics.
66
+ */
67
+enum ethtool_mac_stats_src {
68
+    ETHTOOL_MAC_STATS_SRC_AGGREGATE,
69
+    ETHTOOL_MAC_STATS_SRC_EMAC,
70
+    ETHTOOL_MAC_STATS_SRC_PMAC,
71
+};
72
+
73
/**
74
* enum ethtool_module_power_mode_policy - plug-in module power mode policy
75
* @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode.
76
@@ -XXX,XX +XXX,XX @@ enum ethtool_podl_pse_pw_d_status {
77
    ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR,
78
};
79
80
+/**
81
+ * enum ethtool_mm_verify_status - status of MAC Merge Verify function
82
+ * @ETHTOOL_MM_VERIFY_STATUS_UNKNOWN:
83
+ *    verification status is unknown
84
+ * @ETHTOOL_MM_VERIFY_STATUS_INITIAL:
85
+ *    the 802.3 Verify State diagram is in the state INIT_VERIFICATION
86
+ * @ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
87
+ *    the Verify State diagram is in the state VERIFICATION_IDLE,
88
+ *    SEND_VERIFY or WAIT_FOR_RESPONSE
89
+ * @ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
90
+ *    indicates that the Verify State diagram is in the state VERIFIED
91
+ * @ETHTOOL_MM_VERIFY_STATUS_FAILED:
92
+ *    the Verify State diagram is in the state VERIFY_FAIL
93
+ * @ETHTOOL_MM_VERIFY_STATUS_DISABLED:
94
+ *    verification of preemption operation is disabled
95
+ */
96
+enum ethtool_mm_verify_status {
97
+    ETHTOOL_MM_VERIFY_STATUS_UNKNOWN,
98
+    ETHTOOL_MM_VERIFY_STATUS_INITIAL,
99
+    ETHTOOL_MM_VERIFY_STATUS_VERIFYING,
100
+    ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED,
101
+    ETHTOOL_MM_VERIFY_STATUS_FAILED,
102
+    ETHTOOL_MM_VERIFY_STATUS_DISABLED,
103
+};
104
+
105
/**
106
* struct ethtool_gstrings - string set for data tagging
107
* @cmd: Command number = %ETHTOOL_GSTRINGS
108
@@ -XXX,XX +XXX,XX @@ struct ethtool_rxnfc {
109
        uint32_t            rule_cnt;
110
        uint32_t            rss_context;
111
    };
112
-    uint32_t                rule_locs[0];
113
+    uint32_t                rule_locs[];
114
};
115
116
117
@@ -XXX,XX +XXX,XX @@ enum ethtool_link_mode_bit_indices {
118
    ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT     = 96,
119
    ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT     = 97,
120
    ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT     = 98,
121
+    ETHTOOL_LINK_MODE_10baseT1S_Full_BIT         = 99,
122
+    ETHTOOL_LINK_MODE_10baseT1S_Half_BIT         = 100,
123
+    ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT     = 101,
124
125
    /* must be last entry */
126
    __ETHTOOL_LINK_MODE_MASK_NBITS
127
diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
128
index XXXXXXX..XXXXXXX 100644
129
--- a/include/standard-headers/linux/fuse.h
130
+++ b/include/standard-headers/linux/fuse.h
131
@@ -XXX,XX +XXX,XX @@
132
* 7.38
133
* - add FUSE_EXPIRE_ONLY flag to fuse_notify_inval_entry
134
* - add FOPEN_PARALLEL_DIRECT_WRITES
135
+ * - add total_extlen to fuse_in_header
136
+ * - add FUSE_MAX_NR_SECCTX
137
+ * - add extension header
138
+ * - add FUSE_EXT_GROUPS
139
+ * - add FUSE_CREATE_SUPP_GROUP
140
*/
141
142
#ifndef _LINUX_FUSE_H
143
@@ -XXX,XX +XXX,XX @@ struct fuse_file_lock {
144
* FUSE_SECURITY_CTX:    add security context to create, mkdir, symlink, and
145
*            mknod
146
* FUSE_HAS_INODE_DAX: use per inode DAX
147
+ * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
148
+ *            symlink and mknod (single group that matches parent)
149
*/
150
#define FUSE_ASYNC_READ        (1 << 0)
151
#define FUSE_POSIX_LOCKS    (1 << 1)
152
@@ -XXX,XX +XXX,XX @@ struct fuse_file_lock {
153
/* bits 32..63 get shifted down 32 bits into the flags2 field */
154
#define FUSE_SECURITY_CTX    (1ULL << 32)
155
#define FUSE_HAS_INODE_DAX    (1ULL << 33)
156
+#define FUSE_CREATE_SUPP_GROUP    (1ULL << 34)
157
158
/**
159
* CUSE INIT request/reply flags
160
@@ -XXX,XX +XXX,XX @@ struct fuse_file_lock {
161
*/
162
#define FUSE_EXPIRE_ONLY        (1 << 0)
163
164
+/**
165
+ * extension type
166
+ * FUSE_MAX_NR_SECCTX: maximum value of &fuse_secctx_header.nr_secctx
167
+ * FUSE_EXT_GROUPS: &fuse_supp_groups extension
168
+ */
169
+enum fuse_ext_type {
170
+    /* Types 0..31 are reserved for fuse_secctx_header */
171
+    FUSE_MAX_NR_SECCTX    = 31,
172
+    FUSE_EXT_GROUPS        = 32,
173
+};
174
+
175
enum fuse_opcode {
176
    FUSE_LOOKUP        = 1,
177
    FUSE_FORGET        = 2, /* no reply */
178
@@ -XXX,XX +XXX,XX @@ struct fuse_in_header {
179
    uint32_t    uid;
180
    uint32_t    gid;
181
    uint32_t    pid;
182
-    uint32_t    padding;
183
+    uint16_t    total_extlen; /* length of extensions in 8byte units */
184
+    uint16_t    padding;
185
};
186
187
struct fuse_out_header {
188
@@ -XXX,XX +XXX,XX @@ struct fuse_secctx_header {
189
    uint32_t    nr_secctx;
190
};
191
192
+/**
193
+ * struct fuse_ext_header - extension header
194
+ * @size: total size of this extension including this header
195
+ * @type: type of extension
196
+ *
197
+ * This is made compatible with fuse_secctx_header by using type values >
198
+ * FUSE_MAX_NR_SECCTX
199
+ */
200
+struct fuse_ext_header {
201
+    uint32_t    size;
202
+    uint32_t    type;
203
+};
204
+
205
+/**
206
+ * struct fuse_supp_groups - Supplementary group extension
207
+ * @nr_groups: number of supplementary groups
208
+ * @groups: flexible array of group IDs
209
+ */
210
+struct fuse_supp_groups {
211
+    uint32_t    nr_groups;
212
+    uint32_t    groups[];
213
+};
214
+
215
#endif /* _LINUX_FUSE_H */
216
diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h
217
index XXXXXXX..XXXXXXX 100644
218
--- a/include/standard-headers/linux/pci_regs.h
219
+++ b/include/standard-headers/linux/pci_regs.h
220
@@ -XXX,XX +XXX,XX @@
221
#define PCI_EXP_LNKCTL2_TX_MARGIN    0x0380 /* Transmit Margin */
222
#define PCI_EXP_LNKCTL2_HASD        0x0020 /* HW Autonomous Speed Disable */
223
#define PCI_EXP_LNKSTA2        0x32    /* Link Status 2 */
224
+#define PCI_EXP_LNKSTA2_FLIT        0x0400 /* Flit Mode Status */
225
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2    0x32    /* end of v2 EPs w/ link */
226
#define PCI_EXP_SLTCAP2        0x34    /* Slot Capabilities 2 */
227
#define PCI_EXP_SLTCAP2_IBPD    0x00000001 /* In-band PD Disable Supported */
228
diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h
229
index XXXXXXX..XXXXXXX 100644
230
--- a/include/standard-headers/linux/vhost_types.h
231
+++ b/include/standard-headers/linux/vhost_types.h
232
@@ -XXX,XX +XXX,XX @@ struct vhost_vdpa_iova_range {
233
#define VHOST_BACKEND_F_IOTLB_ASID 0x3
234
/* Device can be suspended */
235
#define VHOST_BACKEND_F_SUSPEND 0x4
236
+/* Device can be resumed */
237
+#define VHOST_BACKEND_F_RESUME 0x5
238
239
#endif
240
diff --git a/include/standard-headers/linux/virtio_blk.h b/include/standard-headers/linux/virtio_blk.h
241
index XXXXXXX..XXXXXXX 100644
242
--- a/include/standard-headers/linux/virtio_blk.h
243
+++ b/include/standard-headers/linux/virtio_blk.h
244
@@ -XXX,XX +XXX,XX @@
245
#define VIRTIO_BLK_F_DISCARD    13    /* DISCARD is supported */
246
#define VIRTIO_BLK_F_WRITE_ZEROES    14    /* WRITE ZEROES is supported */
247
#define VIRTIO_BLK_F_SECURE_ERASE    16 /* Secure Erase is supported */
248
+#define VIRTIO_BLK_F_ZONED        17    /* Zoned block device */
249
250
/* Legacy feature bits */
251
#ifndef VIRTIO_BLK_NO_LEGACY
252
@@ -XXX,XX +XXX,XX @@ struct virtio_blk_config {
253
    /* Secure erase commands must be aligned to this number of sectors. */
254
    __virtio32 secure_erase_sector_alignment;
255
256
+    /* Zoned block device characteristics (if VIRTIO_BLK_F_ZONED) */
257
+    struct virtio_blk_zoned_characteristics {
258
+        uint32_t zone_sectors;
259
+        uint32_t max_open_zones;
260
+        uint32_t max_active_zones;
261
+        uint32_t max_append_sectors;
262
+        uint32_t write_granularity;
263
+        uint8_t model;
264
+        uint8_t unused2[3];
265
+    } zoned;
266
} QEMU_PACKED;
267
268
/*
269
@@ -XXX,XX +XXX,XX @@ struct virtio_blk_config {
270
/* Secure erase command */
271
#define VIRTIO_BLK_T_SECURE_ERASE    14
272
273
+/* Zone append command */
274
+#define VIRTIO_BLK_T_ZONE_APPEND 15
275
+
276
+/* Report zones command */
277
+#define VIRTIO_BLK_T_ZONE_REPORT 16
278
+
279
+/* Open zone command */
280
+#define VIRTIO_BLK_T_ZONE_OPEN 18
281
+
282
+/* Close zone command */
283
+#define VIRTIO_BLK_T_ZONE_CLOSE 20
284
+
285
+/* Finish zone command */
286
+#define VIRTIO_BLK_T_ZONE_FINISH 22
287
+
288
+/* Reset zone command */
289
+#define VIRTIO_BLK_T_ZONE_RESET 24
290
+
291
+/* Reset All zones command */
292
+#define VIRTIO_BLK_T_ZONE_RESET_ALL 26
293
+
294
#ifndef VIRTIO_BLK_NO_LEGACY
295
/* Barrier before this op. */
296
#define VIRTIO_BLK_T_BARRIER    0x80000000
297
@@ -XXX,XX +XXX,XX @@ struct virtio_blk_outhdr {
298
    __virtio64 sector;
299
};
33
300
34
+/*
301
+/*
35
+ * Change BlockDriverState associated with @blk.
302
+ * Supported zoned device models.
36
+ */
303
+ */
37
+int blk_replace_bs(BlockBackend *blk, BlockDriverState *new_bs, Error **errp)
304
+
38
+{
305
+/* Regular block device */
39
+ return bdrv_replace_child_bs(blk->root, new_bs, errp);
306
+#define VIRTIO_BLK_Z_NONE 0
40
+}
307
+/* Host-managed zoned device */
41
+
308
+#define VIRTIO_BLK_Z_HM 1
309
+/* Host-aware zoned device */
310
+#define VIRTIO_BLK_Z_HA 2
311
+
312
+/*
313
+ * Zone descriptor. A part of VIRTIO_BLK_T_ZONE_REPORT command reply.
314
+ */
315
+struct virtio_blk_zone_descriptor {
316
+    /* Zone capacity */
317
+    uint64_t z_cap;
318
+    /* The starting sector of the zone */
319
+    uint64_t z_start;
320
+    /* Zone write pointer position in sectors */
321
+    uint64_t z_wp;
322
+    /* Zone type */
323
+    uint8_t z_type;
324
+    /* Zone state */
325
+    uint8_t z_state;
326
+    uint8_t reserved[38];
327
+};
328
+
329
+struct virtio_blk_zone_report {
330
+    uint64_t nr_zones;
331
+    uint8_t reserved[56];
332
+    struct virtio_blk_zone_descriptor zones[];
333
+};
334
+
335
+/*
336
+ * Supported zone types.
337
+ */
338
+
339
+/* Conventional zone */
340
+#define VIRTIO_BLK_ZT_CONV 1
341
+/* Sequential Write Required zone */
342
+#define VIRTIO_BLK_ZT_SWR 2
343
+/* Sequential Write Preferred zone */
344
+#define VIRTIO_BLK_ZT_SWP 3
345
+
346
+/*
347
+ * Zone states that are available for zones of all types.
348
+ */
349
+
350
+/* Not a write pointer (conventional zones only) */
351
+#define VIRTIO_BLK_ZS_NOT_WP 0
352
+/* Empty */
353
+#define VIRTIO_BLK_ZS_EMPTY 1
354
+/* Implicitly Open */
355
+#define VIRTIO_BLK_ZS_IOPEN 2
356
+/* Explicitly Open */
357
+#define VIRTIO_BLK_ZS_EOPEN 3
358
+/* Closed */
359
+#define VIRTIO_BLK_ZS_CLOSED 4
360
+/* Read-Only */
361
+#define VIRTIO_BLK_ZS_RDONLY 13
362
+/* Full */
363
+#define VIRTIO_BLK_ZS_FULL 14
364
+/* Offline */
365
+#define VIRTIO_BLK_ZS_OFFLINE 15
366
+
367
/* Unmap this range (only valid for write zeroes command) */
368
#define VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP    0x00000001
369
370
@@ -XXX,XX +XXX,XX @@ struct virtio_scsi_inhdr {
371
#define VIRTIO_BLK_S_OK        0
372
#define VIRTIO_BLK_S_IOERR    1
373
#define VIRTIO_BLK_S_UNSUPP    2
374
+
375
+/* Error codes that are specific to zoned block devices */
376
+#define VIRTIO_BLK_S_ZONE_INVALID_CMD 3
377
+#define VIRTIO_BLK_S_ZONE_UNALIGNED_WP 4
378
+#define VIRTIO_BLK_S_ZONE_OPEN_RESOURCE 5
379
+#define VIRTIO_BLK_S_ZONE_ACTIVE_RESOURCE 6
380
+
381
#endif /* _LINUX_VIRTIO_BLK_H */
382
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
383
index XXXXXXX..XXXXXXX 100644
384
--- a/linux-headers/asm-arm64/kvm.h
385
+++ b/linux-headers/asm-arm64/kvm.h
386
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
387
#define KVM_ARM_VCPU_SVE        4 /* enable SVE for this CPU */
388
#define KVM_ARM_VCPU_PTRAUTH_ADDRESS    5 /* VCPU uses address authentication */
389
#define KVM_ARM_VCPU_PTRAUTH_GENERIC    6 /* VCPU uses generic authentication */
390
+#define KVM_ARM_VCPU_HAS_EL2        7 /* Support nested virtualization */
391
392
struct kvm_vcpu_init {
393
    __u32 target;
394
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
395
index XXXXXXX..XXXXXXX 100644
396
--- a/linux-headers/asm-x86/kvm.h
397
+++ b/linux-headers/asm-x86/kvm.h
398
@@ -XXX,XX +XXX,XX @@
399
400
#include <linux/types.h>
401
#include <linux/ioctl.h>
402
+#include <linux/stddef.h>
403
404
#define KVM_PIO_PAGE_OFFSET 1
405
#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
406
@@ -XXX,XX +XXX,XX @@ struct kvm_nested_state {
407
     * KVM_{GET,PUT}_NESTED_STATE ioctl values.
408
     */
409
    union {
410
-        struct kvm_vmx_nested_state_data vmx[0];
411
-        struct kvm_svm_nested_state_data svm[0];
412
+        __DECLARE_FLEX_ARRAY(struct kvm_vmx_nested_state_data, vmx);
413
+        __DECLARE_FLEX_ARRAY(struct kvm_svm_nested_state_data, svm);
414
    } data;
415
};
416
417
@@ -XXX,XX +XXX,XX @@ struct kvm_pmu_event_filter {
418
#define KVM_PMU_EVENT_ALLOW 0
419
#define KVM_PMU_EVENT_DENY 1
420
421
+#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS BIT(0)
422
+#define KVM_PMU_EVENT_FLAGS_VALID_MASK (KVM_PMU_EVENT_FLAG_MASKED_EVENTS)
423
+
424
+/*
425
+ * Masked event layout.
426
+ * Bits Description
427
+ * ---- -----------
428
+ * 7:0 event select (low bits)
429
+ * 15:8 umask match
430
+ * 31:16 unused
431
+ * 35:32 event select (high bits)
432
+ * 36:54 unused
433
+ * 55 exclude bit
434
+ * 63:56 umask mask
435
+ */
436
+
437
+#define KVM_PMU_ENCODE_MASKED_ENTRY(event_select, mask, match, exclude) \
438
+    (((event_select) & 0xFFULL) | (((event_select) & 0XF00ULL) << 24) | \
439
+    (((mask) & 0xFFULL) << 56) | \
440
+    (((match) & 0xFFULL) << 8) | \
441
+    ((__u64)(!!(exclude)) << 55))
442
+
443
+#define KVM_PMU_MASKED_ENTRY_EVENT_SELECT \
444
+    (GENMASK_ULL(7, 0) | GENMASK_ULL(35, 32))
445
+#define KVM_PMU_MASKED_ENTRY_UMASK_MASK        (GENMASK_ULL(63, 56))
446
+#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH    (GENMASK_ULL(15, 8))
447
+#define KVM_PMU_MASKED_ENTRY_EXCLUDE        (BIT_ULL(55))
448
+#define KVM_PMU_MASKED_ENTRY_UMASK_MASK_SHIFT    (56)
449
+
450
/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
451
#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */
452
#define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
453
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
454
index XXXXXXX..XXXXXXX 100644
455
--- a/linux-headers/linux/kvm.h
456
+++ b/linux-headers/linux/kvm.h
457
@@ -XXX,XX +XXX,XX @@ struct kvm_s390_mem_op {
458
        struct {
459
            __u8 ar;    /* the access register number */
460
            __u8 key;    /* access key, ignored if flag unset */
461
+            __u8 pad1[6];    /* ignored */
462
+            __u64 old_addr;    /* ignored if cmpxchg flag unset */
463
        };
464
        __u32 sida_offset; /* offset into the sida */
465
        __u8 reserved[32]; /* ignored */
466
@@ -XXX,XX +XXX,XX @@ struct kvm_s390_mem_op {
467
#define KVM_S390_MEMOP_SIDA_WRITE    3
468
#define KVM_S390_MEMOP_ABSOLUTE_READ    4
469
#define KVM_S390_MEMOP_ABSOLUTE_WRITE    5
470
+#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG    6
471
+
472
/* flags for kvm_s390_mem_op->flags */
473
#define KVM_S390_MEMOP_F_CHECK_ONLY        (1ULL << 0)
474
#define KVM_S390_MEMOP_F_INJECT_EXCEPTION    (1ULL << 1)
475
#define KVM_S390_MEMOP_F_SKEY_PROTECTION    (1ULL << 2)
476
477
+/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */
478
+#define KVM_S390_MEMOP_EXTENSION_CAP_BASE    (1 << 0)
479
+#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG    (1 << 1)
480
+
481
/* for KVM_INTERRUPT */
482
struct kvm_interrupt {
483
    /* in */
484
@@ -XXX,XX +XXX,XX @@ struct kvm_ppc_resize_hpt {
485
#define KVM_CAP_DIRTY_LOG_RING_ACQ_REL 223
486
#define KVM_CAP_S390_PROTECTED_ASYNC_DISABLE 224
487
#define KVM_CAP_DIRTY_LOG_RING_WITH_BITMAP 225
488
+#define KVM_CAP_PMU_EVENT_MASKED_EVENTS 226
489
490
#ifdef KVM_CAP_IRQ_ROUTING
491
492
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
493
index XXXXXXX..XXXXXXX 100644
494
--- a/linux-headers/linux/vfio.h
495
+++ b/linux-headers/linux/vfio.h
496
@@ -XXX,XX +XXX,XX @@
497
/* Supports VFIO_DMA_UNMAP_FLAG_ALL */
498
#define VFIO_UNMAP_ALL            9
499
500
-/* Supports the vaddr flag for DMA map and unmap */
501
+/*
502
+ * Supports the vaddr flag for DMA map and unmap. Not supported for mediated
503
+ * devices, so this capability is subject to change as groups are added or
504
+ * removed.
505
+ */
506
#define VFIO_UPDATE_VADDR        10
507
42
/*
508
/*
43
* Sets the permission bitmasks that the user of the BlockBackend needs.
509
@@ -XXX,XX +XXX,XX @@ struct vfio_iommu_type1_info_dma_avail {
510
* Map process virtual addresses to IO virtual addresses using the
511
* provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
512
*
513
- * If flags & VFIO_DMA_MAP_FLAG_VADDR, update the base vaddr for iova, and
514
- * unblock translation of host virtual addresses in the iova range. The vaddr
515
+ * If flags & VFIO_DMA_MAP_FLAG_VADDR, update the base vaddr for iova. The vaddr
516
* must have previously been invalidated with VFIO_DMA_UNMAP_FLAG_VADDR. To
517
* maintain memory consistency within the user application, the updated vaddr
518
* must address the same memory object as originally mapped. Failure to do so
519
@@ -XXX,XX +XXX,XX @@ struct vfio_bitmap {
520
* must be 0. This cannot be combined with the get-dirty-bitmap flag.
521
*
522
* If flags & VFIO_DMA_UNMAP_FLAG_VADDR, do not unmap, but invalidate host
523
- * virtual addresses in the iova range. Tasks that attempt to translate an
524
- * iova's vaddr will block. DMA to already-mapped pages continues. This
525
- * cannot be combined with the get-dirty-bitmap flag.
526
+ * virtual addresses in the iova range. DMA to already-mapped pages continues.
527
+ * Groups may not be added to the container while any addresses are invalid.
528
+ * This cannot be combined with the get-dirty-bitmap flag.
44
*/
529
*/
530
struct vfio_iommu_type1_dma_unmap {
531
    __u32    argsz;
532
diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h
533
index XXXXXXX..XXXXXXX 100644
534
--- a/linux-headers/linux/vhost.h
535
+++ b/linux-headers/linux/vhost.h
536
@@ -XXX,XX +XXX,XX @@
537
*/
538
#define VHOST_VDPA_SUSPEND        _IO(VHOST_VIRTIO, 0x7D)
539
540
+/* Resume a device so it can resume processing virtqueue requests
541
+ *
542
+ * After the return of this ioctl the device will have restored all the
543
+ * necessary states and it is fully operational to continue processing the
544
+ * virtqueue descriptors.
545
+ */
546
+#define VHOST_VDPA_RESUME        _IO(VHOST_VIRTIO, 0x7E)
547
+
548
#endif
45
--
549
--
46
2.31.1
550
2.39.2
47
48
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Add field, so property can declare support for setting the property
4
when device is realized. To be used in the following commit.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-4-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/hw/qdev-properties.h | 1 +
12
hw/core/qdev-properties.c | 6 +++---
13
2 files changed, 4 insertions(+), 3 deletions(-)
14
15
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/qdev-properties.h
18
+++ b/include/hw/qdev-properties.h
19
@@ -XXX,XX +XXX,XX @@ struct PropertyInfo {
20
const char *name;
21
const char *description;
22
const QEnumLookup *enum_table;
23
+ bool realized_set_allowed; /* allow setting property on realized device */
24
int (*print)(Object *obj, Property *prop, char *dest, size_t len);
25
void (*set_default_value)(ObjectProperty *op, const Property *prop);
26
ObjectProperty *(*create)(ObjectClass *oc, const char *name,
27
diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/core/qdev-properties.c
30
+++ b/hw/core/qdev-properties.c
31
@@ -XXX,XX +XXX,XX @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
32
33
/* returns: true if property is allowed to be set, false otherwise */
34
static bool qdev_prop_allow_set(Object *obj, const char *name,
35
- Error **errp)
36
+ const PropertyInfo *info, Error **errp)
37
{
38
DeviceState *dev = DEVICE(obj);
39
40
- if (dev->realized) {
41
+ if (dev->realized && !info->realized_set_allowed) {
42
qdev_prop_set_after_realize(dev, name, errp);
43
return false;
44
}
45
@@ -XXX,XX +XXX,XX @@ static void field_prop_set(Object *obj, Visitor *v, const char *name,
46
{
47
Property *prop = opaque;
48
49
- if (!qdev_prop_allow_set(obj, name, errp)) {
50
+ if (!qdev_prop_allow_set(obj, name, prop->info, errp)) {
51
return;
52
}
53
54
--
55
2.31.1
56
57
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to convert backup_top to full featured public filter,
4
which can be used in separate of backup job. Start from renaming from
5
"how it used" to "what it does".
6
7
While updating comments in 283 iotest, drop and rephrase also things
8
about ".active", as this field is now dropped, and filter doesn't have
9
"inactive" mode.
10
11
Note that this change may be considered as incompatible interface
12
change, as backup-top filter format name was visible through
13
query-block and query-named-block-nodes.
14
15
Still, consider the following reasoning:
16
17
1. backup-top was never documented, so if someone depends on format
18
name (for driver that can't be used other than it is automatically
19
inserted on backup job start), it's a kind of "undocumented feature
20
use". So I think we are free to change it.
21
22
2. There is a hope, that there is no such users: it's a lot more native
23
to give a good node-name to backup-top filter if need to operate
24
with it somehow, and don't touch format name.
25
26
3. Another "incompatible" change in further commit would be moving
27
copy-before-write filter from using backing child to file child. And
28
this is even more reasonable than renaming: for now all public
29
filters are file-child based.
30
31
So, it's a risky change, but risk seems small and good interface worth
32
it.
33
34
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
35
Reviewed-by: Max Reitz <mreitz@redhat.com>
36
Message-Id: <20210824083856.17408-6-vsementsov@virtuozzo.com>
37
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
38
---
39
block/{backup-top.h => copy-before-write.h} | 28 +++---
40
block/backup.c | 22 ++---
41
block/{backup-top.c => copy-before-write.c} | 100 ++++++++++----------
42
MAINTAINERS | 4 +-
43
block/meson.build | 2 +-
44
tests/qemu-iotests/283 | 35 +++----
45
tests/qemu-iotests/283.out | 4 +-
46
7 files changed, 95 insertions(+), 100 deletions(-)
47
rename block/{backup-top.h => copy-before-write.h} (56%)
48
rename block/{backup-top.c => copy-before-write.c} (62%)
49
50
diff --git a/block/backup-top.h b/block/copy-before-write.h
51
similarity index 56%
52
rename from block/backup-top.h
53
rename to block/copy-before-write.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/backup-top.h
56
+++ b/block/copy-before-write.h
57
@@ -XXX,XX +XXX,XX @@
58
/*
59
- * backup-top filter driver
60
+ * copy-before-write filter driver
61
*
62
* The driver performs Copy-Before-Write (CBW) operation: it is injected above
63
* some node, and before each write it copies _old_ data to the target node.
64
*
65
- * Copyright (c) 2018-2019 Virtuozzo International GmbH.
66
+ * Copyright (c) 2018-2021 Virtuozzo International GmbH.
67
*
68
* Author:
69
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
70
@@ -XXX,XX +XXX,XX @@
71
* along with this program. If not, see <http://www.gnu.org/licenses/>.
72
*/
73
74
-#ifndef BACKUP_TOP_H
75
-#define BACKUP_TOP_H
76
+#ifndef COPY_BEFORE_WRITE_H
77
+#define COPY_BEFORE_WRITE_H
78
79
#include "block/block_int.h"
80
#include "block/block-copy.h"
81
82
-BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
83
- BlockDriverState *target,
84
- const char *filter_node_name,
85
- uint64_t cluster_size,
86
- BackupPerf *perf,
87
- BdrvRequestFlags write_flags,
88
- BlockCopyState **bcs,
89
- Error **errp);
90
-void bdrv_backup_top_drop(BlockDriverState *bs);
91
+BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
92
+ BlockDriverState *target,
93
+ const char *filter_node_name,
94
+ uint64_t cluster_size,
95
+ BackupPerf *perf,
96
+ BdrvRequestFlags write_flags,
97
+ BlockCopyState **bcs,
98
+ Error **errp);
99
+void bdrv_cbw_drop(BlockDriverState *bs);
100
101
-#endif /* BACKUP_TOP_H */
102
+#endif /* COPY_BEFORE_WRITE_H */
103
diff --git a/block/backup.c b/block/backup.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/backup.c
106
+++ b/block/backup.c
107
@@ -XXX,XX +XXX,XX @@
108
#include "qemu/bitmap.h"
109
#include "qemu/error-report.h"
110
111
-#include "block/backup-top.h"
112
+#include "block/copy-before-write.h"
113
114
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
115
116
typedef struct BackupBlockJob {
117
BlockJob common;
118
- BlockDriverState *backup_top;
119
+ BlockDriverState *cbw;
120
BlockDriverState *source_bs;
121
BlockDriverState *target_bs;
122
123
@@ -XXX,XX +XXX,XX @@ static void backup_clean(Job *job)
124
{
125
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
126
block_job_remove_all_bdrv(&s->common);
127
- bdrv_backup_top_drop(s->backup_top);
128
+ bdrv_cbw_drop(s->cbw);
129
}
130
131
void backup_do_checkpoint(BlockJob *job, Error **errp)
132
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
133
BackupBlockJob *job = NULL;
134
int64_t cluster_size;
135
BdrvRequestFlags write_flags;
136
- BlockDriverState *backup_top = NULL;
137
+ BlockDriverState *cbw = NULL;
138
BlockCopyState *bcs = NULL;
139
140
assert(bs);
141
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
142
write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
143
(compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
144
145
- backup_top = bdrv_backup_top_append(bs, target, filter_node_name,
146
+ cbw = bdrv_cbw_append(bs, target, filter_node_name,
147
cluster_size, perf,
148
write_flags, &bcs, errp);
149
- if (!backup_top) {
150
+ if (!cbw) {
151
goto error;
152
}
153
154
/* job->len is fixed, so we can't allow resize */
155
- job = block_job_create(job_id, &backup_job_driver, txn, backup_top,
156
+ job = block_job_create(job_id, &backup_job_driver, txn, cbw,
157
0, BLK_PERM_ALL,
158
speed, creation_flags, cb, opaque, errp);
159
if (!job) {
160
goto error;
161
}
162
163
- job->backup_top = backup_top;
164
+ job->cbw = cbw;
165
job->source_bs = bs;
166
job->target_bs = target;
167
job->on_source_error = on_source_error;
168
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
169
block_copy_set_progress_meter(bcs, &job->common.job.progress);
170
block_copy_set_speed(bcs, speed);
171
172
- /* Required permissions are already taken by backup-top target */
173
+ /* Required permissions are taken by copy-before-write filter target */
174
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
175
&error_abort);
176
177
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
178
if (sync_bitmap) {
179
bdrv_reclaim_dirty_bitmap(sync_bitmap, NULL);
180
}
181
- if (backup_top) {
182
- bdrv_backup_top_drop(backup_top);
183
+ if (cbw) {
184
+ bdrv_cbw_drop(cbw);
185
}
186
187
return NULL;
188
diff --git a/block/backup-top.c b/block/copy-before-write.c
189
similarity index 62%
190
rename from block/backup-top.c
191
rename to block/copy-before-write.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/block/backup-top.c
194
+++ b/block/copy-before-write.c
195
@@ -XXX,XX +XXX,XX @@
196
/*
197
- * backup-top filter driver
198
+ * copy-before-write filter driver
199
*
200
* The driver performs Copy-Before-Write (CBW) operation: it is injected above
201
* some node, and before each write it copies _old_ data to the target node.
202
*
203
- * Copyright (c) 2018-2019 Virtuozzo International GmbH.
204
+ * Copyright (c) 2018-2021 Virtuozzo International GmbH.
205
*
206
* Author:
207
* Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
208
@@ -XXX,XX +XXX,XX @@
209
#include "block/qdict.h"
210
#include "block/block-copy.h"
211
212
-#include "block/backup-top.h"
213
+#include "block/copy-before-write.h"
214
215
-typedef struct BDRVBackupTopState {
216
+typedef struct BDRVCopyBeforeWriteState {
217
BlockCopyState *bcs;
218
BdrvChild *target;
219
int64_t cluster_size;
220
-} BDRVBackupTopState;
221
+} BDRVCopyBeforeWriteState;
222
223
-static coroutine_fn int backup_top_co_preadv(
224
+static coroutine_fn int cbw_co_preadv(
225
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
226
QEMUIOVector *qiov, int flags)
227
{
228
return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
229
}
230
231
-static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
232
- uint64_t bytes, BdrvRequestFlags flags)
233
+static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
234
+ uint64_t offset, uint64_t bytes, BdrvRequestFlags flags)
235
{
236
- BDRVBackupTopState *s = bs->opaque;
237
+ BDRVCopyBeforeWriteState *s = bs->opaque;
238
uint64_t off, end;
239
240
if (flags & BDRV_REQ_WRITE_UNCHANGED) {
241
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_cbw(BlockDriverState *bs, uint64_t offset,
242
return block_copy(s->bcs, off, end - off, true);
243
}
244
245
-static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
246
- int64_t offset, int bytes)
247
+static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
248
+ int64_t offset, int bytes)
249
{
250
- int ret = backup_top_cbw(bs, offset, bytes, 0);
251
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, 0);
252
if (ret < 0) {
253
return ret;
254
}
255
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pdiscard(BlockDriverState *bs,
256
return bdrv_co_pdiscard(bs->backing, offset, bytes);
257
}
258
259
-static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
260
+static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
261
int64_t offset, int bytes, BdrvRequestFlags flags)
262
{
263
- int ret = backup_top_cbw(bs, offset, bytes, flags);
264
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
265
if (ret < 0) {
266
return ret;
267
}
268
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_pwrite_zeroes(BlockDriverState *bs,
269
return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
270
}
271
272
-static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
273
- uint64_t offset,
274
- uint64_t bytes,
275
- QEMUIOVector *qiov, int flags)
276
+static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
277
+ uint64_t offset,
278
+ uint64_t bytes,
279
+ QEMUIOVector *qiov, int flags)
280
{
281
- int ret = backup_top_cbw(bs, offset, bytes, flags);
282
+ int ret = cbw_do_copy_before_write(bs, offset, bytes, flags);
283
if (ret < 0) {
284
return ret;
285
}
286
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int backup_top_co_pwritev(BlockDriverState *bs,
287
return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
288
}
289
290
-static int coroutine_fn backup_top_co_flush(BlockDriverState *bs)
291
+static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
292
{
293
if (!bs->backing) {
294
return 0;
295
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_top_co_flush(BlockDriverState *bs)
296
return bdrv_co_flush(bs->backing->bs);
297
}
298
299
-static void backup_top_refresh_filename(BlockDriverState *bs)
300
+static void cbw_refresh_filename(BlockDriverState *bs)
301
{
302
if (bs->backing == NULL) {
303
/*
304
@@ -XXX,XX +XXX,XX @@ static void backup_top_refresh_filename(BlockDriverState *bs)
305
bs->backing->bs->filename);
306
}
307
308
-static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
309
- BdrvChildRole role,
310
- BlockReopenQueue *reopen_queue,
311
- uint64_t perm, uint64_t shared,
312
- uint64_t *nperm, uint64_t *nshared)
313
+static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
314
+ BdrvChildRole role,
315
+ BlockReopenQueue *reopen_queue,
316
+ uint64_t perm, uint64_t shared,
317
+ uint64_t *nperm, uint64_t *nshared)
318
{
319
if (!(role & BDRV_CHILD_FILTERED)) {
320
/*
321
@@ -XXX,XX +XXX,XX @@ static void backup_top_child_perm(BlockDriverState *bs, BdrvChild *c,
322
}
323
}
324
325
-BlockDriver bdrv_backup_top_filter = {
326
- .format_name = "backup-top",
327
- .instance_size = sizeof(BDRVBackupTopState),
328
+BlockDriver bdrv_cbw_filter = {
329
+ .format_name = "copy-before-write",
330
+ .instance_size = sizeof(BDRVCopyBeforeWriteState),
331
332
- .bdrv_co_preadv = backup_top_co_preadv,
333
- .bdrv_co_pwritev = backup_top_co_pwritev,
334
- .bdrv_co_pwrite_zeroes = backup_top_co_pwrite_zeroes,
335
- .bdrv_co_pdiscard = backup_top_co_pdiscard,
336
- .bdrv_co_flush = backup_top_co_flush,
337
+ .bdrv_co_preadv = cbw_co_preadv,
338
+ .bdrv_co_pwritev = cbw_co_pwritev,
339
+ .bdrv_co_pwrite_zeroes = cbw_co_pwrite_zeroes,
340
+ .bdrv_co_pdiscard = cbw_co_pdiscard,
341
+ .bdrv_co_flush = cbw_co_flush,
342
343
- .bdrv_refresh_filename = backup_top_refresh_filename,
344
+ .bdrv_refresh_filename = cbw_refresh_filename,
345
346
- .bdrv_child_perm = backup_top_child_perm,
347
+ .bdrv_child_perm = cbw_child_perm,
348
349
.is_filter = true,
350
};
351
352
-BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
353
- BlockDriverState *target,
354
- const char *filter_node_name,
355
- uint64_t cluster_size,
356
- BackupPerf *perf,
357
- BdrvRequestFlags write_flags,
358
- BlockCopyState **bcs,
359
- Error **errp)
360
+BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
361
+ BlockDriverState *target,
362
+ const char *filter_node_name,
363
+ uint64_t cluster_size,
364
+ BackupPerf *perf,
365
+ BdrvRequestFlags write_flags,
366
+ BlockCopyState **bcs,
367
+ Error **errp)
368
{
369
ERRP_GUARD();
370
int ret;
371
- BDRVBackupTopState *state;
372
+ BDRVCopyBeforeWriteState *state;
373
BlockDriverState *top;
374
bool appended = false;
375
376
assert(source->total_sectors == target->total_sectors);
377
378
- top = bdrv_new_open_driver(&bdrv_backup_top_filter, filter_node_name,
379
+ top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
380
BDRV_O_RDWR, errp);
381
if (!top) {
382
return NULL;
383
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
384
385
ret = bdrv_append(top, source, errp);
386
if (ret < 0) {
387
- error_prepend(errp, "Cannot append backup-top filter: ");
388
+ error_prepend(errp, "Cannot append copy-before-write filter: ");
389
goto fail;
390
}
391
appended = true;
392
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
393
394
fail:
395
if (appended) {
396
- bdrv_backup_top_drop(top);
397
+ bdrv_cbw_drop(top);
398
} else {
399
bdrv_unref(top);
400
}
401
@@ -XXX,XX +XXX,XX @@ fail:
402
return NULL;
403
}
404
405
-void bdrv_backup_top_drop(BlockDriverState *bs)
406
+void bdrv_cbw_drop(BlockDriverState *bs)
407
{
408
- BDRVBackupTopState *s = bs->opaque;
409
+ BDRVCopyBeforeWriteState *s = bs->opaque;
410
411
bdrv_drop_filter(bs, &error_abort);
412
413
diff --git a/MAINTAINERS b/MAINTAINERS
414
index XXXXXXX..XXXXXXX 100644
415
--- a/MAINTAINERS
416
+++ b/MAINTAINERS
417
@@ -XXX,XX +XXX,XX @@ F: block/mirror.c
418
F: qapi/job.json
419
F: block/block-copy.c
420
F: include/block/block-copy.c
421
-F: block/backup-top.h
422
-F: block/backup-top.c
423
+F: block/copy-before-write.h
424
+F: block/copy-before-write.c
425
F: include/block/aio_task.h
426
F: block/aio_task.c
427
F: util/qemu-co-shared-resource.c
428
diff --git a/block/meson.build b/block/meson.build
429
index XXXXXXX..XXXXXXX 100644
430
--- a/block/meson.build
431
+++ b/block/meson.build
432
@@ -XXX,XX +XXX,XX @@ block_ss.add(files(
433
'aio_task.c',
434
'amend.c',
435
'backup.c',
436
- 'backup-top.c',
437
+ 'copy-before-write.c',
438
'blkdebug.c',
439
'blklogwrites.c',
440
'blkverify.c',
441
diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283
442
index XXXXXXX..XXXXXXX 100755
443
--- a/tests/qemu-iotests/283
444
+++ b/tests/qemu-iotests/283
445
@@ -XXX,XX +XXX,XX @@
446
#!/usr/bin/env python3
447
# group: auto quick
448
#
449
-# Test for backup-top filter permission activation failure
450
+# Test for copy-before-write filter permission conflict
451
#
452
# Copyright (c) 2019 Virtuozzo International GmbH.
453
#
454
@@ -XXX,XX +XXX,XX @@ size = 1024 * 1024
455
""" Test description
456
457
When performing a backup, all writes on the source subtree must go through the
458
-backup-top filter so it can copy all data to the target before it is changed.
459
-backup-top filter is appended above source node, to achieve this thing, so all
460
-parents of source node are handled. A configuration with side parents of source
461
-sub-tree with write permission is unsupported (we'd have append several
462
-backup-top filter like nodes to handle such parents). The test create an
463
-example of such configuration and checks that a backup is then not allowed
464
-(blockdev-backup command should fail).
465
+copy-before-write filter so it can copy all data to the target before it is
466
+changed. copy-before-write filter is appended above source node, to achieve
467
+this thing, so all parents of source node are handled. A configuration with
468
+side parents of source sub-tree with write permission is unsupported (we'd have
469
+append several copy-before-write filter like nodes to handle such parents). The
470
+test create an example of such configuration and checks that a backup is then
471
+not allowed (blockdev-backup command should fail).
472
473
The configuration:
474
475
@@ -XXX,XX +XXX,XX @@ The configuration:
476
│ base │ ◀──────────── │ other │
477
└─────────────┘ └───────┘
478
479
-On activation (see .active field of backup-top state in block/backup-top.c),
480
-backup-top is going to unshare write permission on its source child. Write
481
-unsharing will be propagated to the "source->base" link and will conflict with
482
-other node write permission. So permission update will fail and backup job will
483
-not be started.
484
+copy-before-write filter wants to unshare write permission on its source child.
485
+Write unsharing will be propagated to the "source->base" link and will conflict
486
+with other node write permission. So permission update will fail and backup job
487
+will not be started.
488
489
Note, that the only thing which prevents backup of running on such
490
configuration is default permission propagation scheme. It may be altered by
491
@@ -XXX,XX +XXX,XX @@ vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
492
vm.shutdown()
493
494
495
-print('\n=== backup-top should be gone after job-finalize ===\n')
496
+print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
497
498
-# Check that the backup-top node is gone after job-finalize.
499
-#
500
-# During finalization, the node becomes inactive and can no longer
501
-# function. If it is still present, new parents might be attached, and
502
-# there would be no meaningful way to handle their I/O requests.
503
+# Check that the copy-before-write node is gone after job-finalize.
504
505
vm = iotests.VM()
506
vm.launch()
507
@@ -XXX,XX +XXX,XX @@ vm.qmp_log('blockdev-backup',
508
509
vm.event_wait('BLOCK_JOB_PENDING', 5.0)
510
511
-# The backup-top filter should still be present prior to finalization
512
+# The copy-before-write filter should still be present prior to finalization
513
assert vm.node_info('backup-filter') is not None
514
515
vm.qmp_log('job-finalize', id='backup')
516
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
517
index XXXXXXX..XXXXXXX 100644
518
--- a/tests/qemu-iotests/283.out
519
+++ b/tests/qemu-iotests/283.out
520
@@ -XXX,XX +XXX,XX @@
521
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
522
{"return": {}}
523
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
524
-{"error": {"class": "GenericError", "desc": "Cannot append backup-top filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
525
+{"error": {"class": "GenericError", "desc": "Cannot append copy-before-write filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
526
527
-=== backup-top should be gone after job-finalize ===
528
+=== copy-before-write filter should be gone after job-finalize ===
529
530
{"execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "source"}}
531
{"return": {}}
532
--
533
2.31.1
534
535
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We want to simplify initialization interface of copy-before-write
4
filter as we are going to make it public. So, let's detect fleecing
5
scheme exactly in block-copy code, to not pass this information through
6
extra levels.
7
8
Why not just set BDRV_REQ_SERIALISING unconditionally: because we are
9
going to implement new more efficient fleecing scheme which will not
10
rely on backing feature.
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
Message-Id: <20210824083856.17408-7-vsementsov@virtuozzo.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
16
---
17
block/copy-before-write.h | 2 +-
18
include/block/block-copy.h | 3 +--
19
block/backup.c | 21 +--------------------
20
block/block-copy.c | 24 +++++++++++++++++++++---
21
block/copy-before-write.c | 4 ++--
22
5 files changed, 26 insertions(+), 28 deletions(-)
23
24
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/copy-before-write.h
27
+++ b/block/copy-before-write.h
28
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
29
const char *filter_node_name,
30
uint64_t cluster_size,
31
BackupPerf *perf,
32
- BdrvRequestFlags write_flags,
33
+ bool compress,
34
BlockCopyState **bcs,
35
Error **errp);
36
void bdrv_cbw_drop(BlockDriverState *bs);
37
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block-copy.h
40
+++ b/include/block/block-copy.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct BlockCopyCallState BlockCopyCallState;
42
43
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
44
int64_t cluster_size, bool use_copy_range,
45
- BdrvRequestFlags write_flags,
46
- Error **errp);
47
+ bool compress, Error **errp);
48
49
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
50
51
diff --git a/block/backup.c b/block/backup.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/backup.c
54
+++ b/block/backup.c
55
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
56
int64_t len, target_len;
57
BackupBlockJob *job = NULL;
58
int64_t cluster_size;
59
- BdrvRequestFlags write_flags;
60
BlockDriverState *cbw = NULL;
61
BlockCopyState *bcs = NULL;
62
63
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
64
goto error;
65
}
66
67
- /*
68
- * If source is in backing chain of target assume that target is going to be
69
- * used for "image fleecing", i.e. it should represent a kind of snapshot of
70
- * source at backup-start point in time. And target is going to be read by
71
- * somebody (for example, used as NBD export) during backup job.
72
- *
73
- * In this case, we need to add BDRV_REQ_SERIALISING write flag to avoid
74
- * intersection of backup writes and third party reads from target,
75
- * otherwise reading from target we may occasionally read already updated by
76
- * guest data.
77
- *
78
- * For more information see commit f8d59dfb40bb and test
79
- * tests/qemu-iotests/222
80
- */
81
- write_flags = (bdrv_chain_contains(target, bs) ? BDRV_REQ_SERIALISING : 0) |
82
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
83
-
84
cbw = bdrv_cbw_append(bs, target, filter_node_name,
85
- cluster_size, perf,
86
- write_flags, &bcs, errp);
87
+ cluster_size, perf, compress, &bcs, errp);
88
if (!cbw) {
89
goto error;
90
}
91
diff --git a/block/block-copy.c b/block/block-copy.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/block/block-copy.c
94
+++ b/block/block-copy.c
95
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
96
97
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
98
int64_t cluster_size, bool use_copy_range,
99
- BdrvRequestFlags write_flags, Error **errp)
100
+ bool compress, Error **errp)
101
{
102
BlockCopyState *s;
103
BdrvDirtyBitmap *copy_bitmap;
104
+ bool is_fleecing;
105
106
copy_bitmap = bdrv_create_dirty_bitmap(source->bs, cluster_size, NULL,
107
errp);
108
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
109
}
110
bdrv_disable_dirty_bitmap(copy_bitmap);
111
112
+ /*
113
+ * If source is in backing chain of target assume that target is going to be
114
+ * used for "image fleecing", i.e. it should represent a kind of snapshot of
115
+ * source at backup-start point in time. And target is going to be read by
116
+ * somebody (for example, used as NBD export) during backup job.
117
+ *
118
+ * In this case, we need to add BDRV_REQ_SERIALISING write flag to avoid
119
+ * intersection of backup writes and third party reads from target,
120
+ * otherwise reading from target we may occasionally read already updated by
121
+ * guest data.
122
+ *
123
+ * For more information see commit f8d59dfb40bb and test
124
+ * tests/qemu-iotests/222
125
+ */
126
+ is_fleecing = bdrv_chain_contains(target->bs, source->bs);
127
+
128
s = g_new(BlockCopyState, 1);
129
*s = (BlockCopyState) {
130
.source = source,
131
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
132
.copy_bitmap = copy_bitmap,
133
.cluster_size = cluster_size,
134
.len = bdrv_dirty_bitmap_size(copy_bitmap),
135
- .write_flags = write_flags,
136
+ .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0) |
137
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
138
.mem = shres_create(BLOCK_COPY_MAX_MEM),
139
.max_transfer = QEMU_ALIGN_DOWN(
140
block_copy_max_transfer(source, target),
141
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
142
* behalf).
143
*/
144
s->method = COPY_READ_WRITE_CLUSTER;
145
- } else if (write_flags & BDRV_REQ_WRITE_COMPRESSED) {
146
+ } else if (compress) {
147
/* Compression supports only cluster-size writes and no copy-range. */
148
s->method = COPY_READ_WRITE_CLUSTER;
149
} else {
150
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/block/copy-before-write.c
153
+++ b/block/copy-before-write.c
154
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
155
const char *filter_node_name,
156
uint64_t cluster_size,
157
BackupPerf *perf,
158
- BdrvRequestFlags write_flags,
159
+ bool compress,
160
BlockCopyState **bcs,
161
Error **errp)
162
{
163
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
164
state->cluster_size = cluster_size;
165
state->bcs = block_copy_state_new(top->backing, state->target,
166
cluster_size, perf->use_copy_range,
167
- write_flags, errp);
168
+ compress, errp);
169
if (!state->bcs) {
170
error_prepend(errp, "Cannot create block-copy-state: ");
171
goto fail;
172
--
173
2.31.1
174
175
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We'll need a possibility to set compress and use_copy_range options
4
after initialization of the state. So make corresponding part of
5
block_copy_state_new() separate and public.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Message-Id: <20210824083856.17408-8-vsementsov@virtuozzo.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
include/block/block-copy.h | 3 +++
13
block/block-copy.c | 49 ++++++++++++++++++++++----------------
14
2 files changed, 32 insertions(+), 20 deletions(-)
15
16
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block-copy.h
19
+++ b/include/block/block-copy.h
20
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
21
int64_t cluster_size, bool use_copy_range,
22
bool compress, Error **errp);
23
24
+/* Function should be called prior any actual copy request */
25
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
26
+ bool compress);
27
void block_copy_set_progress_meter(BlockCopyState *s, ProgressMeter *pm);
28
29
void block_copy_state_free(BlockCopyState *s);
30
diff --git a/block/block-copy.c b/block/block-copy.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/block-copy.c
33
+++ b/block/block-copy.c
34
@@ -XXX,XX +XXX,XX @@ static uint32_t block_copy_max_transfer(BdrvChild *source, BdrvChild *target)
35
target->bs->bl.max_transfer));
36
}
37
38
+void block_copy_set_copy_opts(BlockCopyState *s, bool use_copy_range,
39
+ bool compress)
40
+{
41
+ /* Keep BDRV_REQ_SERIALISING set (or not set) in block_copy_state_new() */
42
+ s->write_flags = (s->write_flags & BDRV_REQ_SERIALISING) |
43
+ (compress ? BDRV_REQ_WRITE_COMPRESSED : 0);
44
+
45
+ if (s->max_transfer < s->cluster_size) {
46
+ /*
47
+ * copy_range does not respect max_transfer. We don't want to bother
48
+ * with requests smaller than block-copy cluster size, so fallback to
49
+ * buffered copying (read and write respect max_transfer on their
50
+ * behalf).
51
+ */
52
+ s->method = COPY_READ_WRITE_CLUSTER;
53
+ } else if (compress) {
54
+ /* Compression supports only cluster-size writes and no copy-range. */
55
+ s->method = COPY_READ_WRITE_CLUSTER;
56
+ } else {
57
+ /*
58
+ * If copy range enabled, start with COPY_RANGE_SMALL, until first
59
+ * successful copy_range (look at block_copy_do_copy).
60
+ */
61
+ s->method = use_copy_range ? COPY_RANGE_SMALL : COPY_READ_WRITE;
62
+ }
63
+}
64
+
65
BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
66
int64_t cluster_size, bool use_copy_range,
67
bool compress, Error **errp)
68
@@ -XXX,XX +XXX,XX @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target,
69
.copy_bitmap = copy_bitmap,
70
.cluster_size = cluster_size,
71
.len = bdrv_dirty_bitmap_size(copy_bitmap),
72
- .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0) |
73
- (compress ? BDRV_REQ_WRITE_COMPRESSED : 0),
74
+ .write_flags = (is_fleecing ? BDRV_REQ_SERIALISING : 0),
75
.mem = shres_create(BLOCK_COPY_MAX_MEM),
76
.max_transfer = QEMU_ALIGN_DOWN(
77
block_copy_max_transfer(source, target),
78
cluster_size),
79
};
80
81
- if (s->max_transfer < cluster_size) {
82
- /*
83
- * copy_range does not respect max_transfer. We don't want to bother
84
- * with requests smaller than block-copy cluster size, so fallback to
85
- * buffered copying (read and write respect max_transfer on their
86
- * behalf).
87
- */
88
- s->method = COPY_READ_WRITE_CLUSTER;
89
- } else if (compress) {
90
- /* Compression supports only cluster-size writes and no copy-range. */
91
- s->method = COPY_READ_WRITE_CLUSTER;
92
- } else {
93
- /*
94
- * If copy range enabled, start with COPY_RANGE_SMALL, until first
95
- * successful copy_range (look at block_copy_do_copy).
96
- */
97
- s->method = use_copy_range ? COPY_RANGE_SMALL : COPY_READ_WRITE;
98
- }
99
+ block_copy_set_copy_opts(s, use_copy_range, compress);
100
101
ratelimit_init(&s->rate_limit);
102
qemu_co_mutex_init(&s->lock);
103
--
104
2.31.1
105
106
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter, so it would be
4
initialized through options. Still we don't want to publish compress
5
and copy-range options, as
6
7
1. Modern way to enable compression is to use compress filter.
8
9
2. For copy-range it's unclean how to make proper interface:
10
- it's has experimental prefix for backup job anyway
11
- the whole BackupPerf structure doesn't make sense for the filter
12
So, let's just add copy-range possibility to the filter later if
13
needed.
14
15
Still, we are going to continue support for compression and
16
experimental copy-range in backup job. So, set these options after
17
filter creation.
18
19
Note, that we can drop "compress" argument of bdrv_cbw_append() now, as
20
well as "perf". The only reason not doing so is that now, when I
21
prepare this patch the big series around it is already reviewed and I
22
want to avoid extra rebase conflicts to simplify review of the
23
following version.
24
25
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
27
Message-Id: <20210824083856.17408-9-vsementsov@virtuozzo.com>
28
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
29
---
30
block/copy-before-write.h | 1 -
31
block/backup.c | 3 ++-
32
block/copy-before-write.c | 4 +---
33
3 files changed, 3 insertions(+), 5 deletions(-)
34
35
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/copy-before-write.h
38
+++ b/block/copy-before-write.h
39
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
40
BlockDriverState *target,
41
const char *filter_node_name,
42
uint64_t cluster_size,
43
- BackupPerf *perf,
44
bool compress,
45
BlockCopyState **bcs,
46
Error **errp);
47
diff --git a/block/backup.c b/block/backup.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/backup.c
50
+++ b/block/backup.c
51
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
52
}
53
54
cbw = bdrv_cbw_append(bs, target, filter_node_name,
55
- cluster_size, perf, compress, &bcs, errp);
56
+ cluster_size, false, &bcs, errp);
57
if (!cbw) {
58
goto error;
59
}
60
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
61
job->len = len;
62
job->perf = *perf;
63
64
+ block_copy_set_copy_opts(bcs, perf->use_copy_range, compress);
65
block_copy_set_progress_meter(bcs, &job->common.job.progress);
66
block_copy_set_speed(bcs, speed);
67
68
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/copy-before-write.c
71
+++ b/block/copy-before-write.c
72
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
73
BlockDriverState *target,
74
const char *filter_node_name,
75
uint64_t cluster_size,
76
- BackupPerf *perf,
77
bool compress,
78
BlockCopyState **bcs,
79
Error **errp)
80
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
81
82
state->cluster_size = cluster_size;
83
state->bcs = block_copy_state_new(top->backing, state->target,
84
- cluster_size, perf->use_copy_range,
85
- compress, errp);
86
+ cluster_size, false, compress, errp);
87
if (!state->bcs) {
88
error_prepend(errp, "Cannot create block-copy-state: ");
89
goto fail;
90
--
91
2.31.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are going to publish copy-before-write filter. So, user should be
4
able to create it with blockdev-add first, specifying both filtered and
5
target children. And then do blockdev-reopen, to actually insert the
6
filter where needed.
7
8
Currently, filter unshares write permission unconditionally on source
9
node. It's good, but it will not allow to do blockdev-add. So, let's
10
relax restrictions when filter doesn't have any parent.
11
12
Test output is modified, as now permission conflict happens only when
13
job creates a blk parent for filter node.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Reviewed-by: Max Reitz <mreitz@redhat.com>
17
Message-Id: <20210824083856.17408-11-vsementsov@virtuozzo.com>
18
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
19
---
20
block/copy-before-write.c | 8 +++++---
21
tests/qemu-iotests/283.out | 2 +-
22
2 files changed, 6 insertions(+), 4 deletions(-)
23
24
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/copy-before-write.c
27
+++ b/block/copy-before-write.c
28
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
29
bdrv_default_perms(bs, c, role, reopen_queue,
30
perm, shared, nperm, nshared);
31
32
- if (perm & BLK_PERM_WRITE) {
33
- *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
34
+ if (!QLIST_EMPTY(&bs->parents)) {
35
+ if (perm & BLK_PERM_WRITE) {
36
+ *nperm = *nperm | BLK_PERM_CONSISTENT_READ;
37
+ }
38
+ *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
39
}
40
- *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE);
41
}
42
}
43
44
diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tests/qemu-iotests/283.out
47
+++ b/tests/qemu-iotests/283.out
48
@@ -XXX,XX +XXX,XX @@
49
{"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}}
50
{"return": {}}
51
{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}}
52
-{"error": {"class": "GenericError", "desc": "Cannot append copy-before-write filter: Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
53
+{"error": {"class": "GenericError", "desc": "Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}}
54
55
=== copy-before-write filter should be gone after job-finalize ===
56
57
--
58
2.31.1
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
bdrv_attach_child() do bdrv_unref() on failure, so we shouldn't do it
4
by hand here.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <20210824083856.17408-12-vsementsov@virtuozzo.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
block/copy-before-write.c | 1 -
12
1 file changed, 1 deletion(-)
13
14
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/copy-before-write.c
17
+++ b/block/copy-before-write.c
18
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
19
state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
20
BDRV_CHILD_DATA, errp);
21
if (!state->target) {
22
- bdrv_unref(target);
23
bdrv_unref(top);
24
return NULL;
25
}
26
--
27
2.31.1
28
29
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Finally, copy-before-write gets own .bdrv_open and .bdrv_close
3
This patch extends virtio-blk emulation to handle zoned device commands
4
handlers, block_init() call and becomes available through bdrv_open().
4
by calling the new block layer APIs to perform zoned device I/O on
5
behalf of the guest. It supports Report Zone, four zone oparations (open,
6
close, finish, reset), and Append Zone.
5
7
6
To achieve this:
8
The VIRTIO_BLK_F_ZONED feature bit will only be set if the host does
9
support zoned block devices. Regular block devices(conventional zones)
10
will not be set.
7
11
8
- cbw_init gets unused flags argument and becomes cbw_open
12
The guest os can use blktests, fio to test those commands on zoned devices.
9
- block_copy_state_free() call moved to new cbw_close()
13
Furthermore, using zonefs to test zone append write is also supported.
10
- in bdrv_cbw_append:
11
- options are completed with driver and node-name, and we can simply
12
use bdrv_insert_node() to do both open and drained replacing
13
- in bdrv_cbw_drop:
14
- cbw_close() is now responsible for freeing s->bcs, so don't do it
15
here
16
14
17
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Signed-off-by: Sam Li <faithilikerun@gmail.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Message-id: 20230407082528.18841-3-faithilikerun@gmail.com
19
Message-Id: <20210824083856.17408-22-vsementsov@virtuozzo.com>
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
21
---
18
---
22
block/copy-before-write.c | 60 ++++++++++++++++++---------------------
19
hw/block/virtio-blk-common.c | 2 +
23
1 file changed, 28 insertions(+), 32 deletions(-)
20
hw/block/virtio-blk.c | 389 +++++++++++++++++++++++++++++++++++
21
hw/virtio/virtio-qmp.c | 2 +
22
3 files changed, 393 insertions(+)
24
23
25
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
24
diff --git a/hw/block/virtio-blk-common.c b/hw/block/virtio-blk-common.c
26
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
27
--- a/block/copy-before-write.c
26
--- a/hw/block/virtio-blk-common.c
28
+++ b/block/copy-before-write.c
27
+++ b/hw/block/virtio-blk-common.c
29
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
28
@@ -XXX,XX +XXX,XX @@ static const VirtIOFeature feature_sizes[] = {
29
.end = endof(struct virtio_blk_config, discard_sector_alignment)},
30
{.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES,
31
.end = endof(struct virtio_blk_config, write_zeroes_may_unmap)},
32
+ {.flags = 1ULL << VIRTIO_BLK_F_ZONED,
33
+ .end = endof(struct virtio_blk_config, zoned)},
34
{}
35
};
36
37
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/block/virtio-blk.c
40
+++ b/hw/block/virtio-blk.c
41
@@ -XXX,XX +XXX,XX @@
42
#include "qemu/module.h"
43
#include "qemu/error-report.h"
44
#include "qemu/main-loop.h"
45
+#include "block/block_int.h"
46
#include "trace.h"
47
#include "hw/block/block.h"
48
#include "hw/qdev-properties.h"
49
@@ -XXX,XX +XXX,XX @@ err:
50
return err_status;
51
}
52
53
+typedef struct ZoneCmdData {
54
+ VirtIOBlockReq *req;
55
+ struct iovec *in_iov;
56
+ unsigned in_num;
57
+ union {
58
+ struct {
59
+ unsigned int nr_zones;
60
+ BlockZoneDescriptor *zones;
61
+ } zone_report_data;
62
+ struct {
63
+ int64_t offset;
64
+ } zone_append_data;
65
+ };
66
+} ZoneCmdData;
67
+
68
+/*
69
+ * check zoned_request: error checking before issuing requests. If all checks
70
+ * passed, return true.
71
+ * append: true if only zone append requests issued.
72
+ */
73
+static bool check_zoned_request(VirtIOBlock *s, int64_t offset, int64_t len,
74
+ bool append, uint8_t *status) {
75
+ BlockDriverState *bs = blk_bs(s->blk);
76
+ int index;
77
+
78
+ if (!virtio_has_feature(s->host_features, VIRTIO_BLK_F_ZONED)) {
79
+ *status = VIRTIO_BLK_S_UNSUPP;
80
+ return false;
81
+ }
82
+
83
+ if (offset < 0 || len < 0 || len > (bs->total_sectors << BDRV_SECTOR_BITS)
84
+ || offset > (bs->total_sectors << BDRV_SECTOR_BITS) - len) {
85
+ *status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
86
+ return false;
87
+ }
88
+
89
+ if (append) {
90
+ if (bs->bl.write_granularity) {
91
+ if ((offset % bs->bl.write_granularity) != 0) {
92
+ *status = VIRTIO_BLK_S_ZONE_UNALIGNED_WP;
93
+ return false;
94
+ }
95
+ }
96
+
97
+ index = offset / bs->bl.zone_size;
98
+ if (BDRV_ZT_IS_CONV(bs->wps->wp[index])) {
99
+ *status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
100
+ return false;
101
+ }
102
+
103
+ if (len / 512 > bs->bl.max_append_sectors) {
104
+ if (bs->bl.max_append_sectors == 0) {
105
+ *status = VIRTIO_BLK_S_UNSUPP;
106
+ } else {
107
+ *status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
108
+ }
109
+ return false;
110
+ }
111
+ }
112
+ return true;
113
+}
114
+
115
+static void virtio_blk_zone_report_complete(void *opaque, int ret)
116
+{
117
+ ZoneCmdData *data = opaque;
118
+ VirtIOBlockReq *req = data->req;
119
+ VirtIOBlock *s = req->dev;
120
+ VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
121
+ struct iovec *in_iov = data->in_iov;
122
+ unsigned in_num = data->in_num;
123
+ int64_t zrp_size, n, j = 0;
124
+ int64_t nz = data->zone_report_data.nr_zones;
125
+ int8_t err_status = VIRTIO_BLK_S_OK;
126
+
127
+ if (ret) {
128
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
129
+ goto out;
130
+ }
131
+
132
+ struct virtio_blk_zone_report zrp_hdr = (struct virtio_blk_zone_report) {
133
+ .nr_zones = cpu_to_le64(nz),
134
+ };
135
+ zrp_size = sizeof(struct virtio_blk_zone_report)
136
+ + sizeof(struct virtio_blk_zone_descriptor) * nz;
137
+ n = iov_from_buf(in_iov, in_num, 0, &zrp_hdr, sizeof(zrp_hdr));
138
+ if (n != sizeof(zrp_hdr)) {
139
+ virtio_error(vdev, "Driver provided input buffer that is too small!");
140
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
141
+ goto out;
142
+ }
143
+
144
+ for (size_t i = sizeof(zrp_hdr); i < zrp_size;
145
+ i += sizeof(struct virtio_blk_zone_descriptor), ++j) {
146
+ struct virtio_blk_zone_descriptor desc =
147
+ (struct virtio_blk_zone_descriptor) {
148
+ .z_start = cpu_to_le64(data->zone_report_data.zones[j].start
149
+ >> BDRV_SECTOR_BITS),
150
+ .z_cap = cpu_to_le64(data->zone_report_data.zones[j].cap
151
+ >> BDRV_SECTOR_BITS),
152
+ .z_wp = cpu_to_le64(data->zone_report_data.zones[j].wp
153
+ >> BDRV_SECTOR_BITS),
154
+ };
155
+
156
+ switch (data->zone_report_data.zones[j].type) {
157
+ case BLK_ZT_CONV:
158
+ desc.z_type = VIRTIO_BLK_ZT_CONV;
159
+ break;
160
+ case BLK_ZT_SWR:
161
+ desc.z_type = VIRTIO_BLK_ZT_SWR;
162
+ break;
163
+ case BLK_ZT_SWP:
164
+ desc.z_type = VIRTIO_BLK_ZT_SWP;
165
+ break;
166
+ default:
167
+ g_assert_not_reached();
168
+ }
169
+
170
+ switch (data->zone_report_data.zones[j].state) {
171
+ case BLK_ZS_RDONLY:
172
+ desc.z_state = VIRTIO_BLK_ZS_RDONLY;
173
+ break;
174
+ case BLK_ZS_OFFLINE:
175
+ desc.z_state = VIRTIO_BLK_ZS_OFFLINE;
176
+ break;
177
+ case BLK_ZS_EMPTY:
178
+ desc.z_state = VIRTIO_BLK_ZS_EMPTY;
179
+ break;
180
+ case BLK_ZS_CLOSED:
181
+ desc.z_state = VIRTIO_BLK_ZS_CLOSED;
182
+ break;
183
+ case BLK_ZS_FULL:
184
+ desc.z_state = VIRTIO_BLK_ZS_FULL;
185
+ break;
186
+ case BLK_ZS_EOPEN:
187
+ desc.z_state = VIRTIO_BLK_ZS_EOPEN;
188
+ break;
189
+ case BLK_ZS_IOPEN:
190
+ desc.z_state = VIRTIO_BLK_ZS_IOPEN;
191
+ break;
192
+ case BLK_ZS_NOT_WP:
193
+ desc.z_state = VIRTIO_BLK_ZS_NOT_WP;
194
+ break;
195
+ default:
196
+ g_assert_not_reached();
197
+ }
198
+
199
+ /* TODO: it takes O(n^2) time complexity. Optimizations required. */
200
+ n = iov_from_buf(in_iov, in_num, i, &desc, sizeof(desc));
201
+ if (n != sizeof(desc)) {
202
+ virtio_error(vdev, "Driver provided input buffer "
203
+ "for descriptors that is too small!");
204
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
205
+ }
206
+ }
207
+
208
+out:
209
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
210
+ virtio_blk_req_complete(req, err_status);
211
+ virtio_blk_free_request(req);
212
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
213
+ g_free(data->zone_report_data.zones);
214
+ g_free(data);
215
+}
216
+
217
+static void virtio_blk_handle_zone_report(VirtIOBlockReq *req,
218
+ struct iovec *in_iov,
219
+ unsigned in_num)
220
+{
221
+ VirtIOBlock *s = req->dev;
222
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
223
+ unsigned int nr_zones;
224
+ ZoneCmdData *data;
225
+ int64_t zone_size, offset;
226
+ uint8_t err_status;
227
+
228
+ if (req->in_len < sizeof(struct virtio_blk_inhdr) +
229
+ sizeof(struct virtio_blk_zone_report) +
230
+ sizeof(struct virtio_blk_zone_descriptor)) {
231
+ virtio_error(vdev, "in buffer too small for zone report");
232
+ return;
233
+ }
234
+
235
+ /* start byte offset of the zone report */
236
+ offset = virtio_ldq_p(vdev, &req->out.sector) << BDRV_SECTOR_BITS;
237
+ if (!check_zoned_request(s, offset, 0, false, &err_status)) {
238
+ goto out;
239
+ }
240
+ nr_zones = (req->in_len - sizeof(struct virtio_blk_inhdr) -
241
+ sizeof(struct virtio_blk_zone_report)) /
242
+ sizeof(struct virtio_blk_zone_descriptor);
243
+
244
+ zone_size = sizeof(BlockZoneDescriptor) * nr_zones;
245
+ data = g_malloc(sizeof(ZoneCmdData));
246
+ data->req = req;
247
+ data->in_iov = in_iov;
248
+ data->in_num = in_num;
249
+ data->zone_report_data.nr_zones = nr_zones;
250
+ data->zone_report_data.zones = g_malloc(zone_size),
251
+
252
+ blk_aio_zone_report(s->blk, offset, &data->zone_report_data.nr_zones,
253
+ data->zone_report_data.zones,
254
+ virtio_blk_zone_report_complete, data);
255
+ return;
256
+out:
257
+ virtio_blk_req_complete(req, err_status);
258
+ virtio_blk_free_request(req);
259
+}
260
+
261
+static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
262
+{
263
+ VirtIOBlockReq *req = opaque;
264
+ VirtIOBlock *s = req->dev;
265
+ int8_t err_status = VIRTIO_BLK_S_OK;
266
+
267
+ if (ret) {
268
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
269
+ }
270
+
271
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
272
+ virtio_blk_req_complete(req, err_status);
273
+ virtio_blk_free_request(req);
274
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
275
+}
276
+
277
+static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
278
+{
279
+ VirtIOBlock *s = req->dev;
280
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
281
+ BlockDriverState *bs = blk_bs(s->blk);
282
+ int64_t offset = virtio_ldq_p(vdev, &req->out.sector) << BDRV_SECTOR_BITS;
283
+ uint64_t len;
284
+ uint64_t capacity = bs->total_sectors << BDRV_SECTOR_BITS;
285
+ uint8_t err_status = VIRTIO_BLK_S_OK;
286
+
287
+ uint32_t type = virtio_ldl_p(vdev, &req->out.type);
288
+ if (type == VIRTIO_BLK_T_ZONE_RESET_ALL) {
289
+ /* Entire drive capacity */
290
+ offset = 0;
291
+ len = capacity;
292
+ } else {
293
+ if (bs->bl.zone_size > capacity - offset) {
294
+ /* The zoned device allows the last smaller zone. */
295
+ len = capacity - bs->bl.zone_size * (bs->bl.nr_zones - 1);
296
+ } else {
297
+ len = bs->bl.zone_size;
298
+ }
299
+ }
300
+
301
+ if (!check_zoned_request(s, offset, len, false, &err_status)) {
302
+ goto out;
303
+ }
304
+
305
+ blk_aio_zone_mgmt(s->blk, op, offset, len,
306
+ virtio_blk_zone_mgmt_complete, req);
307
+
308
+ return 0;
309
+out:
310
+ virtio_blk_req_complete(req, err_status);
311
+ virtio_blk_free_request(req);
312
+ return err_status;
313
+}
314
+
315
+static void virtio_blk_zone_append_complete(void *opaque, int ret)
316
+{
317
+ ZoneCmdData *data = opaque;
318
+ VirtIOBlockReq *req = data->req;
319
+ VirtIOBlock *s = req->dev;
320
+ VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
321
+ int64_t append_sector, n;
322
+ uint8_t err_status = VIRTIO_BLK_S_OK;
323
+
324
+ if (ret) {
325
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
326
+ goto out;
327
+ }
328
+
329
+ virtio_stq_p(vdev, &append_sector,
330
+ data->zone_append_data.offset >> BDRV_SECTOR_BITS);
331
+ n = iov_from_buf(data->in_iov, data->in_num, 0, &append_sector,
332
+ sizeof(append_sector));
333
+ if (n != sizeof(append_sector)) {
334
+ virtio_error(vdev, "Driver provided input buffer less than size of "
335
+ "append_sector");
336
+ err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
337
+ goto out;
338
+ }
339
+
340
+out:
341
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
342
+ virtio_blk_req_complete(req, err_status);
343
+ virtio_blk_free_request(req);
344
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
345
+ g_free(data);
346
+}
347
+
348
+static int virtio_blk_handle_zone_append(VirtIOBlockReq *req,
349
+ struct iovec *out_iov,
350
+ struct iovec *in_iov,
351
+ uint64_t out_num,
352
+ unsigned in_num) {
353
+ VirtIOBlock *s = req->dev;
354
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
355
+ uint8_t err_status = VIRTIO_BLK_S_OK;
356
+
357
+ int64_t offset = virtio_ldq_p(vdev, &req->out.sector) << BDRV_SECTOR_BITS;
358
+ int64_t len = iov_size(out_iov, out_num);
359
+
360
+ if (!check_zoned_request(s, offset, len, true, &err_status)) {
361
+ goto out;
362
+ }
363
+
364
+ ZoneCmdData *data = g_malloc(sizeof(ZoneCmdData));
365
+ data->req = req;
366
+ data->in_iov = in_iov;
367
+ data->in_num = in_num;
368
+ data->zone_append_data.offset = offset;
369
+ qemu_iovec_init_external(&req->qiov, out_iov, out_num);
370
+ blk_aio_zone_append(s->blk, &data->zone_append_data.offset, &req->qiov, 0,
371
+ virtio_blk_zone_append_complete, data);
372
+ return 0;
373
+
374
+out:
375
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
376
+ virtio_blk_req_complete(req, err_status);
377
+ virtio_blk_free_request(req);
378
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
379
+ return err_status;
380
+}
381
+
382
static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
383
{
384
uint32_t type;
385
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
386
case VIRTIO_BLK_T_FLUSH:
387
virtio_blk_handle_flush(req, mrb);
388
break;
389
+ case VIRTIO_BLK_T_ZONE_REPORT:
390
+ virtio_blk_handle_zone_report(req, in_iov, in_num);
391
+ break;
392
+ case VIRTIO_BLK_T_ZONE_OPEN:
393
+ virtio_blk_handle_zone_mgmt(req, BLK_ZO_OPEN);
394
+ break;
395
+ case VIRTIO_BLK_T_ZONE_CLOSE:
396
+ virtio_blk_handle_zone_mgmt(req, BLK_ZO_CLOSE);
397
+ break;
398
+ case VIRTIO_BLK_T_ZONE_FINISH:
399
+ virtio_blk_handle_zone_mgmt(req, BLK_ZO_FINISH);
400
+ break;
401
+ case VIRTIO_BLK_T_ZONE_RESET:
402
+ virtio_blk_handle_zone_mgmt(req, BLK_ZO_RESET);
403
+ break;
404
+ case VIRTIO_BLK_T_ZONE_RESET_ALL:
405
+ virtio_blk_handle_zone_mgmt(req, BLK_ZO_RESET);
406
+ break;
407
case VIRTIO_BLK_T_SCSI_CMD:
408
virtio_blk_handle_scsi(req);
409
break;
410
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
411
virtio_blk_free_request(req);
412
break;
30
}
413
}
414
+ case VIRTIO_BLK_T_ZONE_APPEND & ~VIRTIO_BLK_T_OUT:
415
+ /*
416
+ * Passing out_iov/out_num and in_iov/in_num is not safe
417
+ * to access req->elem.out_sg directly because it may be
418
+ * modified by virtio_blk_handle_request().
419
+ */
420
+ virtio_blk_handle_zone_append(req, out_iov, in_iov, out_num, in_num);
421
+ break;
422
/*
423
* VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES are defined with
424
* VIRTIO_BLK_T_OUT flag set. We masked this flag in the switch statement,
425
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
426
{
427
VirtIOBlock *s = VIRTIO_BLK(vdev);
428
BlockConf *conf = &s->conf.conf;
429
+ BlockDriverState *bs = blk_bs(s->blk);
430
struct virtio_blk_config blkcfg;
431
uint64_t capacity;
432
int64_t length;
433
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
434
blkcfg.write_zeroes_may_unmap = 1;
435
virtio_stl_p(vdev, &blkcfg.max_write_zeroes_seg, 1);
436
}
437
+ if (bs->bl.zoned != BLK_Z_NONE) {
438
+ switch (bs->bl.zoned) {
439
+ case BLK_Z_HM:
440
+ blkcfg.zoned.model = VIRTIO_BLK_Z_HM;
441
+ break;
442
+ case BLK_Z_HA:
443
+ blkcfg.zoned.model = VIRTIO_BLK_Z_HA;
444
+ break;
445
+ default:
446
+ g_assert_not_reached();
447
+ }
448
+
449
+ virtio_stl_p(vdev, &blkcfg.zoned.zone_sectors,
450
+ bs->bl.zone_size / 512);
451
+ virtio_stl_p(vdev, &blkcfg.zoned.max_active_zones,
452
+ bs->bl.max_active_zones);
453
+ virtio_stl_p(vdev, &blkcfg.zoned.max_open_zones,
454
+ bs->bl.max_open_zones);
455
+ virtio_stl_p(vdev, &blkcfg.zoned.write_granularity, blk_size);
456
+ virtio_stl_p(vdev, &blkcfg.zoned.max_append_sectors,
457
+ bs->bl.max_append_sectors);
458
+ } else {
459
+ blkcfg.zoned.model = VIRTIO_BLK_Z_NONE;
460
+ }
461
memcpy(config, &blkcfg, s->config_size);
31
}
462
}
32
463
33
-static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
464
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
34
+static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
465
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
35
+ Error **errp)
466
VirtIOBlock *s = VIRTIO_BLK(dev);
36
{
467
VirtIOBlkConf *conf = &s->conf;
37
BDRVCopyBeforeWriteState *s = bs->opaque;
468
+ BlockDriverState *bs = blk_bs(conf->conf.blk);
38
BdrvDirtyBitmap *copy_bitmap;
469
Error *err = NULL;
39
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, QDict *options, Error **errp)
470
unsigned i;
40
return 0;
471
41
}
472
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
42
473
return;
43
+static void cbw_close(BlockDriverState *bs)
44
+{
45
+ BDRVCopyBeforeWriteState *s = bs->opaque;
46
+
47
+ block_copy_state_free(s->bcs);
48
+ s->bcs = NULL;
49
+}
50
+
51
BlockDriver bdrv_cbw_filter = {
52
.format_name = "copy-before-write",
53
.instance_size = sizeof(BDRVCopyBeforeWriteState),
54
55
+ .bdrv_open = cbw_open,
56
+ .bdrv_close = cbw_close,
57
+
58
.bdrv_co_preadv = cbw_co_preadv,
59
.bdrv_co_pwritev = cbw_co_pwritev,
60
.bdrv_co_pwrite_zeroes = cbw_co_pwrite_zeroes,
61
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
62
Error **errp)
63
{
64
ERRP_GUARD();
65
- int ret;
66
BDRVCopyBeforeWriteState *state;
67
BlockDriverState *top;
68
QDict *opts;
69
70
assert(source->total_sectors == target->total_sectors);
71
72
- top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
73
- BDRV_O_RDWR, errp);
74
- if (!top) {
75
- error_prepend(errp, "Cannot open driver: ");
76
- return NULL;
77
- }
78
- state = top->opaque;
79
-
80
opts = qdict_new();
81
+ qdict_put_str(opts, "driver", "copy-before-write");
82
+ if (filter_node_name) {
83
+ qdict_put_str(opts, "node-name", filter_node_name);
84
+ }
85
qdict_put_str(opts, "file", bdrv_get_node_name(source));
86
qdict_put_str(opts, "target", bdrv_get_node_name(target));
87
88
- ret = cbw_init(top, opts, errp);
89
- qobject_unref(opts);
90
- if (ret < 0) {
91
- goto fail;
92
- }
93
-
94
- bdrv_drained_begin(source);
95
- ret = bdrv_replace_node(source, top, errp);
96
- bdrv_drained_end(source);
97
- if (ret < 0) {
98
- error_prepend(errp, "Cannot append copy-before-write filter: ");
99
- goto fail;
100
+ top = bdrv_insert_node(source, opts, BDRV_O_RDWR, errp);
101
+ if (!top) {
102
+ return NULL;
103
}
474
}
104
475
105
+ state = top->opaque;
476
+ if (bs->bl.zoned != BLK_Z_NONE) {
106
*bcs = state->bcs;
477
+ virtio_add_feature(&s->host_features, VIRTIO_BLK_F_ZONED);
107
478
+ if (bs->bl.zoned == BLK_Z_HM) {
108
return top;
479
+ virtio_clear_feature(&s->host_features, VIRTIO_BLK_F_DISCARD);
109
-
480
+ }
110
-fail:
481
+ }
111
- block_copy_state_free(state->bcs);
482
+
112
- bdrv_unref(top);
483
if (virtio_has_feature(s->host_features, VIRTIO_BLK_F_DISCARD) &&
113
- return NULL;
484
(!conf->max_discard_sectors ||
114
}
485
conf->max_discard_sectors > BDRV_REQUEST_MAX_SECTORS)) {
115
486
diff --git a/hw/virtio/virtio-qmp.c b/hw/virtio/virtio-qmp.c
116
void bdrv_cbw_drop(BlockDriverState *bs)
487
index XXXXXXX..XXXXXXX 100644
117
{
488
--- a/hw/virtio/virtio-qmp.c
118
- BDRVCopyBeforeWriteState *s = bs->opaque;
489
+++ b/hw/virtio/virtio-qmp.c
119
-
490
@@ -XXX,XX +XXX,XX @@ static const qmp_virtio_feature_map_t virtio_blk_feature_map[] = {
120
bdrv_drop_filter(bs, &error_abort);
491
"VIRTIO_BLK_F_DISCARD: Discard command supported"),
121
-
492
FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \
122
- block_copy_state_free(s->bcs);
493
"VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"),
123
-
494
+ FEATURE_ENTRY(VIRTIO_BLK_F_ZONED, \
124
bdrv_unref(bs);
495
+ "VIRTIO_BLK_F_ZONED: Zoned block devices"),
125
}
496
#ifndef VIRTIO_BLK_NO_LEGACY
126
+
497
FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \
127
+static void cbw_init(void)
498
"VIRTIO_BLK_F_BARRIER: Request barriers supported"),
128
+{
129
+ bdrv_register(&bdrv_cbw_filter);
130
+}
131
+
132
+block_init(cbw_init);
133
--
499
--
134
2.31.1
500
2.39.2
135
136
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
3
Taking account of the new zone append write operation for zoned devices,
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
BLOCK_ACCT_ZONE_APPEND enum is introduced as other I/O request type (read,
5
Acked-by: Markus Armbruster <armbru@redhat.com>
5
write, flush).
6
Message-Id: <20210824083856.17408-23-vsementsov@virtuozzo.com>
6
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Signed-off-by: Sam Li <faithilikerun@gmail.com>
8
Message-id: 20230407082528.18841-4-faithilikerun@gmail.com
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
10
---
9
qapi/block-core.json | 25 +++++++++++++++++++++++--
11
qapi/block-core.json | 68 ++++++++++++++++++++++++++++++++------
10
1 file changed, 23 insertions(+), 2 deletions(-)
12
qapi/block.json | 4 +++
13
include/block/accounting.h | 1 +
14
block/qapi-sysemu.c | 11 ++++++
15
block/qapi.c | 18 ++++++++++
16
hw/block/virtio-blk.c | 4 +++
17
6 files changed, 95 insertions(+), 11 deletions(-)
11
18
12
diff --git a/qapi/block-core.json b/qapi/block-core.json
19
diff --git a/qapi/block-core.json b/qapi/block-core.json
13
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
14
--- a/qapi/block-core.json
21
--- a/qapi/block-core.json
15
+++ b/qapi/block-core.json
22
+++ b/qapi/block-core.json
16
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
17
# @blklogwrites: Since 3.0
24
# @min_wr_latency_ns: Minimum latency of write operations in the
18
# @blkreplay: Since 4.2
25
# defined interval, in nanoseconds.
19
# @compress: Since 5.0
26
#
20
+# @copy-before-write: Since 6.2
27
+# @min_zone_append_latency_ns: Minimum latency of zone append operations
21
#
28
+# in the defined interval, in nanoseconds
22
# Since: 2.9
29
+# (since 8.1)
30
+#
31
# @min_flush_latency_ns: Minimum latency of flush operations in the
32
# defined interval, in nanoseconds.
33
#
34
@@ -XXX,XX +XXX,XX @@
35
# @max_wr_latency_ns: Maximum latency of write operations in the
36
# defined interval, in nanoseconds.
37
#
38
+# @max_zone_append_latency_ns: Maximum latency of zone append operations
39
+# in the defined interval, in nanoseconds
40
+# (since 8.1)
41
+#
42
# @max_flush_latency_ns: Maximum latency of flush operations in the
43
# defined interval, in nanoseconds.
44
#
45
@@ -XXX,XX +XXX,XX @@
46
# @avg_wr_latency_ns: Average latency of write operations in the
47
# defined interval, in nanoseconds.
48
#
49
+# @avg_zone_append_latency_ns: Average latency of zone append operations
50
+# in the defined interval, in nanoseconds
51
+# (since 8.1)
52
+#
53
# @avg_flush_latency_ns: Average latency of flush operations in the
54
# defined interval, in nanoseconds.
55
#
56
@@ -XXX,XX +XXX,XX @@
57
# @avg_wr_queue_depth: Average number of pending write operations
58
# in the defined interval.
59
#
60
+# @avg_zone_append_queue_depth: Average number of pending zone append
61
+# operations in the defined interval
62
+# (since 8.1).
63
+#
64
# Since: 2.5
23
##
65
##
24
{ 'enum': 'BlockdevDriver',
66
{ 'struct': 'BlockDeviceTimedStats',
25
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
67
'data': { 'interval_length': 'int', 'min_rd_latency_ns': 'int',
26
- 'cloop', 'compress', 'copy-on-read', 'dmg', 'file', 'ftp', 'ftps',
68
'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int',
27
- 'gluster',
69
'min_wr_latency_ns': 'int', 'max_wr_latency_ns': 'int',
28
+ 'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg',
70
- 'avg_wr_latency_ns': 'int', 'min_flush_latency_ns': 'int',
29
+ 'file', 'ftp', 'ftps', 'gluster',
71
- 'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int',
30
{'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
72
- 'avg_rd_queue_depth': 'number', 'avg_wr_queue_depth': 'number' } }
31
{'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
73
+ 'avg_wr_latency_ns': 'int', 'min_zone_append_latency_ns': 'int',
32
'http', 'https', 'iscsi',
74
+ 'max_zone_append_latency_ns': 'int',
33
@@ -XXX,XX +XXX,XX @@
75
+ 'avg_zone_append_latency_ns': 'int',
34
'base': 'BlockdevOptionsGenericFormat',
76
+ 'min_flush_latency_ns': 'int', 'max_flush_latency_ns': 'int',
35
'data': { '*bottom': 'str' } }
77
+ 'avg_flush_latency_ns': 'int', 'avg_rd_queue_depth': 'number',
36
78
+ 'avg_wr_queue_depth': 'number',
37
+##
79
+ 'avg_zone_append_queue_depth': 'number' } }
38
+# @BlockdevOptionsCbw:
80
39
+#
81
##
40
+# Driver specific block device options for the copy-before-write driver,
82
# @BlockDeviceStats:
41
+# which does so called copy-before-write operations: when data is
83
@@ -XXX,XX +XXX,XX @@
42
+# written to the filter, the filter first reads corresponding blocks
84
#
43
+# from its file child and copies them to @target child. After successfully
85
# @wr_bytes: The number of bytes written by the device.
44
+# copying, the write request is propagated to file child. If copying
86
#
45
+# fails, the original write request is failed too and no data is written
87
+# @zone_append_bytes: The number of bytes appended by the zoned devices
46
+# to file child.
88
+# (since 8.1)
47
+#
89
+#
48
+# @target: The target for copy-before-write operations.
90
# @unmap_bytes: The number of bytes unmapped by the device (Since 4.2)
49
+#
91
#
50
+# Since: 6.2
92
# @rd_operations: The number of read operations performed by the device.
51
+##
93
#
52
+{ 'struct': 'BlockdevOptionsCbw',
94
# @wr_operations: The number of write operations performed by the device.
53
+ 'base': 'BlockdevOptionsGenericFormat',
95
#
54
+ 'data': { 'target': 'BlockdevRef' } }
96
+# @zone_append_operations: The number of zone append operations performed
97
+# by the zoned devices (since 8.1)
98
+#
99
# @flush_operations: The number of cache flush operations performed by the
100
# device (since 0.15)
101
#
102
@@ -XXX,XX +XXX,XX @@
103
#
104
# @wr_total_time_ns: Total time spent on writes in nanoseconds (since 0.15).
105
#
106
+# @zone_append_total_time_ns: Total time spent on zone append writes
107
+# in nanoseconds (since 8.1)
108
+#
109
# @flush_total_time_ns: Total time spent on cache flushes in nanoseconds
110
# (since 0.15).
111
#
112
@@ -XXX,XX +XXX,XX @@
113
# @wr_merged: Number of write requests that have been merged into another
114
# request (Since 2.3).
115
#
116
+# @zone_append_merged: Number of zone append requests that have been merged
117
+# into another request (since 8.1)
118
+#
119
# @unmap_merged: Number of unmap requests that have been merged into another
120
# request (Since 4.2)
121
#
122
@@ -XXX,XX +XXX,XX @@
123
# @failed_wr_operations: The number of failed write operations
124
# performed by the device (Since 2.5)
125
#
126
+# @failed_zone_append_operations: The number of failed zone append write
127
+# operations performed by the zoned devices
128
+# (since 8.1)
129
+#
130
# @failed_flush_operations: The number of failed flush operations
131
# performed by the device (Since 2.5)
132
#
133
@@ -XXX,XX +XXX,XX @@
134
# @invalid_wr_operations: The number of invalid write operations
135
# performed by the device (Since 2.5)
136
#
137
+# @invalid_zone_append_operations: The number of invalid zone append operations
138
+# performed by the zoned device (since 8.1)
139
+#
140
# @invalid_flush_operations: The number of invalid flush operations
141
# performed by the device (Since 2.5)
142
#
143
@@ -XXX,XX +XXX,XX @@
144
#
145
# @wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
146
#
147
+# @zone_append_latency_histogram: @BlockLatencyHistogramInfo. (since 8.1)
148
+#
149
# @flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 4.0)
150
#
151
# Since: 0.14
152
##
153
{ 'struct': 'BlockDeviceStats',
154
- 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'unmap_bytes' : 'int',
155
- 'rd_operations': 'int', 'wr_operations': 'int',
156
+ 'data': {'rd_bytes': 'int', 'wr_bytes': 'int', 'zone_append_bytes': 'int',
157
+ 'unmap_bytes' : 'int', 'rd_operations': 'int',
158
+ 'wr_operations': 'int', 'zone_append_operations': 'int',
159
'flush_operations': 'int', 'unmap_operations': 'int',
160
'rd_total_time_ns': 'int', 'wr_total_time_ns': 'int',
161
- 'flush_total_time_ns': 'int', 'unmap_total_time_ns': 'int',
162
- 'wr_highest_offset': 'int',
163
- 'rd_merged': 'int', 'wr_merged': 'int', 'unmap_merged': 'int',
164
- '*idle_time_ns': 'int',
165
+ 'zone_append_total_time_ns': 'int', 'flush_total_time_ns': 'int',
166
+ 'unmap_total_time_ns': 'int', 'wr_highest_offset': 'int',
167
+ 'rd_merged': 'int', 'wr_merged': 'int', 'zone_append_merged': 'int',
168
+ 'unmap_merged': 'int', '*idle_time_ns': 'int',
169
'failed_rd_operations': 'int', 'failed_wr_operations': 'int',
170
- 'failed_flush_operations': 'int', 'failed_unmap_operations': 'int',
171
- 'invalid_rd_operations': 'int', 'invalid_wr_operations': 'int',
172
+ 'failed_zone_append_operations': 'int',
173
+ 'failed_flush_operations': 'int',
174
+ 'failed_unmap_operations': 'int', 'invalid_rd_operations': 'int',
175
+ 'invalid_wr_operations': 'int',
176
+ 'invalid_zone_append_operations': 'int',
177
'invalid_flush_operations': 'int', 'invalid_unmap_operations': 'int',
178
'account_invalid': 'bool', 'account_failed': 'bool',
179
'timed_stats': ['BlockDeviceTimedStats'],
180
'*rd_latency_histogram': 'BlockLatencyHistogramInfo',
181
'*wr_latency_histogram': 'BlockLatencyHistogramInfo',
182
+ '*zone_append_latency_histogram': 'BlockLatencyHistogramInfo',
183
'*flush_latency_histogram': 'BlockLatencyHistogramInfo' } }
184
185
##
186
diff --git a/qapi/block.json b/qapi/block.json
187
index XXXXXXX..XXXXXXX 100644
188
--- a/qapi/block.json
189
+++ b/qapi/block.json
190
@@ -XXX,XX +XXX,XX @@
191
# @boundaries-write: list of interval boundary values for write latency
192
# histogram.
193
#
194
+# @boundaries-zap: list of interval boundary values for zone append write
195
+# latency histogram.
196
+#
197
# @boundaries-flush: list of interval boundary values for flush latency
198
# histogram.
199
#
200
@@ -XXX,XX +XXX,XX @@
201
'*boundaries': ['uint64'],
202
'*boundaries-read': ['uint64'],
203
'*boundaries-write': ['uint64'],
204
+ '*boundaries-zap': ['uint64'],
205
'*boundaries-flush': ['uint64'] },
206
'allow-preconfig': true }
207
diff --git a/include/block/accounting.h b/include/block/accounting.h
208
index XXXXXXX..XXXXXXX 100644
209
--- a/include/block/accounting.h
210
+++ b/include/block/accounting.h
211
@@ -XXX,XX +XXX,XX @@ enum BlockAcctType {
212
BLOCK_ACCT_READ,
213
BLOCK_ACCT_WRITE,
214
BLOCK_ACCT_FLUSH,
215
+ BLOCK_ACCT_ZONE_APPEND,
216
BLOCK_ACCT_UNMAP,
217
BLOCK_MAX_IOTYPE,
218
};
219
diff --git a/block/qapi-sysemu.c b/block/qapi-sysemu.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/block/qapi-sysemu.c
222
+++ b/block/qapi-sysemu.c
223
@@ -XXX,XX +XXX,XX @@ void qmp_block_latency_histogram_set(
224
bool has_boundaries, uint64List *boundaries,
225
bool has_boundaries_read, uint64List *boundaries_read,
226
bool has_boundaries_write, uint64List *boundaries_write,
227
+ bool has_boundaries_append, uint64List *boundaries_append,
228
bool has_boundaries_flush, uint64List *boundaries_flush,
229
Error **errp)
230
{
231
@@ -XXX,XX +XXX,XX @@ void qmp_block_latency_histogram_set(
232
}
233
}
234
235
+ if (has_boundaries || has_boundaries_append) {
236
+ ret = block_latency_histogram_set(
237
+ stats, BLOCK_ACCT_ZONE_APPEND,
238
+ has_boundaries_append ? boundaries_append : boundaries);
239
+ if (ret) {
240
+ error_setg(errp, "Device '%s' set append write boundaries fail", id);
241
+ return;
242
+ }
243
+ }
55
+
244
+
56
##
245
if (has_boundaries || has_boundaries_flush) {
57
# @BlockdevOptions:
246
ret = block_latency_histogram_set(
58
#
247
stats, BLOCK_ACCT_FLUSH,
59
@@ -XXX,XX +XXX,XX @@
248
diff --git a/block/qapi.c b/block/qapi.c
60
'bochs': 'BlockdevOptionsGenericFormat',
249
index XXXXXXX..XXXXXXX 100644
61
'cloop': 'BlockdevOptionsGenericFormat',
250
--- a/block/qapi.c
62
'compress': 'BlockdevOptionsGenericFormat',
251
+++ b/block/qapi.c
63
+ 'copy-before-write':'BlockdevOptionsCbw',
252
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
64
'copy-on-read':'BlockdevOptionsCor',
253
65
'dmg': 'BlockdevOptionsGenericFormat',
254
ds->rd_bytes = stats->nr_bytes[BLOCK_ACCT_READ];
66
'file': 'BlockdevOptionsFile',
255
ds->wr_bytes = stats->nr_bytes[BLOCK_ACCT_WRITE];
256
+ ds->zone_append_bytes = stats->nr_bytes[BLOCK_ACCT_ZONE_APPEND];
257
ds->unmap_bytes = stats->nr_bytes[BLOCK_ACCT_UNMAP];
258
ds->rd_operations = stats->nr_ops[BLOCK_ACCT_READ];
259
ds->wr_operations = stats->nr_ops[BLOCK_ACCT_WRITE];
260
+ ds->zone_append_operations = stats->nr_ops[BLOCK_ACCT_ZONE_APPEND];
261
ds->unmap_operations = stats->nr_ops[BLOCK_ACCT_UNMAP];
262
263
ds->failed_rd_operations = stats->failed_ops[BLOCK_ACCT_READ];
264
ds->failed_wr_operations = stats->failed_ops[BLOCK_ACCT_WRITE];
265
+ ds->failed_zone_append_operations =
266
+ stats->failed_ops[BLOCK_ACCT_ZONE_APPEND];
267
ds->failed_flush_operations = stats->failed_ops[BLOCK_ACCT_FLUSH];
268
ds->failed_unmap_operations = stats->failed_ops[BLOCK_ACCT_UNMAP];
269
270
ds->invalid_rd_operations = stats->invalid_ops[BLOCK_ACCT_READ];
271
ds->invalid_wr_operations = stats->invalid_ops[BLOCK_ACCT_WRITE];
272
+ ds->invalid_zone_append_operations =
273
+ stats->invalid_ops[BLOCK_ACCT_ZONE_APPEND];
274
ds->invalid_flush_operations =
275
stats->invalid_ops[BLOCK_ACCT_FLUSH];
276
ds->invalid_unmap_operations = stats->invalid_ops[BLOCK_ACCT_UNMAP];
277
278
ds->rd_merged = stats->merged[BLOCK_ACCT_READ];
279
ds->wr_merged = stats->merged[BLOCK_ACCT_WRITE];
280
+ ds->zone_append_merged = stats->merged[BLOCK_ACCT_ZONE_APPEND];
281
ds->unmap_merged = stats->merged[BLOCK_ACCT_UNMAP];
282
ds->flush_operations = stats->nr_ops[BLOCK_ACCT_FLUSH];
283
ds->wr_total_time_ns = stats->total_time_ns[BLOCK_ACCT_WRITE];
284
+ ds->zone_append_total_time_ns =
285
+ stats->total_time_ns[BLOCK_ACCT_ZONE_APPEND];
286
ds->rd_total_time_ns = stats->total_time_ns[BLOCK_ACCT_READ];
287
ds->flush_total_time_ns = stats->total_time_ns[BLOCK_ACCT_FLUSH];
288
ds->unmap_total_time_ns = stats->total_time_ns[BLOCK_ACCT_UNMAP];
289
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
290
291
TimedAverage *rd = &ts->latency[BLOCK_ACCT_READ];
292
TimedAverage *wr = &ts->latency[BLOCK_ACCT_WRITE];
293
+ TimedAverage *zap = &ts->latency[BLOCK_ACCT_ZONE_APPEND];
294
TimedAverage *fl = &ts->latency[BLOCK_ACCT_FLUSH];
295
296
dev_stats->interval_length = ts->interval_length;
297
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
298
dev_stats->max_wr_latency_ns = timed_average_max(wr);
299
dev_stats->avg_wr_latency_ns = timed_average_avg(wr);
300
301
+ dev_stats->min_zone_append_latency_ns = timed_average_min(zap);
302
+ dev_stats->max_zone_append_latency_ns = timed_average_max(zap);
303
+ dev_stats->avg_zone_append_latency_ns = timed_average_avg(zap);
304
+
305
dev_stats->min_flush_latency_ns = timed_average_min(fl);
306
dev_stats->max_flush_latency_ns = timed_average_max(fl);
307
dev_stats->avg_flush_latency_ns = timed_average_avg(fl);
308
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
309
block_acct_queue_depth(ts, BLOCK_ACCT_READ);
310
dev_stats->avg_wr_queue_depth =
311
block_acct_queue_depth(ts, BLOCK_ACCT_WRITE);
312
+ dev_stats->avg_zone_append_queue_depth =
313
+ block_acct_queue_depth(ts, BLOCK_ACCT_ZONE_APPEND);
314
315
QAPI_LIST_PREPEND(ds->timed_stats, dev_stats);
316
}
317
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
318
= bdrv_latency_histogram_stats(&hgram[BLOCK_ACCT_READ]);
319
ds->wr_latency_histogram
320
= bdrv_latency_histogram_stats(&hgram[BLOCK_ACCT_WRITE]);
321
+ ds->zone_append_latency_histogram
322
+ = bdrv_latency_histogram_stats(&hgram[BLOCK_ACCT_ZONE_APPEND]);
323
ds->flush_latency_histogram
324
= bdrv_latency_histogram_stats(&hgram[BLOCK_ACCT_FLUSH]);
325
}
326
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
327
index XXXXXXX..XXXXXXX 100644
328
--- a/hw/block/virtio-blk.c
329
+++ b/hw/block/virtio-blk.c
330
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_zone_append(VirtIOBlockReq *req,
331
data->in_num = in_num;
332
data->zone_append_data.offset = offset;
333
qemu_iovec_init_external(&req->qiov, out_iov, out_num);
334
+
335
+ block_acct_start(blk_get_stats(s->blk), &req->acct, len,
336
+ BLOCK_ACCT_ZONE_APPEND);
337
+
338
blk_aio_zone_append(s->blk, &data->zone_append_data.offset, &req->qiov, 0,
339
virtio_blk_zone_append_complete, data);
340
return 0;
67
--
341
--
68
2.31.1
342
2.39.2
69
70
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
We are going to publish copy-before-write filter, and there no public
3
Signed-off-by: Sam Li <faithilikerun@gmail.com>
4
backing-child-based filter in Qemu. No reason to create a precedent, so
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
let's refactor copy-before-write filter instead.
5
Message-id: 20230407082528.18841-5-faithilikerun@gmail.com
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
---
8
hw/block/virtio-blk.c | 12 ++++++++++++
9
hw/block/trace-events | 7 +++++++
10
2 files changed, 19 insertions(+)
6
11
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <20210824083856.17408-13-vsementsov@virtuozzo.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
block/copy-before-write.c | 39 ++++++++++++++++++++++-----------------
13
1 file changed, 22 insertions(+), 17 deletions(-)
14
15
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/block/copy-before-write.c
14
--- a/hw/block/virtio-blk.c
18
+++ b/block/copy-before-write.c
15
+++ b/hw/block/virtio-blk.c
19
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_preadv(
16
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_zone_report_complete(void *opaque, int ret)
20
BlockDriverState *bs, uint64_t offset, uint64_t bytes,
17
int64_t nz = data->zone_report_data.nr_zones;
21
QEMUIOVector *qiov, int flags)
18
int8_t err_status = VIRTIO_BLK_S_OK;
19
20
+ trace_virtio_blk_zone_report_complete(vdev, req, nz, ret);
21
if (ret) {
22
err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
23
goto out;
24
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_handle_zone_report(VirtIOBlockReq *req,
25
nr_zones = (req->in_len - sizeof(struct virtio_blk_inhdr) -
26
sizeof(struct virtio_blk_zone_report)) /
27
sizeof(struct virtio_blk_zone_descriptor);
28
+ trace_virtio_blk_handle_zone_report(vdev, req,
29
+ offset >> BDRV_SECTOR_BITS, nr_zones);
30
31
zone_size = sizeof(BlockZoneDescriptor) * nr_zones;
32
data = g_malloc(sizeof(ZoneCmdData));
33
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_zone_mgmt_complete(void *opaque, int ret)
22
{
34
{
23
- return bdrv_co_preadv(bs->backing, offset, bytes, qiov, flags);
35
VirtIOBlockReq *req = opaque;
24
+ return bdrv_co_preadv(bs->file, offset, bytes, qiov, flags);
36
VirtIOBlock *s = req->dev;
25
}
37
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
26
38
int8_t err_status = VIRTIO_BLK_S_OK;
27
static coroutine_fn int cbw_do_copy_before_write(BlockDriverState *bs,
39
+ trace_virtio_blk_zone_mgmt_complete(vdev, req,ret);
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pdiscard(BlockDriverState *bs,
40
29
return ret;
41
if (ret) {
42
err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
43
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
44
/* Entire drive capacity */
45
offset = 0;
46
len = capacity;
47
+ trace_virtio_blk_handle_zone_reset_all(vdev, req, 0,
48
+ bs->total_sectors);
49
} else {
50
if (bs->bl.zone_size > capacity - offset) {
51
/* The zoned device allows the last smaller zone. */
52
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_zone_mgmt(VirtIOBlockReq *req, BlockZoneOp op)
53
} else {
54
len = bs->bl.zone_size;
55
}
56
+ trace_virtio_blk_handle_zone_mgmt(vdev, req, op,
57
+ offset >> BDRV_SECTOR_BITS,
58
+ len >> BDRV_SECTOR_BITS);
30
}
59
}
31
60
32
- return bdrv_co_pdiscard(bs->backing, offset, bytes);
61
if (!check_zoned_request(s, offset, len, false, &err_status)) {
33
+ return bdrv_co_pdiscard(bs->file, offset, bytes);
62
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_zone_append_complete(void *opaque, int ret)
34
}
63
err_status = VIRTIO_BLK_S_ZONE_INVALID_CMD;
35
64
goto out;
36
static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn cbw_co_pwrite_zeroes(BlockDriverState *bs,
38
return ret;
39
}
65
}
40
66
+ trace_virtio_blk_zone_append_complete(vdev, req, append_sector, ret);
41
- return bdrv_co_pwrite_zeroes(bs->backing, offset, bytes, flags);
67
42
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
68
out:
43
}
69
aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
44
70
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_zone_append(VirtIOBlockReq *req,
45
static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
71
int64_t offset = virtio_ldq_p(vdev, &req->out.sector) << BDRV_SECTOR_BITS;
46
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int cbw_co_pwritev(BlockDriverState *bs,
72
int64_t len = iov_size(out_iov, out_num);
47
return ret;
73
74
+ trace_virtio_blk_handle_zone_append(vdev, req, offset >> BDRV_SECTOR_BITS);
75
if (!check_zoned_request(s, offset, len, true, &err_status)) {
76
goto out;
48
}
77
}
49
78
diff --git a/hw/block/trace-events b/hw/block/trace-events
50
- return bdrv_co_pwritev(bs->backing, offset, bytes, qiov, flags);
79
index XXXXXXX..XXXXXXX 100644
51
+ return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
80
--- a/hw/block/trace-events
52
}
81
+++ b/hw/block/trace-events
53
82
@@ -XXX,XX +XXX,XX @@ pflash_write_unknown(const char *name, uint8_t cmd) "%s: unknown command 0x%02x"
54
static int coroutine_fn cbw_co_flush(BlockDriverState *bs)
83
# virtio-blk.c
55
{
84
virtio_blk_req_complete(void *vdev, void *req, int status) "vdev %p req %p status %d"
56
- if (!bs->backing) {
85
virtio_blk_rw_complete(void *vdev, void *req, int ret) "vdev %p req %p ret %d"
57
+ if (!bs->file) {
86
+virtio_blk_zone_report_complete(void *vdev, void *req, unsigned int nr_zones, int ret) "vdev %p req %p nr_zones %u ret %d"
58
return 0;
87
+virtio_blk_zone_mgmt_complete(void *vdev, void *req, int ret) "vdev %p req %p ret %d"
59
}
88
+virtio_blk_zone_append_complete(void *vdev, void *req, int64_t sector, int ret) "vdev %p req %p, append sector 0x%" PRIx64 " ret %d"
60
89
virtio_blk_handle_write(void *vdev, void *req, uint64_t sector, size_t nsectors) "vdev %p req %p sector %"PRIu64" nsectors %zu"
61
- return bdrv_co_flush(bs->backing->bs);
90
virtio_blk_handle_read(void *vdev, void *req, uint64_t sector, size_t nsectors) "vdev %p req %p sector %"PRIu64" nsectors %zu"
62
+ return bdrv_co_flush(bs->file->bs);
91
virtio_blk_submit_multireq(void *vdev, void *mrb, int start, int num_reqs, uint64_t offset, size_t size, bool is_write) "vdev %p mrb %p start %d num_reqs %d offset %"PRIu64" size %zu is_write %d"
63
}
92
+virtio_blk_handle_zone_report(void *vdev, void *req, int64_t sector, unsigned int nr_zones) "vdev %p req %p sector 0x%" PRIx64 " nr_zones %u"
64
93
+virtio_blk_handle_zone_mgmt(void *vdev, void *req, uint8_t op, int64_t sector, int64_t len) "vdev %p req %p op 0x%x sector 0x%" PRIx64 " len 0x%" PRIx64 ""
65
static void cbw_refresh_filename(BlockDriverState *bs)
94
+virtio_blk_handle_zone_reset_all(void *vdev, void *req, int64_t sector, int64_t len) "vdev %p req %p sector 0x%" PRIx64 " cap 0x%" PRIx64 ""
66
{
95
+virtio_blk_handle_zone_append(void *vdev, void *req, int64_t sector) "vdev %p req %p, append sector 0x%" PRIx64 ""
67
- if (bs->backing == NULL) {
96
68
- /*
97
# hd-geometry.c
69
- * we can be here after failed bdrv_attach_child in
98
hd_geometry_lchs_guess(void *blk, int cyls, int heads, int secs) "blk %p LCHS %d %d %d"
70
- * bdrv_set_backing_hd
71
- */
72
- return;
73
- }
74
pstrcpy(bs->exact_filename, sizeof(bs->exact_filename),
75
- bs->backing->bs->filename);
76
+ bs->file->bs->filename);
77
}
78
79
static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
80
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
81
top = bdrv_new_open_driver(&bdrv_cbw_filter, filter_node_name,
82
BDRV_O_RDWR, errp);
83
if (!top) {
84
+ error_prepend(errp, "Cannot open driver: ");
85
return NULL;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
89
state->target = bdrv_attach_child(top, target, "target", &child_of_bds,
90
BDRV_CHILD_DATA, errp);
91
if (!state->target) {
92
+ error_prepend(errp, "Cannot attach target child: ");
93
+ bdrv_unref(top);
94
+ return NULL;
95
+ }
96
+
97
+ bdrv_ref(source);
98
+ top->file = bdrv_attach_child(top, source, "file", &child_of_bds,
99
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
100
+ errp);
101
+ if (!top->file) {
102
+ error_prepend(errp, "Cannot attach file child: ");
103
bdrv_unref(top);
104
return NULL;
105
}
106
107
bdrv_drained_begin(source);
108
109
- ret = bdrv_append(top, source, errp);
110
+ ret = bdrv_replace_node(source, top, errp);
111
if (ret < 0) {
112
error_prepend(errp, "Cannot append copy-before-write filter: ");
113
goto fail;
114
}
115
appended = true;
116
117
- state->bcs = block_copy_state_new(top->backing, state->target,
118
- false, compress, errp);
119
+ state->bcs = block_copy_state_new(top->file, state->target, false, compress,
120
+ errp);
121
if (!state->bcs) {
122
error_prepend(errp, "Cannot create block-copy-state: ");
123
goto fail;
124
--
99
--
125
2.31.1
100
2.39.2
126
127
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Refactor the function to replace child at last. Thus we don't need to
4
revert it and code is simplified.
5
6
block-copy state initialization being done before replacing the child
7
doesn't need any drained section.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <20210824083856.17408-14-vsementsov@virtuozzo.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
block/copy-before-write.c | 33 +++++++++++----------------------
15
1 file changed, 11 insertions(+), 22 deletions(-)
16
17
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/copy-before-write.c
20
+++ b/block/copy-before-write.c
21
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
22
int ret;
23
BDRVCopyBeforeWriteState *state;
24
BlockDriverState *top;
25
- bool appended = false;
26
27
assert(source->total_sectors == target->total_sectors);
28
29
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
30
BDRV_CHILD_DATA, errp);
31
if (!state->target) {
32
error_prepend(errp, "Cannot attach target child: ");
33
- bdrv_unref(top);
34
- return NULL;
35
+ goto fail;
36
}
37
38
bdrv_ref(source);
39
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
40
errp);
41
if (!top->file) {
42
error_prepend(errp, "Cannot attach file child: ");
43
- bdrv_unref(top);
44
- return NULL;
45
- }
46
-
47
- bdrv_drained_begin(source);
48
-
49
- ret = bdrv_replace_node(source, top, errp);
50
- if (ret < 0) {
51
- error_prepend(errp, "Cannot append copy-before-write filter: ");
52
goto fail;
53
}
54
- appended = true;
55
56
state->bcs = block_copy_state_new(top->file, state->target, false, compress,
57
errp);
58
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
59
error_prepend(errp, "Cannot create block-copy-state: ");
60
goto fail;
61
}
62
- *bcs = state->bcs;
63
64
+ bdrv_drained_begin(source);
65
+ ret = bdrv_replace_node(source, top, errp);
66
bdrv_drained_end(source);
67
+ if (ret < 0) {
68
+ error_prepend(errp, "Cannot append copy-before-write filter: ");
69
+ goto fail;
70
+ }
71
+
72
+ *bcs = state->bcs;
73
74
return top;
75
76
fail:
77
- if (appended) {
78
- bdrv_cbw_drop(top);
79
- } else {
80
- bdrv_unref(top);
81
- }
82
-
83
- bdrv_drained_end(source);
84
-
85
+ block_copy_state_free(state->bcs);
86
+ bdrv_unref(top);
87
return NULL;
88
}
89
90
--
91
2.31.1
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
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
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
Message-Id: <20210824083856.17408-18-vsementsov@virtuozzo.com>
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
---
8
block/copy-before-write.h | 1 -
9
block/backup.c | 2 +-
10
block/copy-before-write.c | 7 +++----
11
3 files changed, 4 insertions(+), 6 deletions(-)
12
13
diff --git a/block/copy-before-write.h b/block/copy-before-write.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/copy-before-write.h
16
+++ b/block/copy-before-write.h
17
@@ -XXX,XX +XXX,XX @@
18
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
19
BlockDriverState *target,
20
const char *filter_node_name,
21
- bool compress,
22
BlockCopyState **bcs,
23
Error **errp);
24
void bdrv_cbw_drop(BlockDriverState *bs);
25
diff --git a/block/backup.c b/block/backup.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/backup.c
28
+++ b/block/backup.c
29
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
30
goto error;
31
}
32
33
- cbw = bdrv_cbw_append(bs, target, filter_node_name, false, &bcs, errp);
34
+ cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp);
35
if (!cbw) {
36
goto error;
37
}
38
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/copy-before-write.c
41
+++ b/block/copy-before-write.c
42
@@ -XXX,XX +XXX,XX @@ static void cbw_child_perm(BlockDriverState *bs, BdrvChild *c,
43
}
44
45
static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
46
- BlockDriverState *target, bool compress, Error **errp)
47
+ BlockDriverState *target, Error **errp)
48
{
49
BDRVCopyBeforeWriteState *s = bs->opaque;
50
51
@@ -XXX,XX +XXX,XX @@ static int cbw_init(BlockDriverState *bs, BlockDriverState *source,
52
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
53
bs->file->bs->supported_zero_flags);
54
55
- s->bcs = block_copy_state_new(bs->file, s->target, false, compress, errp);
56
+ s->bcs = block_copy_state_new(bs->file, s->target, false, false, errp);
57
if (!s->bcs) {
58
error_prepend(errp, "Cannot create block-copy-state: ");
59
return -EINVAL;
60
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_cbw_filter = {
61
BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
62
BlockDriverState *target,
63
const char *filter_node_name,
64
- bool compress,
65
BlockCopyState **bcs,
66
Error **errp)
67
{
68
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source,
69
}
70
state = top->opaque;
71
72
- ret = cbw_init(top, source, target, compress, errp);
73
+ ret = cbw_init(top, source, target, errp);
74
if (ret < 0) {
75
goto fail;
76
}
77
--
78
2.31.1
79
80
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Now block-copy will crash if user don't set progress meter by
4
block_copy_set_progress_meter(). copy-before-write filter will be used
5
in separate of backup job, and it doesn't want any progress meter (for
6
now). So, allow not setting it.
7
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <20210824083856.17408-21-vsementsov@virtuozzo.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/block-copy.c | 18 +++++++++++-------
14
1 file changed, 11 insertions(+), 7 deletions(-)
15
16
diff --git a/block/block-copy.c b/block/block-copy.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/block-copy.c
19
+++ b/block/block-copy.c
20
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn block_copy_task_end(BlockCopyTask *task, int ret)
21
bdrv_set_dirty_bitmap(task->s->copy_bitmap, task->offset, task->bytes);
22
}
23
QLIST_REMOVE(task, list);
24
- progress_set_remaining(task->s->progress,
25
- bdrv_get_dirty_count(task->s->copy_bitmap) +
26
- task->s->in_flight_bytes);
27
+ if (task->s->progress) {
28
+ progress_set_remaining(task->s->progress,
29
+ bdrv_get_dirty_count(task->s->copy_bitmap) +
30
+ task->s->in_flight_bytes);
31
+ }
32
qemu_co_queue_restart_all(&task->wait_queue);
33
}
34
35
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int block_copy_task_entry(AioTask *task)
36
t->call_state->ret = ret;
37
t->call_state->error_is_read = error_is_read;
38
}
39
- } else {
40
+ } else if (s->progress) {
41
progress_work_done(s->progress, t->bytes);
42
}
43
}
44
@@ -XXX,XX +XXX,XX @@ int64_t block_copy_reset_unallocated(BlockCopyState *s,
45
if (!ret) {
46
qemu_co_mutex_lock(&s->lock);
47
bdrv_reset_dirty_bitmap(s->copy_bitmap, offset, bytes);
48
- progress_set_remaining(s->progress,
49
- bdrv_get_dirty_count(s->copy_bitmap) +
50
- s->in_flight_bytes);
51
+ if (s->progress) {
52
+ progress_set_remaining(s->progress,
53
+ bdrv_get_dirty_count(s->copy_bitmap) +
54
+ s->in_flight_bytes);
55
+ }
56
qemu_co_mutex_unlock(&s->lock);
57
}
58
59
--
60
2.31.1
61
62
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
- 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
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Sam Li <faithilikerun@gmail.com>
2
2
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
3
Add the documentation about the example of using virtio-blk driver
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
to pass the zoned block devices through to the guest.
5
Reviewed-by: John Snow <jsnow@redhat.com>
5
6
Message-Id: <20210824083856.17408-30-vsementsov@virtuozzo.com>
6
Signed-off-by: Sam Li <faithilikerun@gmail.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Message-id: 20230407082528.18841-6-faithilikerun@gmail.com
8
[Fix Sphinx indentation error by turning command-lines into
9
pre-formatted text.
10
--Stefan]
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
12
---
9
tests/qemu-iotests/iotests.py | 5 +++--
13
docs/devel/zoned-storage.rst | 25 ++++++++++++++++++++++---
10
1 file changed, 3 insertions(+), 2 deletions(-)
14
1 file changed, 22 insertions(+), 3 deletions(-)
11
15
12
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
16
diff --git a/docs/devel/zoned-storage.rst b/docs/devel/zoned-storage.rst
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/tests/qemu-iotests/iotests.py
18
--- a/docs/devel/zoned-storage.rst
15
+++ b/tests/qemu-iotests/iotests.py
19
+++ b/docs/devel/zoned-storage.rst
16
@@ -XXX,XX +XXX,XX @@ def resume_drive(self, drive: str) -> None:
20
@@ -XXX,XX +XXX,XX @@ When the BlockBackend's BlockLimits model reports a zoned storage device, users
17
self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')
21
like the virtio-blk emulation or the qemu-io-cmds.c utility can use block layer
18
22
APIs for zoned storage emulation or testing.
19
def hmp_qemu_io(self, drive: str, cmd: str,
23
20
- use_log: bool = False) -> QMPMessage:
24
-For example, to test zone_report on a null_blk device using qemu-io is:
21
+ use_log: bool = False, qdev: bool = False) -> QMPMessage:
25
-$ path/to/qemu-io --image-opts -n driver=host_device,filename=/dev/nullb0
22
"""Write to a given drive using an HMP command"""
26
--c "zrp offset nr_zones"
23
- return self.hmp(f'qemu-io {drive} "{cmd}"', use_log=use_log)
27
+For example, to test zone_report on a null_blk device using qemu-io is::
24
+ d = '-d ' if qdev else ''
28
+
25
+ return self.hmp(f'qemu-io {d}{drive} "{cmd}"', use_log=use_log)
29
+ $ path/to/qemu-io --image-opts -n driver=host_device,filename=/dev/nullb0 -c "zrp offset nr_zones"
26
30
+
27
def flatten_qmp_object(self, obj, output=None, basestr=''):
31
+To expose the host's zoned block device through virtio-blk, the command line
28
if output is None:
32
+can be (includes the -device parameter)::
33
+
34
+ -blockdev node-name=drive0,driver=host_device,filename=/dev/nullb0,cache.direct=on \
35
+ -device virtio-blk-pci,drive=drive0
36
+
37
+Or only use the -drive parameter::
38
+
39
+ -driver driver=host_device,file=/dev/nullb0,if=virtio,cache.direct=on
40
+
41
+Additionally, QEMU has several ways of supporting zoned storage, including:
42
+(1) Using virtio-scsi: --device scsi-block allows for the passing through of
43
+SCSI ZBC devices, enabling the attachment of ZBC or ZAC HDDs to QEMU.
44
+(2) PCI device pass-through: While NVMe ZNS emulation is available for testing
45
+purposes, it cannot yet pass through a zoned device from the host. To pass on
46
+the NVMe ZNS device to the guest, use VFIO PCI pass the entire NVMe PCI adapter
47
+through to the guest. Likewise, an HDD HBA can be passed on to QEMU all HDDs
48
+attached to the HBA.
29
--
49
--
30
2.31.1
50
2.39.2
31
32
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
From: Carlos Santos <casantos@redhat.com>
2
2
3
Give a good name to test file.
3
It is not useful when configuring with --enable-trace-backends=nop.
4
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
Signed-off-by: Carlos Santos <casantos@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Message-Id: <20210824083856.17408-29-vsementsov@virtuozzo.com>
7
Message-Id: <20230408010410.281263-1-casantos@redhat.com>
8
[hreitz: Adjust .gitlab-ci.d/buildtest.yml]
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
8
---
11
.gitlab-ci.d/buildtest.yml | 6 +++---
9
trace/meson.build | 2 +-
12
tests/qemu-iotests/{222 => tests/image-fleecing} | 0
10
1 file changed, 1 insertion(+), 1 deletion(-)
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
11
18
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
12
diff --git a/trace/meson.build b/trace/meson.build
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/.gitlab-ci.d/buildtest.yml
14
--- a/trace/meson.build
21
+++ b/.gitlab-ci.d/buildtest.yml
15
+++ b/trace/meson.build
22
@@ -XXX,XX +XXX,XX @@ build-tcg-disabled:
16
@@ -XXX,XX +XXX,XX @@ trace_events_all = custom_target('trace-events-all',
23
- cd tests/qemu-iotests/
17
input: trace_events_files,
24
- ./check -raw 001 002 003 004 005 008 009 010 011 012 021 025 032 033 048
18
command: [ 'cat', '@INPUT@' ],
25
052 063 077 086 101 104 106 113 148 150 151 152 157 159 160 163
19
capture: true,
26
- 170 171 183 184 192 194 208 221 222 226 227 236 253 277
20
- install: true,
27
+ 170 171 183 184 192 194 208 221 226 227 236 253 277 image-fleecing
21
+ install: get_option('trace_backends') != [ 'nop' ],
28
- ./check -qcow2 028 051 056 057 058 065 068 082 085 091 095 096 102 122
22
install_dir: qemu_datadir)
29
124 132 139 142 144 145 151 152 155 157 165 194 196 200 202
23
30
- 208 209 216 218 222 227 234 246 247 248 250 254 255 257 258
24
if 'ust' in get_option('trace_backends')
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
--
25
--
46
2.31.1
26
2.39.2
47
48
diff view generated by jsdifflib