1
The following changes since commit 16aaacb307ed607b9780c12702c44f0fe52edc7e:
1
The following changes since commit 67b6526cf042f22521feff5ea521a05d3dd2bf8f:
2
2
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200430' into staging (2020-04-30 14:00:36 +0100)
3
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging (2022-01-13 13:59:56 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to eaae29ef89d498d0eac553c77b554f310a47f809:
9
for you to fetch changes up to e5e748739562268ef4063ee77bf53ad7040b25c7:
10
10
11
qemu-storage-daemon: Fix non-string --object properties (2020-04-30 17:51:07 +0200)
11
iotests/testrunner.py: refactor test_field_width (2022-01-14 12:03:16 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- Fix resize (extending) of short overlays
16
- qemu-storage-daemon: Add vhost-user-blk help
17
- nvme: introduce PMR support from NVMe 1.4 spec
17
- block-backend: Fix use-after-free for BDS pointers after aio_poll()
18
- qemu-storage-daemon: Fix non-string --object properties
18
- qemu-img: Fix sparseness of output image with unaligned ranges
19
- vvfat: Fix crashes in read-write mode
20
- Fix device deletion events with -device JSON syntax
21
- Code cleanups
19
22
20
----------------------------------------------------------------
23
----------------------------------------------------------------
21
Alberto Garcia (1):
24
Daniel P. Berrangé (1):
22
qcow2: Add incompatibility note between backing files and raw external data files
25
softmmu: fix device deletion events with -device JSON syntax
23
26
24
Andrzej Jakowski (1):
27
Emanuele Giuseppe Esposito (3):
25
nvme: introduce PMR support from NVMe 1.4 spec
28
block_int: make bdrv_backing_overridden static
29
include/sysemu/blockdev.h: remove drive_mark_claimed_by_board and inline drive_def
30
include/sysemu/blockdev.h: remove drive_get_max_devs
26
31
27
Kevin Wolf (12):
32
Hanna Reitz (2):
28
block: Add flags to BlockDriver.bdrv_co_truncate()
33
iotests/stream-error-on-reset: New test
29
block: Add flags to bdrv(_co)_truncate()
34
iotests/308: Fix for CAP_DAC_OVERRIDE
30
block-backend: Add flags to blk_truncate()
31
qcow2: Support BDRV_REQ_ZERO_WRITE for truncate
32
raw-format: Support BDRV_REQ_ZERO_WRITE for truncate
33
file-posix: Support BDRV_REQ_ZERO_WRITE for truncate
34
block: truncate: Don't make backing file data visible
35
iotests: Filter testfiles out in filter_img_info()
36
iotests: Test committing to short backing file
37
qcow2: Forward ZERO_WRITE flag for full preallocation
38
qom: Factor out user_creatable_add_dict()
39
qemu-storage-daemon: Fix non-string --object properties
40
35
41
Paolo Bonzini (1):
36
Kevin Wolf (3):
42
qemu-iotests: allow qcow2 external discarded clusters to contain stale data
37
vvfat: Fix size of temporary qcow file
38
vvfat: Fix vvfat_write() for writes before the root directory
39
iotests: Test qemu-img convert of zeroed data cluster
43
40
44
docs/interop/qcow2.txt | 3 +
41
Philippe Mathieu-Daudé (3):
45
hw/block/nvme.h | 2 +
42
docs: Correct 'vhost-user-blk' spelling
46
include/block/block.h | 5 +-
43
qemu-storage-daemon: Add vhost-user-blk help
47
include/block/block_int.h | 10 +-
44
qapi/block: Restrict vhost-user-blk to CONFIG_VHOST_USER_BLK_SERVER
48
include/block/nvme.h | 172 ++++++++++++++++++++++++++
45
49
include/qom/object_interfaces.h | 16 +++
46
Stefan Hajnoczi (1):
50
include/sysemu/block-backend.h | 2 +-
47
block-backend: prevent dangling BDS pointers across aio_poll()
51
block.c | 3 +-
48
52
block/block-backend.c | 4 +-
49
Vladimir Sementsov-Ogievskiy (3):
53
block/commit.c | 4 +-
50
qemu-img: make is_allocated_sectors() more efficient
54
block/crypto.c | 7 +-
51
block: drop BLK_PERM_GRAPH_MOD
55
block/file-posix.c | 6 +-
52
iotests/testrunner.py: refactor test_field_width
56
block/file-win32.c | 2 +-
53
57
block/gluster.c | 1 +
54
qapi/block-core.json | 7 +-
58
block/io.c | 43 ++++++-
55
qapi/block-export.json | 6 +-
59
block/iscsi.c | 2 +-
56
qapi/qdev.json | 5 +-
60
block/mirror.c | 2 +-
57
docs/tools/qemu-storage-daemon.rst | 2 +-
61
block/nfs.c | 3 +-
58
include/block/block.h | 9 +-
62
block/parallels.c | 6 +-
59
include/block/block_int.h | 3 -
63
block/qcow.c | 4 +-
60
include/sysemu/blockdev.h | 3 -
64
block/qcow2-cluster.c | 2 +-
61
block.c | 11 +-
65
block/qcow2-refcount.c | 2 +-
62
block/block-backend.c | 19 ++-
66
block/qcow2.c | 73 +++++++++--
63
block/commit.c | 1 -
67
block/qed.c | 3 +-
64
block/mirror.c | 15 +--
68
block/raw-format.c | 6 +-
65
block/monitor/block-hmp-cmds.c | 2 +-
69
block/rbd.c | 1 +
66
block/vvfat.c | 37 ++++--
70
block/sheepdog.c | 4 +-
67
blockdev.c | 24 +---
71
block/ssh.c | 2 +-
68
hw/block/block.c | 3 +-
72
block/vdi.c | 2 +-
69
qemu-img.c | 23 +++-
73
block/vhdx-log.c | 2 +-
70
softmmu/vl.c | 8 +-
74
block/vhdx.c | 6 +-
71
storage-daemon/qemu-storage-daemon.c | 13 ++
75
block/vmdk.c | 8 +-
72
tests/qtest/device-plug-test.c | 19 +++
76
block/vpc.c | 2 +-
73
scripts/render_block_graph.py | 1 -
77
blockdev.c | 2 +-
74
tests/qemu-iotests/testrunner.py | 21 ++--
78
hw/block/nvme.c | 109 ++++++++++++++++
75
tests/qemu-iotests/122 | 1 +
79
qemu-img.c | 2 +-
76
tests/qemu-iotests/122.out | 2 +
80
qemu-io-cmds.c | 2 +-
77
tests/qemu-iotests/273.out | 4 -
81
qemu-storage-daemon.c | 4 +-
78
tests/qemu-iotests/308 | 25 +++-
82
qom/object_interfaces.c | 31 +++++
79
tests/qemu-iotests/308.out | 2 +-
83
qom/qom-qmp-cmds.c | 24 +---
80
tests/qemu-iotests/tests/stream-error-on-reset | 140 +++++++++++++++++++++
84
tests/test-block-iothread.c | 9 +-
81
tests/qemu-iotests/tests/stream-error-on-reset.out | 5 +
85
tests/qemu-iotests/iotests.py | 5 +-
82
28 files changed, 307 insertions(+), 104 deletions(-)
86
hw/block/Makefile.objs | 2 +-
83
create mode 100755 tests/qemu-iotests/tests/stream-error-on-reset
87
hw/block/trace-events | 4 +
84
create mode 100644 tests/qemu-iotests/tests/stream-error-on-reset.out
88
tests/qemu-iotests/244 | 10 +-
89
tests/qemu-iotests/244.out | 9 +-
90
tests/qemu-iotests/274 | 155 +++++++++++++++++++++++
91
tests/qemu-iotests/274.out | 268 ++++++++++++++++++++++++++++++++++++++++
92
tests/qemu-iotests/group | 1 +
93
49 files changed, 951 insertions(+), 96 deletions(-)
94
create mode 100755 tests/qemu-iotests/274
95
create mode 100644 tests/qemu-iotests/274.out
96
85
97
86
diff view generated by jsdifflib
1
This adds a new BdrvRequestFlags parameter to the .bdrv_co_truncate()
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
driver callbacks, and a supported_truncate_flags field in
3
BlockDriverState that allows drivers to advertise support for request
4
flags in the context of truncate.
5
2
6
For now, we always pass 0 and no drivers declare support for any flag.
3
bdrv_backing_overridden is only used in block.c, so there is
4
no need to leave it in block_int.h
7
5
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Message-Id: <20211215121140.456939-2-eesposit@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <20200424125448.63318-2-kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
10
---
15
include/block/block_int.h | 10 +++++++++-
11
include/block/block_int.h | 3 ---
16
block/crypto.c | 3 ++-
12
block.c | 4 +++-
17
block/file-posix.c | 2 +-
13
2 files changed, 3 insertions(+), 4 deletions(-)
18
block/file-win32.c | 2 +-
19
block/gluster.c | 1 +
20
block/io.c | 8 +++++++-
21
block/iscsi.c | 2 +-
22
block/nfs.c | 3 ++-
23
block/qcow2.c | 2 +-
24
block/qed.c | 1 +
25
block/raw-format.c | 2 +-
26
block/rbd.c | 1 +
27
block/sheepdog.c | 4 ++--
28
block/ssh.c | 2 +-
29
tests/test-block-iothread.c | 3 ++-
30
15 files changed, 33 insertions(+), 13 deletions(-)
31
14
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
15
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
17
--- a/include/block/block_int.h
35
+++ b/include/block/block_int.h
18
+++ b/include/block/block_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
19
@@ -XXX,XX +XXX,XX @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size,
37
*/
20
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
38
int coroutine_fn (*bdrv_co_truncate)(BlockDriverState *bs, int64_t offset,
21
QDict *options);
39
bool exact, PreallocMode prealloc,
22
40
- Error **errp);
23
-bool bdrv_backing_overridden(BlockDriverState *bs);
41
+ BdrvRequestFlags flags, Error **errp);
24
-
42
25
-
43
int64_t (*bdrv_getlength)(BlockDriverState *bs);
26
/**
44
bool has_variable_length;
27
* bdrv_add_aio_context_notifier:
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
28
*
46
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
29
diff --git a/block.c b/block.c
47
* BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
48
unsigned int supported_zero_flags;
49
+ /*
50
+ * Flags honoured during truncate (so far: BDRV_REQ_ZERO_WRITE).
51
+ *
52
+ * If BDRV_REQ_ZERO_WRITE is given, the truncate operation must make sure
53
+ * that any added space reads as all zeros. If this can't be guaranteed,
54
+ * the operation must fail.
55
+ */
56
+ unsigned int supported_truncate_flags;
57
58
/* the following member gives a name to every node on the bs graph. */
59
char node_name[32];
60
diff --git a/block/crypto.c b/block/crypto.c
61
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
62
--- a/block/crypto.c
31
--- a/block.c
63
+++ b/block/crypto.c
32
+++ b/block.c
64
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
33
@@ -XXX,XX +XXX,XX @@ static int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
65
34
static void bdrv_reopen_commit(BDRVReopenState *reopen_state);
66
static int coroutine_fn
35
static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
67
block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
36
68
- PreallocMode prealloc, Error **errp)
37
+static bool bdrv_backing_overridden(BlockDriverState *bs);
69
+ PreallocMode prealloc, BdrvRequestFlags flags,
38
+
70
+ Error **errp)
39
/* If non-zero, use only whitelisted block drivers */
40
static int use_bdrv_whitelist;
41
42
@@ -XXX,XX +XXX,XX @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs)
43
/* Note: This function may return false positives; it may return true
44
* even if opening the backing file specified by bs's image header
45
* would result in exactly bs->backing. */
46
-bool bdrv_backing_overridden(BlockDriverState *bs)
47
+static bool bdrv_backing_overridden(BlockDriverState *bs)
71
{
48
{
72
BlockCrypto *crypto = bs->opaque;
49
if (bs->backing) {
73
uint64_t payload_offset =
50
return strcmp(bs->auto_backing_file,
74
diff --git a/block/file-posix.c b/block/file-posix.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/file-posix.c
77
+++ b/block/file-posix.c
78
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
79
80
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
81
bool exact, PreallocMode prealloc,
82
- Error **errp)
83
+ BdrvRequestFlags flags, Error **errp)
84
{
85
BDRVRawState *s = bs->opaque;
86
struct stat st;
87
diff --git a/block/file-win32.c b/block/file-win32.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/file-win32.c
90
+++ b/block/file-win32.c
91
@@ -XXX,XX +XXX,XX @@ static void raw_close(BlockDriverState *bs)
92
93
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
94
bool exact, PreallocMode prealloc,
95
- Error **errp)
96
+ BdrvRequestFlags flags, Error **errp)
97
{
98
BDRVRawState *s = bs->opaque;
99
LONG low, high;
100
diff --git a/block/gluster.c b/block/gluster.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/gluster.c
103
+++ b/block/gluster.c
104
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
105
int64_t offset,
106
bool exact,
107
PreallocMode prealloc,
108
+ BdrvRequestFlags flags,
109
Error **errp)
110
{
111
BDRVGlusterState *s = bs->opaque;
112
diff --git a/block/io.c b/block/io.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/block/io.c
115
+++ b/block/io.c
116
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
117
BlockDriverState *bs = child->bs;
118
BlockDriver *drv = bs->drv;
119
BdrvTrackedRequest req;
120
+ BdrvRequestFlags flags = 0;
121
int64_t old_size, new_bytes;
122
int ret;
123
124
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
125
}
126
127
if (drv->bdrv_co_truncate) {
128
- ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, errp);
129
+ if (flags & ~bs->supported_truncate_flags) {
130
+ error_setg(errp, "Block driver does not support requested flags");
131
+ ret = -ENOTSUP;
132
+ goto out;
133
+ }
134
+ ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
135
} else if (bs->file && drv->is_filter) {
136
ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
137
} else {
138
diff --git a/block/iscsi.c b/block/iscsi.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/iscsi.c
141
+++ b/block/iscsi.c
142
@@ -XXX,XX +XXX,XX @@ static void iscsi_reopen_commit(BDRVReopenState *reopen_state)
143
144
static int coroutine_fn iscsi_co_truncate(BlockDriverState *bs, int64_t offset,
145
bool exact, PreallocMode prealloc,
146
- Error **errp)
147
+ BdrvRequestFlags flags, Error **errp)
148
{
149
IscsiLun *iscsilun = bs->opaque;
150
int64_t cur_length;
151
diff --git a/block/nfs.c b/block/nfs.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/block/nfs.c
154
+++ b/block/nfs.c
155
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_get_allocated_file_size(BlockDriverState *bs)
156
157
static int coroutine_fn
158
nfs_file_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
159
- PreallocMode prealloc, Error **errp)
160
+ PreallocMode prealloc, BdrvRequestFlags flags,
161
+ Error **errp)
162
{
163
NFSClient *client = bs->opaque;
164
int ret;
165
diff --git a/block/qcow2.c b/block/qcow2.c
166
index XXXXXXX..XXXXXXX 100644
167
--- a/block/qcow2.c
168
+++ b/block/qcow2.c
169
@@ -XXX,XX +XXX,XX @@ fail:
170
171
static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
172
bool exact, PreallocMode prealloc,
173
- Error **errp)
174
+ BdrvRequestFlags flags, Error **errp)
175
{
176
BDRVQcow2State *s = bs->opaque;
177
uint64_t old_length;
178
diff --git a/block/qed.c b/block/qed.c
179
index XXXXXXX..XXXXXXX 100644
180
--- a/block/qed.c
181
+++ b/block/qed.c
182
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_truncate(BlockDriverState *bs,
183
int64_t offset,
184
bool exact,
185
PreallocMode prealloc,
186
+ BdrvRequestFlags flags,
187
Error **errp)
188
{
189
BDRVQEDState *s = bs->opaque;
190
diff --git a/block/raw-format.c b/block/raw-format.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/raw-format.c
193
+++ b/block/raw-format.c
194
@@ -XXX,XX +XXX,XX @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
195
196
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
197
bool exact, PreallocMode prealloc,
198
- Error **errp)
199
+ BdrvRequestFlags flags, Error **errp)
200
{
201
BDRVRawState *s = bs->opaque;
202
203
diff --git a/block/rbd.c b/block/rbd.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/block/rbd.c
206
+++ b/block/rbd.c
207
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qemu_rbd_co_truncate(BlockDriverState *bs,
208
int64_t offset,
209
bool exact,
210
PreallocMode prealloc,
211
+ BdrvRequestFlags flags,
212
Error **errp)
213
{
214
int r;
215
diff --git a/block/sheepdog.c b/block/sheepdog.c
216
index XXXXXXX..XXXXXXX 100644
217
--- a/block/sheepdog.c
218
+++ b/block/sheepdog.c
219
@@ -XXX,XX +XXX,XX @@ static int64_t sd_getlength(BlockDriverState *bs)
220
221
static int coroutine_fn sd_co_truncate(BlockDriverState *bs, int64_t offset,
222
bool exact, PreallocMode prealloc,
223
- Error **errp)
224
+ BdrvRequestFlags flags, Error **errp)
225
{
226
BDRVSheepdogState *s = bs->opaque;
227
int ret, fd;
228
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
229
230
assert(!flags);
231
if (offset > s->inode.vdi_size) {
232
- ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, NULL);
233
+ ret = sd_co_truncate(bs, offset, false, PREALLOC_MODE_OFF, 0, NULL);
234
if (ret < 0) {
235
return ret;
236
}
237
diff --git a/block/ssh.c b/block/ssh.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/block/ssh.c
240
+++ b/block/ssh.c
241
@@ -XXX,XX +XXX,XX @@ static int64_t ssh_getlength(BlockDriverState *bs)
242
243
static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset,
244
bool exact, PreallocMode prealloc,
245
- Error **errp)
246
+ BdrvRequestFlags flags, Error **errp)
247
{
248
BDRVSSHState *s = bs->opaque;
249
250
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tests/test-block-iothread.c
253
+++ b/tests/test-block-iothread.c
254
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_test_co_pdiscard(BlockDriverState *bs,
255
256
static int coroutine_fn
257
bdrv_test_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
258
- PreallocMode prealloc, Error **errp)
259
+ PreallocMode prealloc, BdrvRequestFlags flags,
260
+ Error **errp)
261
{
262
return 0;
263
}
264
--
51
--
265
2.25.3
52
2.31.1
266
53
267
54
diff view generated by jsdifflib
1
The QMP handler qmp_object_add() and the implementation of --object in
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
qemu-storage-daemon can share most of the code. Currently,
3
qemu-storage-daemon calls qmp_object_add(), but this is not correct
4
because different visitors need to be used.
5
2
6
As a first step towards a fix, make qmp_object_add() a wrapper around a
3
drive_def is only a particular use case of
7
new function user_creatable_add_dict() that can get an additional
4
qemu_opts_parse_noisily, so it can be inlined.
8
parameter. The handling of "props" is only required for compatibility
9
and not required for the qemu-storage-daemon command line, so it stays
10
in qmp_object_add().
11
5
6
Also remove drive_mark_claimed_by_board, as it is only defined
7
but not implemented (nor used) anywhere.
8
9
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
10
Message-Id: <20211215121140.456939-3-eesposit@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
12
---
14
include/qom/object_interfaces.h | 12 ++++++++++++
13
include/sysemu/blockdev.h | 2 --
15
qom/object_interfaces.c | 27 +++++++++++++++++++++++++++
14
block/monitor/block-hmp-cmds.c | 2 +-
16
qom/qom-qmp-cmds.c | 24 +-----------------------
15
blockdev.c | 7 +------
17
3 files changed, 40 insertions(+), 23 deletions(-)
16
softmmu/vl.c | 4 +++-
17
4 files changed, 5 insertions(+), 10 deletions(-)
18
18
19
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
19
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/qom/object_interfaces.h
21
--- a/include/sysemu/blockdev.h
22
+++ b/include/qom/object_interfaces.h
22
+++ b/include/sysemu/blockdev.h
23
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
23
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo);
24
const QDict *qdict,
24
void override_max_devs(BlockInterfaceType type, int max_devs);
25
Visitor *v, Error **errp);
25
26
26
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
27
+/**
27
-void drive_mark_claimed_by_board(void);
28
+ * user_creatable_add_dict:
28
void drive_check_orphaned(void);
29
+ * @qdict: the object definition
29
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
30
+ * @errp: if an error occurs, a pointer to an area to store the error
30
int drive_get_max_bus(BlockInterfaceType type);
31
+ *
31
int drive_get_max_devs(BlockInterfaceType type);
32
+ * Create an instance of the user creatable object that is defined by
32
33
+ * @qdict. The object type is taken from the QDict key 'qom-type', its
33
-QemuOpts *drive_def(const char *optstr);
34
+ * ID from the key 'id'. The remaining entries in @qdict are used to
34
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
35
+ * initialize the object properties.
35
const char *optstr);
36
+ */
36
DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type,
37
+void user_creatable_add_dict(QDict *qdict, Error **errp);
37
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
38
+
39
/**
40
* user_creatable_add_opts:
41
* @opts: the object definition
42
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
43
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
44
--- a/qom/object_interfaces.c
39
--- a/block/monitor/block-hmp-cmds.c
45
+++ b/qom/object_interfaces.c
40
+++ b/block/monitor/block-hmp-cmds.c
46
@@ -XXX,XX +XXX,XX @@
41
@@ -XXX,XX +XXX,XX @@ void hmp_drive_add(Monitor *mon, const QDict *qdict)
47
#include "qapi/qmp/qerror.h"
42
return;
48
#include "qapi/qmp/qjson.h"
43
}
49
#include "qapi/qmp/qstring.h"
44
50
+#include "qapi/qobject-input-visitor.h"
45
- opts = drive_def(optstr);
51
#include "qom/object_interfaces.h"
46
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
52
#include "qemu/help_option.h"
47
if (!opts)
53
#include "qemu/module.h"
48
return;
54
@@ -XXX,XX +XXX,XX @@ out:
49
55
return obj;
50
diff --git a/blockdev.c b/blockdev.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/blockdev.c
53
+++ b/blockdev.c
54
@@ -XXX,XX +XXX,XX @@ static int drive_index_to_unit_id(BlockInterfaceType type, int index)
55
return max_devs ? index % max_devs : index;
56
}
56
}
57
57
58
+void user_creatable_add_dict(QDict *qdict, Error **errp)
58
-QemuOpts *drive_def(const char *optstr)
59
+{
59
-{
60
+ Visitor *v;
60
- return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
61
+ Object *obj;
61
-}
62
+ g_autofree char *type = NULL;
62
-
63
+ g_autofree char *id = NULL;
63
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
64
+
64
const char *optstr)
65
+ type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
66
+ if (!type) {
67
+ error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
68
+ return;
69
+ }
70
+ qdict_del(qdict, "qom-type");
71
+
72
+ id = g_strdup(qdict_get_try_str(qdict, "id"));
73
+ if (!id) {
74
+ error_setg(errp, QERR_MISSING_PARAMETER, "id");
75
+ return;
76
+ }
77
+ qdict_del(qdict, "id");
78
+
79
+ v = qobject_input_visitor_new(QOBJECT(qdict));
80
+ obj = user_creatable_add_type(type, id, qdict, v, errp);
81
+ visit_free(v);
82
+ object_unref(obj);
83
+}
84
85
Object *user_creatable_add_opts(QemuOpts *opts, Error **errp)
86
{
65
{
87
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
66
QemuOpts *opts;
67
68
- opts = drive_def(optstr);
69
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false);
70
if (!opts) {
71
return NULL;
72
}
73
diff --git a/softmmu/vl.c b/softmmu/vl.c
88
index XXXXXXX..XXXXXXX 100644
74
index XXXXXXX..XXXXXXX 100644
89
--- a/qom/qom-qmp-cmds.c
75
--- a/softmmu/vl.c
90
+++ b/qom/qom-qmp-cmds.c
76
+++ b/softmmu/vl.c
91
@@ -XXX,XX +XXX,XX @@
77
@@ -XXX,XX +XXX,XX @@ void qemu_init(int argc, char **argv, char **envp)
92
#include "qapi/qapi-commands-qom.h"
78
break;
93
#include "qapi/qmp/qdict.h"
79
}
94
#include "qapi/qmp/qerror.h"
80
case QEMU_OPTION_drive:
95
-#include "qapi/qobject-input-visitor.h"
81
- if (drive_def(optarg) == NULL) {
96
#include "qemu/cutils.h"
82
+ opts = qemu_opts_parse_noisily(qemu_find_opts("drive"),
97
#include "qom/object_interfaces.h"
83
+ optarg, false);
98
#include "qom/qom-qobject.h"
84
+ if (opts == NULL) {
99
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
85
exit(1);
100
{
86
}
101
QObject *props;
87
break;
102
QDict *pdict;
103
- Visitor *v;
104
- Object *obj;
105
- g_autofree char *type = NULL;
106
- g_autofree char *id = NULL;
107
-
108
- type = g_strdup(qdict_get_try_str(qdict, "qom-type"));
109
- if (!type) {
110
- error_setg(errp, QERR_MISSING_PARAMETER, "qom-type");
111
- return;
112
- }
113
- qdict_del(qdict, "qom-type");
114
-
115
- id = g_strdup(qdict_get_try_str(qdict, "id"));
116
- if (!id) {
117
- error_setg(errp, QERR_MISSING_PARAMETER, "id");
118
- return;
119
- }
120
- qdict_del(qdict, "id");
121
122
props = qdict_get(qdict, "props");
123
if (props) {
124
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
125
qobject_unref(pdict);
126
}
127
128
- v = qobject_input_visitor_new(QOBJECT(qdict));
129
- obj = user_creatable_add_type(type, id, qdict, v, errp);
130
- visit_free(v);
131
- object_unref(obj);
132
+ user_creatable_add_dict(qdict, errp);
133
}
134
135
void qmp_object_del(const char *id, Error **errp)
136
--
88
--
137
2.25.3
89
2.31.1
138
90
139
91
diff view generated by jsdifflib
1
After processing the option string with the keyval parser, we get a
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
QDict that contains only strings. This QDict must be fed to a keyval
3
visitor which converts the strings into the right data types.
4
2
5
qmp_object_add(), however, uses the normal QObject input visitor, which
3
Remove drive_get_max_devs, as it is not used by anyone.
6
expects a QDict where all properties already have the QType that matches
7
the data type required by the QOM object type.
8
4
9
Change the --object implementation in qemu-storage-daemon so that it
5
Last use was removed in commit 8f2d75e81d5
10
doesn't call qmp_object_add(), but calls user_creatable_add_dict()
6
("hw: Drop superfluous special checks for orphaned -drive").
11
directly instead and pass it a new keyval boolean that decides which
12
visitor must be used.
13
7
14
Reported-by: Coiby Xu <coiby.xu@gmail.com>
8
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20211215121140.456939-4-eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
13
---
17
include/qom/object_interfaces.h | 6 +++++-
14
include/sysemu/blockdev.h | 1 -
18
qemu-storage-daemon.c | 4 +---
15
blockdev.c | 17 -----------------
19
qom/object_interfaces.c | 8 ++++++--
16
2 files changed, 18 deletions(-)
20
qom/qom-qmp-cmds.c | 2 +-
21
4 files changed, 13 insertions(+), 7 deletions(-)
22
17
23
diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h
18
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
24
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
25
--- a/include/qom/object_interfaces.h
20
--- a/include/sysemu/blockdev.h
26
+++ b/include/qom/object_interfaces.h
21
+++ b/include/sysemu/blockdev.h
27
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
22
@@ -XXX,XX +XXX,XX @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
28
/**
23
void drive_check_orphaned(void);
29
* user_creatable_add_dict:
24
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
30
* @qdict: the object definition
25
int drive_get_max_bus(BlockInterfaceType type);
31
+ * @keyval: if true, use a keyval visitor for processing @qdict (i.e.
26
-int drive_get_max_devs(BlockInterfaceType type);
32
+ * assume that all @qdict values are strings); otherwise, use
27
33
+ * the normal QObject visitor (i.e. assume all @qdict values
28
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
34
+ * have the QType expected by the QOM object type)
29
const char *optstr);
35
* @errp: if an error occurs, a pointer to an area to store the error
30
diff --git a/blockdev.c b/blockdev.c
36
*
37
* Create an instance of the user creatable object that is defined by
38
@@ -XXX,XX +XXX,XX @@ Object *user_creatable_add_type(const char *type, const char *id,
39
* ID from the key 'id'. The remaining entries in @qdict are used to
40
* initialize the object properties.
41
*/
42
-void user_creatable_add_dict(QDict *qdict, Error **errp);
43
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp);
44
45
/**
46
* user_creatable_add_opts:
47
diff --git a/qemu-storage-daemon.c b/qemu-storage-daemon.c
48
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-storage-daemon.c
32
--- a/blockdev.c
50
+++ b/qemu-storage-daemon.c
33
+++ b/blockdev.c
51
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
34
@@ -XXX,XX +XXX,XX @@ void blockdev_auto_del(BlockBackend *blk)
52
QemuOpts *opts;
35
}
53
const char *type;
54
QDict *args;
55
- QObject *ret_data = NULL;
56
57
/* FIXME The keyval parser rejects 'help' arguments, so we must
58
* unconditionall try QemuOpts first. */
59
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[])
60
qemu_opts_del(opts);
61
62
args = keyval_parse(optarg, "qom-type", &error_fatal);
63
- qmp_object_add(args, &ret_data, &error_fatal);
64
+ user_creatable_add_dict(args, true, &error_fatal);
65
qobject_unref(args);
66
- qobject_unref(ret_data);
67
break;
68
}
69
default:
70
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/qom/object_interfaces.c
73
+++ b/qom/object_interfaces.c
74
@@ -XXX,XX +XXX,XX @@ out:
75
return obj;
76
}
36
}
77
37
78
-void user_creatable_add_dict(QDict *qdict, Error **errp)
38
-/**
79
+void user_creatable_add_dict(QDict *qdict, bool keyval, Error **errp)
39
- * Returns the current mapping of how many units per bus
40
- * a particular interface can support.
41
- *
42
- * A positive integer indicates n units per bus.
43
- * 0 implies the mapping has not been established.
44
- * -1 indicates an invalid BlockInterfaceType was given.
45
- */
46
-int drive_get_max_devs(BlockInterfaceType type)
47
-{
48
- if (type >= IF_IDE && type < IF_COUNT) {
49
- return if_max_devs[type];
50
- }
51
-
52
- return -1;
53
-}
54
-
55
static int drive_index_to_bus_id(BlockInterfaceType type, int index)
80
{
56
{
81
Visitor *v;
57
int max_devs = if_max_devs[type];
82
Object *obj;
83
@@ -XXX,XX +XXX,XX @@ void user_creatable_add_dict(QDict *qdict, Error **errp)
84
}
85
qdict_del(qdict, "id");
86
87
- v = qobject_input_visitor_new(QOBJECT(qdict));
88
+ if (keyval) {
89
+ v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
90
+ } else {
91
+ v = qobject_input_visitor_new(QOBJECT(qdict));
92
+ }
93
obj = user_creatable_add_type(type, id, qdict, v, errp);
94
visit_free(v);
95
object_unref(obj);
96
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/qom/qom-qmp-cmds.c
99
+++ b/qom/qom-qmp-cmds.c
100
@@ -XXX,XX +XXX,XX @@ void qmp_object_add(QDict *qdict, QObject **ret_data, Error **errp)
101
qobject_unref(pdict);
102
}
103
104
- user_creatable_add_dict(qdict, errp);
105
+ user_creatable_add_dict(qdict, false, errp);
106
}
107
108
void qmp_object_del(const char *id, Error **errp)
109
--
58
--
110
2.25.3
59
2.31.1
111
60
112
61
diff view generated by jsdifflib
1
The raw format driver can simply forward the flag and let its bs->file
1
From: Daniel P. Berrangé <berrange@redhat.com>
2
child take care of actually providing the zeros.
3
2
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
The -device JSON syntax impl leaks a reference on the created
5
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
DeviceState instance. As a result when you hot-unplug the
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
device, the device_finalize method won't be called and thus
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
it will fail to emit the required DEVICE_DELETED event.
8
Message-Id: <20200424125448.63318-6-kwolf@redhat.com>
7
8
A 'json-cli' feature was previously added against the
9
'device_add' QMP command QAPI schema to indicated to mgmt
10
apps that -device supported JSON syntax. Given the hotplug
11
bug that feature flag is not usable for its purpose, so
12
we add a new 'json-cli-hotplug' feature to indicate the
13
-device supports JSON without breaking hotplug.
14
15
Fixes: 5dacda5167560b3af8eadbce5814f60ba44b467e
16
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/802
17
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
18
Message-Id: <20220105123847.4047954-2-berrange@redhat.com>
19
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
20
Tested-by: Ján Tomko <jtomko@redhat.com>
21
Reviewed-by: Thomas Huth <thuth@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
23
---
11
block/raw-format.c | 4 +++-
24
qapi/qdev.json | 5 ++++-
12
1 file changed, 3 insertions(+), 1 deletion(-)
25
softmmu/vl.c | 4 +++-
26
tests/qtest/device-plug-test.c | 19 +++++++++++++++++++
27
3 files changed, 26 insertions(+), 2 deletions(-)
13
28
14
diff --git a/block/raw-format.c b/block/raw-format.c
29
diff --git a/qapi/qdev.json b/qapi/qdev.json
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/block/raw-format.c
31
--- a/qapi/qdev.json
17
+++ b/block/raw-format.c
32
+++ b/qapi/qdev.json
18
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
33
@@ -XXX,XX +XXX,XX @@
19
34
# @json-cli: If present, the "-device" command line option supports JSON
20
s->size = offset;
35
# syntax with a structure identical to the arguments of this
21
offset += s->offset;
36
# command.
22
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
37
+# @json-cli-hotplug: If present, the "-device" command line option supports JSON
23
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
38
+# syntax without the reference counting leak that broke
39
+# hot-unplug
40
#
41
# Notes:
42
#
43
@@ -XXX,XX +XXX,XX @@
44
{ 'command': 'device_add',
45
'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
46
'gen': false, # so we can get the additional arguments
47
- 'features': ['json-cli'] }
48
+ 'features': ['json-cli', 'json-cli-hotplug'] }
49
50
##
51
# @device_del:
52
diff --git a/softmmu/vl.c b/softmmu/vl.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/softmmu/vl.c
55
+++ b/softmmu/vl.c
56
@@ -XXX,XX +XXX,XX @@ static void qemu_create_cli_devices(void)
57
qemu_opts_foreach(qemu_find_opts("device"),
58
device_init_func, NULL, &error_fatal);
59
QTAILQ_FOREACH(opt, &device_opts, next) {
60
+ DeviceState *dev;
61
loc_push_restore(&opt->loc);
62
/*
63
* TODO Eventually we should call qmp_device_add() here to make sure it
64
@@ -XXX,XX +XXX,XX @@ static void qemu_create_cli_devices(void)
65
* from the start, so call qdev_device_add_from_qdict() directly for
66
* now.
67
*/
68
- qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
69
+ dev = qdev_device_add_from_qdict(opt->opts, true, &error_fatal);
70
+ object_unref(OBJECT(dev));
71
loc_pop(&opt->loc);
72
}
73
rom_reset_order_override();
74
diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/tests/qtest/device-plug-test.c
77
+++ b/tests/qtest/device-plug-test.c
78
@@ -XXX,XX +XXX,XX @@ static void test_pci_unplug_request(void)
79
qtest_quit(qtest);
24
}
80
}
25
81
26
static void raw_eject(BlockDriverState *bs, bool eject_flag)
82
+static void test_pci_unplug_json_request(void)
27
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
83
+{
28
bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
84
+ QTestState *qtest = qtest_initf(
29
((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) &
85
+ "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'");
30
bs->file->bs->supported_zero_flags);
86
+
31
+ bs->supported_truncate_flags = bs->file->bs->supported_truncate_flags &
87
+ /*
32
+ BDRV_REQ_ZERO_WRITE;
88
+ * Request device removal. As the guest is not running, the request won't
33
89
+ * be processed. However during system reset, the removal will be
34
if (bs->probed && !bdrv_is_read_only(bs)) {
90
+ * handled, removing the device.
35
bdrv_refresh_filename(bs->file->bs);
91
+ */
92
+ device_del(qtest, "dev0");
93
+ system_reset(qtest);
94
+ wait_device_deleted_event(qtest, "dev0");
95
+
96
+ qtest_quit(qtest);
97
+}
98
+
99
static void test_ccw_unplug(void)
100
{
101
QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0");
102
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
103
*/
104
qtest_add_func("/device-plug/pci-unplug-request",
105
test_pci_unplug_request);
106
+ qtest_add_func("/device-plug/pci-unplug-json-request",
107
+ test_pci_unplug_json_request);
108
109
if (!strcmp(arch, "s390x")) {
110
qtest_add_func("/device-plug/ccw-unplug",
36
--
111
--
37
2.25.3
112
2.31.1
38
113
39
114
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Reported-by: Eric Blake <eblake@redhat.com>
4
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-Id: <20220107105420.395011-2-f4bug@amsat.org>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
docs/tools/qemu-storage-daemon.rst | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst
12
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/tools/qemu-storage-daemon.rst
14
+++ b/docs/tools/qemu-storage-daemon.rst
15
@@ -XXX,XX +XXX,XX @@ Export raw image file ``disk.img`` over NBD UNIX domain socket ``nbd.sock``::
16
--nbd-server addr.type=unix,addr.path=nbd.sock \
17
--export type=nbd,id=export,node-name=disk,writable=on
18
19
-Export a qcow2 image file ``disk.qcow2`` as a vhosts-user-blk device over UNIX
20
+Export a qcow2 image file ``disk.qcow2`` as a vhost-user-blk device over UNIX
21
domain socket ``vhost-user-blk.sock``::
22
23
$ qemu-storage-daemon \
24
--
25
2.31.1
26
27
diff view generated by jsdifflib
1
The BDRV_REQ_ZERO_WRITE is currently implemented in a way that first the
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
image is possibly preallocated and then the zero flag is added to all
3
clusters. This means that a copy-on-write operation may be needed when
4
writing to these clusters, despite having used preallocation, negating
5
one of the major benefits of preallocation.
6
2
7
Instead, try to forward the BDRV_REQ_ZERO_WRITE to the protocol driver,
3
Add missing vhost-user-blk help:
8
and if the protocol driver can ensure that the new area reads as zeros,
9
we can skip setting the zero flag in the qcow2 layer.
10
4
11
Unfortunately, the same approach doesn't work for metadata
5
$ qemu-storage-daemon -h
12
preallocation, so we'll still set the zero flag there.
6
...
7
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,
8
addr.type=unix,addr.path=<socket-path>[,writable=on|off]
9
[,logical-block-size=<block-size>][,num-queues=<num-queues>]
10
export the specified block node as a
11
vhosts-user-blk device over UNIX domain socket
12
--export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,
13
fd,addr.str=<fd>[,writable=on|off]
14
[,logical-block-size=<block-size>][,num-queues=<num-queues>]
15
export the specified block node as a
16
vhosts-user-blk device over file descriptor
17
...
13
18
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Fixes: 90fc91d50b7 ("convert vhost-user-blk server to block export API")
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Reported-by: Qing Wang <qinwang@redhat.com>
16
Message-Id: <20200424142701.67053-1-kwolf@redhat.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
22
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
23
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Message-Id: <20220107105420.395011-3-f4bug@amsat.org>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
26
---
20
block/qcow2.c | 22 +++++++++++++++++++---
27
storage-daemon/qemu-storage-daemon.c | 13 +++++++++++++
21
tests/qemu-iotests/274.out | 4 ++--
28
1 file changed, 13 insertions(+)
22
2 files changed, 21 insertions(+), 5 deletions(-)
23
29
24
diff --git a/block/qcow2.c b/block/qcow2.c
30
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
25
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.c
32
--- a/storage-daemon/qemu-storage-daemon.c
27
+++ b/block/qcow2.c
33
+++ b/storage-daemon/qemu-storage-daemon.c
28
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
34
@@ -XXX,XX +XXX,XX @@ static void help(void)
29
/* Allocate the data area */
35
" export the specified block node over FUSE\n"
30
new_file_size = allocation_start +
36
"\n"
31
nb_new_data_clusters * s->cluster_size;
37
#endif /* CONFIG_FUSE */
32
- /* Image file grows, so @exact does not matter */
38
+#ifdef CONFIG_VHOST_USER_BLK_SERVER
33
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
39
+" --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
34
- errp);
40
+" addr.type=unix,addr.path=<socket-path>[,writable=on|off]\n"
35
+ /*
41
+" [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
36
+ * Image file grows, so @exact does not matter.
42
+" export the specified block node as a\n"
37
+ *
43
+" vhost-user-blk device over UNIX domain socket\n"
38
+ * If we need to zero out the new area, try first whether the protocol
44
+" --export [type=]vhost-user-blk,id=<id>,node-name=<node-name>,\n"
39
+ * driver can already take care of this.
45
+" fd,addr.str=<fd>[,writable=on|off]\n"
40
+ */
46
+" [,logical-block-size=<block-size>][,num-queues=<num-queues>]\n"
41
+ if (flags & BDRV_REQ_ZERO_WRITE) {
47
+" export the specified block node as a\n"
42
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc,
48
+" vhost-user-blk device over file descriptor\n"
43
+ BDRV_REQ_ZERO_WRITE, NULL);
49
+"\n"
44
+ if (ret >= 0) {
50
+#endif /* CONFIG_VHOST_USER_BLK_SERVER */
45
+ flags &= ~BDRV_REQ_ZERO_WRITE;
51
" --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n"
46
+ }
52
" configure a QMP monitor\n"
47
+ } else {
53
"\n"
48
+ ret = -1;
49
+ }
50
+ if (ret < 0) {
51
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
52
+ errp);
53
+ }
54
if (ret < 0) {
55
error_prepend(errp, "Failed to resize underlying file: ");
56
qcow2_free_clusters(bs, allocation_start,
57
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tests/qemu-iotests/274.out
60
+++ b/tests/qemu-iotests/274.out
61
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
62
10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
63
64
[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
65
-{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
66
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
67
68
=== preallocation=full ===
69
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
70
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
71
4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
72
73
[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
74
-{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
75
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
76
77
=== preallocation=off ===
78
Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
79
--
54
--
80
2.25.3
55
2.31.1
81
56
82
57
diff view generated by jsdifflib
1
We want to keep TEST_IMG for the full path of the main test image, but
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
2
filter_testfiles() must be called for other test images before replacing
3
other things like the image format because the test directory path could
4
contain the format as a substring.
5
2
6
Insert a filter_testfiles() call between both.
3
When building QEMU with --disable-vhost-user and using introspection,
4
query-qmp-schema lists vhost-user-blk even though it's not actually
5
available:
7
6
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
{ "execute": "query-qmp-schema" }
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
{
10
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
9
"return": [
11
Message-Id: <20200424125448.63318-9-kwolf@redhat.com>
10
...
11
{
12
"name": "312",
13
"members": [
14
{
15
"name": "nbd"
16
},
17
{
18
"name": "vhost-user-blk"
19
}
20
],
21
"meta-type": "enum",
22
"values": [
23
"nbd",
24
"vhost-user-blk"
25
]
26
},
27
28
Restrict vhost-user-blk in BlockExportType when
29
CONFIG_VHOST_USER_BLK_SERVER is disabled, so it
30
doesn't end listed by query-qmp-schema.
31
32
Fixes: 90fc91d50b7 ("convert vhost-user-blk server to block export API")
33
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
34
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
35
Message-Id: <20220107105420.395011-4-f4bug@amsat.org>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
36
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
37
---
14
tests/qemu-iotests/iotests.py | 5 +++--
38
qapi/block-export.json | 6 ++++--
15
1 file changed, 3 insertions(+), 2 deletions(-)
39
1 file changed, 4 insertions(+), 2 deletions(-)
16
40
17
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
41
diff --git a/qapi/block-export.json b/qapi/block-export.json
18
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/iotests.py
43
--- a/qapi/block-export.json
20
+++ b/tests/qemu-iotests/iotests.py
44
+++ b/qapi/block-export.json
21
@@ -XXX,XX +XXX,XX @@ def filter_img_info(output, filename):
45
@@ -XXX,XX +XXX,XX @@
22
for line in output.split('\n'):
46
# Since: 4.2
23
if 'disk size' in line or 'actual-size' in line:
47
##
24
continue
48
{ 'enum': 'BlockExportType',
25
- line = line.replace(filename, 'TEST_IMG') \
49
- 'data': [ 'nbd', 'vhost-user-blk',
26
- .replace(imgfmt, 'IMGFMT')
50
+ 'data': [ 'nbd',
27
+ line = line.replace(filename, 'TEST_IMG')
51
+ { 'name': 'vhost-user-blk', 'if': 'CONFIG_VHOST_USER_BLK_SERVER' },
28
+ line = filter_testfiles(line)
52
{ 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] }
29
+ line = line.replace(imgfmt, 'IMGFMT')
53
30
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
54
##
31
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
55
@@ -XXX,XX +XXX,XX @@
32
line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
56
'discriminator': 'type',
57
'data': {
58
'nbd': 'BlockExportOptionsNbd',
59
- 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk',
60
+ 'vhost-user-blk': { 'type': 'BlockExportOptionsVhostUserBlk',
61
+ 'if': 'CONFIG_VHOST_USER_BLK_SERVER' },
62
'fuse': { 'type': 'BlockExportOptionsFuse',
63
'if': 'CONFIG_FUSE' }
64
} }
33
--
65
--
34
2.25.3
66
2.31.1
35
67
36
68
diff view generated by jsdifflib
1
Now that block drivers can support flags for .bdrv_co_truncate, expose
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
the parameter in the node level interfaces bdrv_co_truncate() and
3
bdrv_truncate().
4
2
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
3
The BlockBackend root child can change when aio_poll() is invoked. This
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
happens when a temporary filter node is removed upon blockjob
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
completion, for example.
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
6
9
Message-Id: <20200424125448.63318-3-kwolf@redhat.com>
7
Functions in block/block-backend.c must be aware of this when using a
8
blk_bs() pointer across aio_poll() because the BlockDriverState refcnt
9
may reach 0, resulting in a stale pointer.
10
11
One example is scsi_device_purge_requests(), which calls blk_drain() to
12
wait for in-flight requests to cancel. If the backup blockjob is active,
13
then the BlockBackend root child is a temporary filter BDS owned by the
14
blockjob. The blockjob can complete during bdrv_drained_begin() and the
15
last reference to the BDS is released when the temporary filter node is
16
removed. This results in a use-after-free when blk_drain() calls
17
bdrv_drained_end(bs) on the dangling pointer.
18
19
Explicitly hold a reference to bs across block APIs that invoke
20
aio_poll().
21
22
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2021778
23
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178
24
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
25
Message-Id: <20220111153613.25453-2-stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
27
---
12
include/block/block.h | 5 +++--
28
block/block-backend.c | 19 +++++++++++++++++--
13
block/block-backend.c | 2 +-
29
1 file changed, 17 insertions(+), 2 deletions(-)
14
block/crypto.c | 2 +-
15
block/io.c | 12 +++++++-----
16
block/parallels.c | 6 +++---
17
block/qcow.c | 4 ++--
18
block/qcow2-refcount.c | 2 +-
19
block/qcow2.c | 15 +++++++++------
20
block/raw-format.c | 2 +-
21
block/vhdx-log.c | 2 +-
22
block/vhdx.c | 2 +-
23
block/vmdk.c | 2 +-
24
tests/test-block-iothread.c | 6 +++---
25
13 files changed, 34 insertions(+), 28 deletions(-)
26
30
27
diff --git a/include/block/block.h b/include/block/block.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/block/block.h
30
+++ b/include/block/block.h
31
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
32
void bdrv_refresh_filename(BlockDriverState *bs);
33
34
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
35
- PreallocMode prealloc, Error **errp);
36
+ PreallocMode prealloc, BdrvRequestFlags flags,
37
+ Error **errp);
38
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
39
- PreallocMode prealloc, Error **errp);
40
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
41
42
int64_t bdrv_nb_sectors(BlockDriverState *bs);
43
int64_t bdrv_getlength(BlockDriverState *bs);
44
diff --git a/block/block-backend.c b/block/block-backend.c
31
diff --git a/block/block-backend.c b/block/block-backend.c
45
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
46
--- a/block/block-backend.c
33
--- a/block/block-backend.c
47
+++ b/block/block-backend.c
34
+++ b/block/block-backend.c
48
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
35
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
49
return -ENOMEDIUM;
36
void blk_remove_bs(BlockBackend *blk)
37
{
38
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
39
- BlockDriverState *bs;
40
BdrvChild *root;
41
42
notifier_list_notify(&blk->remove_bs_notifiers, blk);
43
if (tgm->throttle_state) {
44
- bs = blk_bs(blk);
45
+ BlockDriverState *bs = blk_bs(blk);
46
+
47
+ /*
48
+ * Take a ref in case blk_bs() changes across bdrv_drained_begin(), for
49
+ * example, if a temporary filter node is removed by a blockjob.
50
+ */
51
+ bdrv_ref(bs);
52
bdrv_drained_begin(bs);
53
throttle_group_detach_aio_context(tgm);
54
throttle_group_attach_aio_context(tgm, qemu_get_aio_context());
55
bdrv_drained_end(bs);
56
+ bdrv_unref(bs);
50
}
57
}
51
58
52
- return bdrv_truncate(blk->root, offset, exact, prealloc, errp);
59
blk_update_root_state(blk);
53
+ return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
60
@@ -XXX,XX +XXX,XX @@ void blk_drain(BlockBackend *blk)
61
BlockDriverState *bs = blk_bs(blk);
62
63
if (bs) {
64
+ bdrv_ref(bs);
65
bdrv_drained_begin(bs);
66
}
67
68
@@ -XXX,XX +XXX,XX @@ void blk_drain(BlockBackend *blk)
69
70
if (bs) {
71
bdrv_drained_end(bs);
72
+ bdrv_unref(bs);
73
}
54
}
74
}
55
75
56
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
76
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
57
diff --git a/block/crypto.c b/block/crypto.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block/crypto.c
60
+++ b/block/crypto.c
61
@@ -XXX,XX +XXX,XX @@ block_crypto_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
62
63
offset += payload_offset;
64
65
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
66
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
67
}
68
69
static void block_crypto_close(BlockDriverState *bs)
70
diff --git a/block/io.c b/block/io.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/io.c
73
+++ b/block/io.c
74
@@ -XXX,XX +XXX,XX @@ static void bdrv_parent_cb_resize(BlockDriverState *bs)
75
* 'offset' bytes in length.
76
*/
77
int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
78
- PreallocMode prealloc, Error **errp)
79
+ PreallocMode prealloc, BdrvRequestFlags flags,
80
+ Error **errp)
81
{
82
BlockDriverState *bs = child->bs;
83
BlockDriver *drv = bs->drv;
84
BdrvTrackedRequest req;
85
- BdrvRequestFlags flags = 0;
86
int64_t old_size, new_bytes;
87
int ret;
77
int ret;
88
78
89
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
79
if (bs) {
90
}
80
+ bdrv_ref(bs);
91
ret = drv->bdrv_co_truncate(bs, offset, exact, prealloc, flags, errp);
81
+
92
} else if (bs->file && drv->is_filter) {
82
if (update_root_node) {
93
- ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
83
ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
94
+ ret = bdrv_co_truncate(bs->file, offset, exact, prealloc, flags, errp);
84
errp);
95
} else {
96
error_setg(errp, "Image format driver does not support resize");
97
ret = -ENOTSUP;
98
@@ -XXX,XX +XXX,XX @@ typedef struct TruncateCo {
99
int64_t offset;
100
bool exact;
101
PreallocMode prealloc;
102
+ BdrvRequestFlags flags;
103
Error **errp;
104
int ret;
105
} TruncateCo;
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_truncate_co_entry(void *opaque)
107
{
108
TruncateCo *tco = opaque;
109
tco->ret = bdrv_co_truncate(tco->child, tco->offset, tco->exact,
110
- tco->prealloc, tco->errp);
111
+ tco->prealloc, tco->flags, tco->errp);
112
aio_wait_kick();
113
}
114
115
int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
116
- PreallocMode prealloc, Error **errp)
117
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
118
{
119
Coroutine *co;
120
TruncateCo tco = {
121
@@ -XXX,XX +XXX,XX @@ int bdrv_truncate(BdrvChild *child, int64_t offset, bool exact,
122
.offset = offset,
123
.exact = exact,
124
.prealloc = prealloc,
125
+ .flags = flags,
126
.errp = errp,
127
.ret = NOT_DONE,
128
};
129
diff --git a/block/parallels.c b/block/parallels.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/parallels.c
132
+++ b/block/parallels.c
133
@@ -XXX,XX +XXX,XX @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
134
} else {
135
ret = bdrv_truncate(bs->file,
136
(s->data_end + space) << BDRV_SECTOR_BITS,
137
- false, PREALLOC_MODE_OFF, NULL);
138
+ false, PREALLOC_MODE_OFF, 0, NULL);
139
}
140
if (ret < 0) {
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
143
* That means we have to pass exact=true.
144
*/
145
ret = bdrv_truncate(bs->file, res->image_end_offset, true,
146
- PREALLOC_MODE_OFF, &local_err);
147
+ PREALLOC_MODE_OFF, 0, &local_err);
148
if (ret < 0) {
85
if (ret < 0) {
149
error_report_err(local_err);
86
+ bdrv_unref(bs);
150
res->check_errors++;
151
@@ -XXX,XX +XXX,XX @@ static void parallels_close(BlockDriverState *bs)
152
153
/* errors are ignored, so we might as well pass exact=true */
154
bdrv_truncate(bs->file, s->data_end << BDRV_SECTOR_BITS, true,
155
- PREALLOC_MODE_OFF, NULL);
156
+ PREALLOC_MODE_OFF, 0, NULL);
157
}
158
159
g_free(s->bat_dirty_bmap);
160
diff --git a/block/qcow.c b/block/qcow.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/block/qcow.c
163
+++ b/block/qcow.c
164
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
165
return -E2BIG;
166
}
167
ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
168
- false, PREALLOC_MODE_OFF, NULL);
169
+ false, PREALLOC_MODE_OFF, 0, NULL);
170
if (ret < 0) {
171
return ret;
172
}
173
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
174
l1_length) < 0)
175
return -1;
176
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
177
- PREALLOC_MODE_OFF, NULL);
178
+ PREALLOC_MODE_OFF, 0, NULL);
179
if (ret < 0)
180
return ret;
181
182
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/block/qcow2-refcount.c
185
+++ b/block/qcow2-refcount.c
186
@@ -XXX,XX +XXX,XX @@ static int check_refblocks(BlockDriverState *bs, BdrvCheckResult *res,
187
}
188
189
ret = bdrv_truncate(bs->file, offset + s->cluster_size, false,
190
- PREALLOC_MODE_OFF, &local_err);
191
+ PREALLOC_MODE_OFF, 0, &local_err);
192
if (ret < 0) {
193
error_report_err(local_err);
194
goto resize_fail;
195
diff --git a/block/qcow2.c b/block/qcow2.c
196
index XXXXXXX..XXXXXXX 100644
197
--- a/block/qcow2.c
198
+++ b/block/qcow2.c
199
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
200
mode = PREALLOC_MODE_OFF;
201
}
202
ret = bdrv_co_truncate(s->data_file, host_offset + cur_bytes, false,
203
- mode, errp);
204
+ mode, 0, errp);
205
if (ret < 0) {
206
return ret;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
209
* always fulfilled, so there is no need to pass it on.)
210
*/
211
bdrv_co_truncate(bs->file, (last_cluster + 1) * s->cluster_size,
212
- false, PREALLOC_MODE_OFF, &local_err);
213
+ false, PREALLOC_MODE_OFF, 0, &local_err);
214
if (local_err) {
215
warn_reportf_err(local_err,
216
"Failed to truncate the tail of the image: ");
217
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
218
* file should be resized to the exact target size, too,
219
* so we pass @exact here.
220
*/
221
- ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, errp);
222
+ ret = bdrv_co_truncate(s->data_file, offset, exact, prealloc, 0,
223
+ errp);
224
if (ret < 0) {
225
goto fail;
226
}
227
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
228
new_file_size = allocation_start +
229
nb_new_data_clusters * s->cluster_size;
230
/* Image file grows, so @exact does not matter */
231
- ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, errp);
232
+ ret = bdrv_co_truncate(bs->file, new_file_size, false, prealloc, 0,
233
+ errp);
234
if (ret < 0) {
235
error_prepend(errp, "Failed to resize underlying file: ");
236
qcow2_free_clusters(bs, allocation_start,
237
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
238
if (len < 0) {
239
return len;
240
}
241
- return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, NULL);
242
+ return bdrv_co_truncate(bs->file, len, false, PREALLOC_MODE_OFF, 0,
243
+ NULL);
244
}
245
246
if (offset_into_cluster(s, offset)) {
247
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
248
}
249
250
ret = bdrv_truncate(bs->file, (3 + l1_clusters) * s->cluster_size, false,
251
- PREALLOC_MODE_OFF, &local_err);
252
+ PREALLOC_MODE_OFF, 0, &local_err);
253
if (ret < 0) {
254
error_report_err(local_err);
255
goto fail;
256
diff --git a/block/raw-format.c b/block/raw-format.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/raw-format.c
259
+++ b/block/raw-format.c
260
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
261
262
s->size = offset;
263
offset += s->offset;
264
- return bdrv_co_truncate(bs->file, offset, exact, prealloc, errp);
265
+ return bdrv_co_truncate(bs->file, offset, exact, prealloc, 0, errp);
266
}
267
268
static void raw_eject(BlockDriverState *bs, bool eject_flag)
269
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/block/vhdx-log.c
272
+++ b/block/vhdx-log.c
273
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
274
goto exit;
275
}
276
ret = bdrv_truncate(bs->file, new_file_size, false,
277
- PREALLOC_MODE_OFF, NULL);
278
+ PREALLOC_MODE_OFF, 0, NULL);
279
if (ret < 0) {
280
goto exit;
281
}
282
diff --git a/block/vhdx.c b/block/vhdx.c
283
index XXXXXXX..XXXXXXX 100644
284
--- a/block/vhdx.c
285
+++ b/block/vhdx.c
286
@@ -XXX,XX +XXX,XX @@ static int vhdx_allocate_block(BlockDriverState *bs, BDRVVHDXState *s,
287
}
288
289
return bdrv_truncate(bs->file, *new_offset + s->block_size, false,
290
- PREALLOC_MODE_OFF, NULL);
291
+ PREALLOC_MODE_OFF, 0, NULL);
292
}
293
294
/*
295
diff --git a/block/vmdk.c b/block/vmdk.c
296
index XXXXXXX..XXXXXXX 100644
297
--- a/block/vmdk.c
298
+++ b/block/vmdk.c
299
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
300
}
301
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
302
ret = bdrv_truncate(s->extents[i].file, length, false,
303
- PREALLOC_MODE_OFF, NULL);
304
+ PREALLOC_MODE_OFF, 0, NULL);
305
if (ret < 0) {
306
return ret;
87
return ret;
307
}
88
}
308
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
89
}
309
index XXXXXXX..XXXXXXX 100644
90
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
310
--- a/tests/test-block-iothread.c
91
throttle_group_attach_aio_context(tgm, new_context);
311
+++ b/tests/test-block-iothread.c
92
bdrv_drained_end(bs);
312
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
93
}
313
int ret;
94
+
314
95
+ bdrv_unref(bs);
315
/* Normal success path */
96
}
316
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
97
317
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
98
blk->ctx = new_context;
318
g_assert_cmpint(ret, ==, 0);
99
@@ -XXX,XX +XXX,XX @@ void blk_io_limits_disable(BlockBackend *blk)
319
100
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
320
/* Early error: Negative offset */
101
assert(tgm->throttle_state);
321
- ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, NULL);
102
if (bs) {
322
+ ret = bdrv_truncate(c, -2, false, PREALLOC_MODE_OFF, 0, NULL);
103
+ bdrv_ref(bs);
323
g_assert_cmpint(ret, ==, -EINVAL);
104
bdrv_drained_begin(bs);
324
105
}
325
/* Error: Read-only image */
106
throttle_group_unregister_tgm(tgm);
326
c->bs->read_only = true;
107
if (bs) {
327
c->bs->open_flags &= ~BDRV_O_RDWR;
108
bdrv_drained_end(bs);
328
109
+ bdrv_unref(bs);
329
- ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, NULL);
110
}
330
+ ret = bdrv_truncate(c, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
111
}
331
g_assert_cmpint(ret, ==, -EACCES);
112
332
333
c->bs->read_only = false;
334
--
113
--
335
2.25.3
114
2.31.1
336
115
337
116
diff view generated by jsdifflib
1
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
Message-Id: <20200424125448.63318-10-kwolf@redhat.com>
2
3
Reviewed-by: Max Reitz <mreitz@redhat.com>
3
Test the following scenario:
4
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
- Simple stream block in two-layer backing chain (base and top)
5
- The job is drained via blk_drain(), then an error occurs while the job
6
settles the ongoing request
7
- And so the job completes while in blk_drain()
8
9
This was reported as a segfault, but is fixed by "block-backend: prevent
10
dangling BDS pointers across aio_poll()".
11
12
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-Id: <20220111153613.25453-3-stefanha@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
17
---
7
tests/qemu-iotests/274 | 155 +++++++++++++++++++++
18
.../qemu-iotests/tests/stream-error-on-reset | 140 ++++++++++++++++++
8
tests/qemu-iotests/274.out | 268 +++++++++++++++++++++++++++++++++++++
19
.../tests/stream-error-on-reset.out | 5 +
9
tests/qemu-iotests/group | 1 +
20
2 files changed, 145 insertions(+)
10
3 files changed, 424 insertions(+)
21
create mode 100755 tests/qemu-iotests/tests/stream-error-on-reset
11
create mode 100755 tests/qemu-iotests/274
22
create mode 100644 tests/qemu-iotests/tests/stream-error-on-reset.out
12
create mode 100644 tests/qemu-iotests/274.out
13
23
14
diff --git a/tests/qemu-iotests/274 b/tests/qemu-iotests/274
24
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset
15
new file mode 100755
25
new file mode 100755
16
index XXXXXXX..XXXXXXX
26
index XXXXXXX..XXXXXXX
17
--- /dev/null
27
--- /dev/null
18
+++ b/tests/qemu-iotests/274
28
+++ b/tests/qemu-iotests/tests/stream-error-on-reset
19
@@ -XXX,XX +XXX,XX @@
29
@@ -XXX,XX +XXX,XX @@
20
+#!/usr/bin/env python3
30
+#!/usr/bin/env python3
31
+# group: rw quick
21
+#
32
+#
22
+# Copyright (C) 2019 Red Hat, Inc.
33
+# Test what happens when a stream job completes in a blk_drain().
34
+#
35
+# Copyright (C) 2022 Red Hat, Inc.
23
+#
36
+#
24
+# This program is free software; you can redistribute it and/or modify
37
+# This program is free software; you can redistribute it and/or modify
25
+# it under the terms of the GNU General Public License as published by
38
+# it under the terms of the GNU General Public License as published by
26
+# the Free Software Foundation; either version 2 of the License, or
39
+# the Free Software Foundation; either version 2 of the License, or
27
+# (at your option) any later version.
40
+# (at your option) any later version.
...
...
32
+# GNU General Public License for more details.
45
+# GNU General Public License for more details.
33
+#
46
+#
34
+# You should have received a copy of the GNU General Public License
47
+# You should have received a copy of the GNU General Public License
35
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
48
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
36
+#
49
+#
37
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
38
+#
39
+# Some tests for short backing files and short overlays
40
+
50
+
51
+import os
41
+import iotests
52
+import iotests
42
+
53
+from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase
43
+iotests.verify_image_format(supported_fmts=['qcow2'])
44
+iotests.verify_platform(['linux'])
45
+
46
+size_short = 1 * 1024 * 1024
47
+size_long = 2 * 1024 * 1024
48
+size_diff = size_long - size_short
49
+
50
+def create_chain() -> None:
51
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base,
52
+ str(size_long))
53
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, mid,
54
+ str(size_short))
55
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', mid, top,
56
+ str(size_long))
57
+
58
+ iotests.qemu_io_log('-c', 'write -P 1 0 %d' % size_long, base)
59
+
60
+def create_vm() -> iotests.VM:
61
+ vm = iotests.VM()
62
+ vm.add_blockdev('file,filename=%s,node-name=base-file' % base)
63
+ vm.add_blockdev('%s,file=base-file,node-name=base' % iotests.imgfmt)
64
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % mid)
65
+ vm.add_blockdev('%s,file=mid-file,node-name=mid,backing=base'
66
+ % iotests.imgfmt)
67
+ vm.add_drive(top, 'backing=mid,node-name=top')
68
+ return vm
69
+
70
+with iotests.FilePath('base') as base, \
71
+ iotests.FilePath('mid') as mid, \
72
+ iotests.FilePath('top') as top:
73
+
74
+ iotests.log('== Commit tests ==')
75
+
76
+ create_chain()
77
+
78
+ iotests.log('=== Check visible data ===')
79
+
80
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, top)
81
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), top)
82
+
83
+ iotests.log('=== Checking allocation status ===')
84
+
85
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
86
+ '-c', 'alloc %d %d' % (size_short, size_diff),
87
+ base)
88
+
89
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
90
+ '-c', 'alloc %d %d' % (size_short, size_diff),
91
+ mid)
92
+
93
+ iotests.qemu_io_log('-c', 'alloc 0 %d' % size_short,
94
+ '-c', 'alloc %d %d' % (size_short, size_diff),
95
+ top)
96
+
97
+ iotests.log('=== Checking map ===')
98
+
99
+ iotests.qemu_img_log('map', '--output=json', base)
100
+ iotests.qemu_img_log('map', '--output=human', base)
101
+ iotests.qemu_img_log('map', '--output=json', mid)
102
+ iotests.qemu_img_log('map', '--output=human', mid)
103
+ iotests.qemu_img_log('map', '--output=json', top)
104
+ iotests.qemu_img_log('map', '--output=human', top)
105
+
106
+ iotests.log('=== Testing qemu-img commit (top -> mid) ===')
107
+
108
+ iotests.qemu_img_log('commit', top)
109
+ iotests.img_info_log(mid)
110
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
111
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
112
+
113
+ iotests.log('=== Testing HMP commit (top -> mid) ===')
114
+
115
+ create_chain()
116
+ with create_vm() as vm:
117
+ vm.launch()
118
+ vm.qmp_log('human-monitor-command', command_line='commit drive0')
119
+
120
+ iotests.img_info_log(mid)
121
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
122
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
123
+
124
+ iotests.log('=== Testing QMP active commit (top -> mid) ===')
125
+
126
+ create_chain()
127
+ with create_vm() as vm:
128
+ vm.launch()
129
+ vm.qmp_log('block-commit', device='top', base_node='mid',
130
+ job_id='job0', auto_dismiss=False)
131
+ vm.run_job('job0', wait=5)
132
+
133
+ iotests.img_info_log(mid)
134
+ iotests.qemu_io_log('-c', 'read -P 1 0 %d' % size_short, mid)
135
+ iotests.qemu_io_log('-c', 'read -P 0 %d %d' % (size_short, size_diff), mid)
136
+
54
+
137
+
55
+
138
+ iotests.log('== Resize tests ==')
56
+image_size = 1 * 1024 * 1024
57
+data_size = 64 * 1024
58
+base = os.path.join(iotests.test_dir, 'base.img')
59
+top = os.path.join(iotests.test_dir, 'top.img')
139
+
60
+
140
+ # Use different sizes for different allocation modes:
141
+ #
142
+ # We want to have at least one test where 32 bit truncation in the size of
143
+ # the overlapping area becomes visible. This is covered by the
144
+ # prealloc='off' case (1G to 6G is an overlap of 5G).
145
+ #
146
+ # However, we can only do this for modes that don't preallocate data
147
+ # because otherwise we might run out of space on the test host.
148
+ #
149
+ # We also want to test some unaligned combinations.
150
+ for (prealloc, base_size, top_size_old, top_size_new, off) in [
151
+ ('off', '6G', '1G', '8G', '5G'),
152
+ ('metadata', '32G', '30G', '33G', '31G'),
153
+ ('falloc', '10M', '5M', '15M', '9M'),
154
+ ('full', '16M', '8M', '12M', '11M'),
155
+ ('off', '384k', '253k', '512k', '253k'),
156
+ ('off', '400k', '256k', '512k', '336k'),
157
+ ('off', '512k', '256k', '500k', '436k')]:
158
+
61
+
159
+ iotests.log('=== preallocation=%s ===' % prealloc)
62
+# We want to test completing a stream job in a blk_drain().
160
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, base, base_size)
63
+#
161
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, '-b', base, top,
64
+# The blk_drain() we are going to use is a virtio-scsi device resetting,
162
+ top_size_old)
65
+# which we can trigger by resetting the system.
163
+ iotests.qemu_io_log('-c', 'write -P 1 %s 64k' % off, base)
66
+#
67
+# In order to have the block job complete on drain, we (1) throttle its
68
+# base image so we can start the drain after it has begun, but before it
69
+# completes, and (2) make it encounter an I/O error on the ensuing write.
70
+# (If it completes regularly, the completion happens after the drain for
71
+# some reason.)
164
+
72
+
165
+ # After this, top_size_old to base_size should be allocated/zeroed.
73
+class TestStreamErrorOnReset(QMPTestCase):
166
+ #
74
+ def setUp(self) -> None:
167
+ # In theory, leaving base_size to top_size_new unallocated would be
75
+ """
168
+ # correct, but in practice, if we zero out anything, we zero out
76
+ Create two images:
169
+ # everything up to top_size_new.
77
+ - base image {base} with {data_size} bytes allocated
170
+ iotests.qemu_img_log('resize', '-f', iotests.imgfmt,
78
+ - top image {top} without any data allocated
171
+ '--preallocation', prealloc, top, top_size_new)
79
+
172
+ iotests.qemu_io_log('-c', 'read -P 0 %s 64k' % off, top)
80
+ And the following VM configuration:
173
+ iotests.qemu_io_log('-c', 'map', top)
81
+ - base image throttled to {data_size}
174
+ iotests.qemu_img_log('map', '--output=json', top)
82
+ - top image with a blkdebug configuration so the first write access
175
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
83
+ to it will result in an error
84
+ - top image is attached to a virtio-scsi device
85
+ """
86
+ assert qemu_img_create('-f', imgfmt, base, str(image_size)) == 0
87
+ assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0
88
+ assert qemu_img_create('-f', imgfmt, top, str(image_size)) == 0
89
+
90
+ self.vm = iotests.VM()
91
+ self.vm.add_args('-accel', 'tcg') # Make throttling work properly
92
+ self.vm.add_object(self.vm.qmp_to_opts({
93
+ 'qom-type': 'throttle-group',
94
+ 'id': 'thrgr',
95
+ 'x-bps-total': str(data_size)
96
+ }))
97
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
98
+ 'driver': imgfmt,
99
+ 'node-name': 'base',
100
+ 'file': {
101
+ 'driver': 'throttle',
102
+ 'throttle-group': 'thrgr',
103
+ 'file': {
104
+ 'driver': 'file',
105
+ 'filename': base
106
+ }
107
+ }
108
+ }))
109
+ self.vm.add_blockdev(self.vm.qmp_to_opts({
110
+ 'driver': imgfmt,
111
+ 'node-name': 'top',
112
+ 'file': {
113
+ 'driver': 'blkdebug',
114
+ 'node-name': 'top-blkdebug',
115
+ 'inject-error': [{
116
+ 'event': 'pwritev',
117
+ 'immediately': 'true',
118
+ 'once': 'true'
119
+ }],
120
+ 'image': {
121
+ 'driver': 'file',
122
+ 'filename': top
123
+ }
124
+ },
125
+ 'backing': 'base'
126
+ }))
127
+ self.vm.add_device(self.vm.qmp_to_opts({
128
+ 'driver': 'virtio-scsi',
129
+ 'id': 'vscsi'
130
+ }))
131
+ self.vm.add_device(self.vm.qmp_to_opts({
132
+ 'driver': 'scsi-hd',
133
+ 'bus': 'vscsi.0',
134
+ 'drive': 'top'
135
+ }))
136
+ self.vm.launch()
137
+
138
+ def tearDown(self) -> None:
139
+ self.vm.shutdown()
140
+ os.remove(top)
141
+ os.remove(base)
142
+
143
+ def test_stream_error_on_reset(self) -> None:
144
+ # Launch a stream job, which will take at least a second to
145
+ # complete, because the base image is throttled (so we can
146
+ # get in between it having started and it having completed)
147
+ res = self.vm.qmp('block-stream', job_id='stream', device='top')
148
+ self.assert_qmp(res, 'return', {})
149
+
150
+ while True:
151
+ ev = self.vm.event_wait('JOB_STATUS_CHANGE')
152
+ if ev['data']['status'] == 'running':
153
+ # Once the stream job is running, reset the system, which
154
+ # forces the virtio-scsi device to be reset, thus draining
155
+ # the stream job, and making it complete. Completing
156
+ # inside of that drain should not result in a segfault.
157
+ res = self.vm.qmp('system_reset')
158
+ self.assert_qmp(res, 'return', {})
159
+ elif ev['data']['status'] == 'null':
160
+ # The test is done once the job is gone
161
+ break
162
+
163
+
164
+if __name__ == '__main__':
165
+ # Passes with any format with backing file support, but qed and
166
+ # qcow1 do not seem to exercise the used-to-be problematic code
167
+ # path, so there is no point in having them in this list
168
+ iotests.main(supported_fmts=['qcow2', 'vmdk'],
169
+ supported_protocols=['file'])
170
diff --git a/tests/qemu-iotests/tests/stream-error-on-reset.out b/tests/qemu-iotests/tests/stream-error-on-reset.out
176
new file mode 100644
171
new file mode 100644
177
index XXXXXXX..XXXXXXX
172
index XXXXXXX..XXXXXXX
178
--- /dev/null
173
--- /dev/null
179
+++ b/tests/qemu-iotests/274.out
174
+++ b/tests/qemu-iotests/tests/stream-error-on-reset.out
180
@@ -XXX,XX +XXX,XX @@
175
@@ -XXX,XX +XXX,XX @@
181
+== Commit tests ==
176
+.
182
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
177
+----------------------------------------------------------------------
178
+Ran 1 tests
183
+
179
+
184
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
180
+OK
185
+
186
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
187
+
188
+wrote 2097152/2097152 bytes at offset 0
189
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
190
+
191
+=== Check visible data ===
192
+read 1048576/1048576 bytes at offset 0
193
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
194
+
195
+read 1048576/1048576 bytes at offset 1048576
196
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
+
198
+=== Checking allocation status ===
199
+1048576/1048576 bytes allocated at offset 0 bytes
200
+1048576/1048576 bytes allocated at offset 1 MiB
201
+
202
+0/1048576 bytes allocated at offset 0 bytes
203
+0/0 bytes allocated at offset 1 MiB
204
+
205
+0/1048576 bytes allocated at offset 0 bytes
206
+0/1048576 bytes allocated at offset 1 MiB
207
+
208
+=== Checking map ===
209
+[{ "start": 0, "length": 2097152, "depth": 0, "zero": false, "data": true, "offset": 327680}]
210
+
211
+Offset Length Mapped to File
212
+0 0x200000 0x50000 TEST_DIR/PID-base
213
+
214
+[{ "start": 0, "length": 1048576, "depth": 1, "zero": false, "data": true, "offset": 327680}]
215
+
216
+Offset Length Mapped to File
217
+0 0x100000 0x50000 TEST_DIR/PID-base
218
+
219
+[{ "start": 0, "length": 1048576, "depth": 2, "zero": false, "data": true, "offset": 327680},
220
+{ "start": 1048576, "length": 1048576, "depth": 0, "zero": true, "data": false}]
221
+
222
+Offset Length Mapped to File
223
+0 0x100000 0x50000 TEST_DIR/PID-base
224
+
225
+=== Testing qemu-img commit (top -> mid) ===
226
+Image committed.
227
+
228
+image: TEST_IMG
229
+file format: IMGFMT
230
+virtual size: 2 MiB (2097152 bytes)
231
+cluster_size: 65536
232
+backing file: TEST_DIR/PID-base
233
+Format specific information:
234
+ compat: 1.1
235
+ lazy refcounts: false
236
+ refcount bits: 16
237
+ corrupt: false
238
+
239
+read 1048576/1048576 bytes at offset 0
240
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
241
+
242
+read 1048576/1048576 bytes at offset 1048576
243
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
244
+
245
+=== Testing HMP commit (top -> mid) ===
246
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
247
+
248
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
249
+
250
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
251
+
252
+wrote 2097152/2097152 bytes at offset 0
253
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+
255
+{"execute": "human-monitor-command", "arguments": {"command-line": "commit drive0"}}
256
+{"return": ""}
257
+image: TEST_IMG
258
+file format: IMGFMT
259
+virtual size: 2 MiB (2097152 bytes)
260
+cluster_size: 65536
261
+backing file: TEST_DIR/PID-base
262
+Format specific information:
263
+ compat: 1.1
264
+ lazy refcounts: false
265
+ refcount bits: 16
266
+ corrupt: false
267
+
268
+read 1048576/1048576 bytes at offset 0
269
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
270
+
271
+read 1048576/1048576 bytes at offset 1048576
272
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+
274
+=== Testing QMP active commit (top -> mid) ===
275
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=2097152 cluster_size=65536 lazy_refcounts=off refcount_bits=16
276
+
277
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 size=1048576 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
278
+
279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=2097152 backing_file=TEST_DIR/PID-mid cluster_size=65536 lazy_refcounts=off refcount_bits=16
280
+
281
+wrote 2097152/2097152 bytes at offset 0
282
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
283
+
284
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "base-node": "mid", "device": "top", "job-id": "job0"}}
285
+{"return": {}}
286
+{"execute": "job-complete", "arguments": {"id": "job0"}}
287
+{"return": {}}
288
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
289
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
290
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
291
+{"return": {}}
292
+image: TEST_IMG
293
+file format: IMGFMT
294
+virtual size: 2 MiB (2097152 bytes)
295
+cluster_size: 65536
296
+backing file: TEST_DIR/PID-base
297
+Format specific information:
298
+ compat: 1.1
299
+ lazy refcounts: false
300
+ refcount bits: 16
301
+ corrupt: false
302
+
303
+read 1048576/1048576 bytes at offset 0
304
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
305
+
306
+read 1048576/1048576 bytes at offset 1048576
307
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
308
+
309
+== Resize tests ==
310
+=== preallocation=off ===
311
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=6442450944 cluster_size=65536 lazy_refcounts=off refcount_bits=16
312
+
313
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=1073741824 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
314
+
315
+wrote 65536/65536 bytes at offset 5368709120
316
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
317
+
318
+Image resized.
319
+
320
+read 65536/65536 bytes at offset 5368709120
321
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
322
+
323
+1 GiB (0x40000000) bytes not allocated at offset 0 bytes (0x0)
324
+7 GiB (0x1c0000000) bytes allocated at offset 1 GiB (0x40000000)
325
+
326
+[{ "start": 0, "length": 1073741824, "depth": 1, "zero": true, "data": false},
327
+{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
328
+
329
+=== preallocation=metadata ===
330
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=34359738368 cluster_size=65536 lazy_refcounts=off refcount_bits=16
331
+
332
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=32212254720 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
333
+
334
+wrote 65536/65536 bytes at offset 33285996544
335
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
336
+
337
+Image resized.
338
+
339
+read 65536/65536 bytes at offset 33285996544
340
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
341
+
342
+30 GiB (0x780000000) bytes not allocated at offset 0 bytes (0x0)
343
+3 GiB (0xc0000000) bytes allocated at offset 30 GiB (0x780000000)
344
+
345
+[{ "start": 0, "length": 32212254720, "depth": 1, "zero": true, "data": false},
346
+{ "start": 32212254720, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 327680},
347
+{ "start": 32749125632, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 537264128},
348
+{ "start": 33285996544, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1074200576},
349
+{ "start": 33822867456, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 1611137024},
350
+{ "start": 34359738368, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2148139008},
351
+{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
352
+
353
+=== preallocation=falloc ===
354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=10485760 cluster_size=65536 lazy_refcounts=off refcount_bits=16
355
+
356
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=5242880 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
357
+
358
+wrote 65536/65536 bytes at offset 9437184
359
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
360
+
361
+Image resized.
362
+
363
+read 65536/65536 bytes at offset 9437184
364
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
365
+
366
+5 MiB (0x500000) bytes not allocated at offset 0 bytes (0x0)
367
+10 MiB (0xa00000) bytes allocated at offset 5 MiB (0x500000)
368
+
369
+[{ "start": 0, "length": 5242880, "depth": 1, "zero": true, "data": false},
370
+{ "start": 5242880, "length": 10485760, "depth": 0, "zero": true, "data": false, "offset": 327680}]
371
+
372
+=== preallocation=full ===
373
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=16777216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
374
+
375
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=8388608 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
376
+
377
+wrote 65536/65536 bytes at offset 11534336
378
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
379
+
380
+Image resized.
381
+
382
+read 65536/65536 bytes at offset 11534336
383
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
384
+
385
+8 MiB (0x800000) bytes not allocated at offset 0 bytes (0x0)
386
+4 MiB (0x400000) bytes allocated at offset 8 MiB (0x800000)
387
+
388
+[{ "start": 0, "length": 8388608, "depth": 1, "zero": true, "data": false},
389
+{ "start": 8388608, "length": 4194304, "depth": 0, "zero": true, "data": false, "offset": 327680}]
390
+
391
+=== preallocation=off ===
392
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=393216 cluster_size=65536 lazy_refcounts=off refcount_bits=16
393
+
394
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=259072 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
395
+
396
+wrote 65536/65536 bytes at offset 259072
397
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
398
+
399
+Image resized.
400
+
401
+read 65536/65536 bytes at offset 259072
402
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
403
+
404
+192 KiB (0x30000) bytes not allocated at offset 0 bytes (0x0)
405
+320 KiB (0x50000) bytes allocated at offset 192 KiB (0x30000)
406
+
407
+[{ "start": 0, "length": 196608, "depth": 1, "zero": true, "data": false},
408
+{ "start": 196608, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": 327680},
409
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
410
+
411
+=== preallocation=off ===
412
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=409600 cluster_size=65536 lazy_refcounts=off refcount_bits=16
413
+
414
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
415
+
416
+wrote 65536/65536 bytes at offset 344064
417
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
418
+
419
+Image resized.
420
+
421
+read 65536/65536 bytes at offset 344064
422
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
423
+
424
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
425
+256 KiB (0x40000) bytes allocated at offset 256 KiB (0x40000)
426
+
427
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
428
+{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
429
+
430
+=== preallocation=off ===
431
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=524288 cluster_size=65536 lazy_refcounts=off refcount_bits=16
432
+
433
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 size=262144 backing_file=TEST_DIR/PID-base cluster_size=65536 lazy_refcounts=off refcount_bits=16
434
+
435
+wrote 65536/65536 bytes at offset 446464
436
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
437
+
438
+Image resized.
439
+
440
+read 65536/65536 bytes at offset 446464
441
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
442
+
443
+256 KiB (0x40000) bytes not allocated at offset 0 bytes (0x0)
444
+244 KiB (0x3d000) bytes allocated at offset 256 KiB (0x40000)
445
+
446
+[{ "start": 0, "length": 262144, "depth": 1, "zero": true, "data": false},
447
+{ "start": 262144, "length": 249856, "depth": 0, "zero": true, "data": false}]
448
+
449
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
450
index XXXXXXX..XXXXXXX 100644
451
--- a/tests/qemu-iotests/group
452
+++ b/tests/qemu-iotests/group
453
@@ -XXX,XX +XXX,XX @@
454
270 rw backing quick
455
272 rw
456
273 backing quick
457
+274 rw backing
458
277 rw quick
459
279 rw backing quick
460
280 rw migration quick
461
--
181
--
462
2.25.3
182
2.31.1
463
183
464
184
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Hanna Reitz <hreitz@redhat.com>
2
2
3
Test 244 checks the expected behavior of qcow2 external data files
3
With CAP_DAC_OVERRIDE (which e.g. root generally has), permission checks
4
with respect to zero and discarded clusters. Filesystems however
4
will be bypassed when opening files.
5
are free to ignore discard requests, and this seems to be the
6
case for overlayfs. Relax the tests to skip checks on the
7
external data file for discarded areas, which implies not using
8
qemu-img compare in the data_file_raw=on case.
9
5
10
This fixes docker tests on RHEL8.
6
308 in one instance tries to open a read-only file (FUSE export) with
7
qemu-io as read/write, and expects this to fail. However, when running
8
it as root, opening will succeed (thanks to CAP_DAC_OVERRIDE) and only
9
the actual write operation will fail.
11
10
12
Cc: Kevin Wolf <kwolf@redhat.com>
11
Note this as "Case not run", but have the test pass in either case.
13
Cc: qemu-block@nongnu.org
12
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <20200409191006.24429-1-pbonzini@redhat.com>
14
Fixes: 2c7dd057aa7bd7a875e9b1a53975c220d6380bc4
15
("export/fuse: Pass default_permissions for mount")
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
Message-Id: <20220103120014.13061-1-hreitz@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
19
---
18
tests/qemu-iotests/244 | 10 ++++++++--
20
tests/qemu-iotests/308 | 25 +++++++++++++++++++++++--
19
tests/qemu-iotests/244.out | 9 ++++++---
21
tests/qemu-iotests/308.out | 2 +-
20
2 files changed, 14 insertions(+), 5 deletions(-)
22
2 files changed, 24 insertions(+), 3 deletions(-)
21
23
22
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
24
diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308
23
index XXXXXXX..XXXXXXX 100755
25
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/244
26
--- a/tests/qemu-iotests/308
25
+++ b/tests/qemu-iotests/244
27
+++ b/tests/qemu-iotests/308
26
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
28
@@ -XXX,XX +XXX,XX @@ echo '=== Writable export ==='
27
echo
29
fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true"
28
$QEMU_IO -c 'read -P 0 0 1M' \
30
29
-c 'read -P 0x11 1M 1M' \
31
# Check that writing to the read-only export fails
30
- -c 'read -P 0 2M 2M' \
32
-$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
31
-c 'read -P 0x11 4M 1M' \
33
- | _filter_qemu_io | _filter_testdir | _filter_imgfmt
32
-c 'read -P 0 5M 1M' \
34
+output=$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \
33
-f raw "$TEST_IMG.data" |
35
+ | _filter_qemu_io | _filter_testdir | _filter_imgfmt)
34
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'read -P 0 0 1M' \
36
+
35
-f $IMGFMT "$TEST_IMG" |
37
+# Expected reference output: Opening the file fails because it has no
36
_filter_qemu_io
38
+# write permission
37
39
+reference="Could not open 'TEST_DIR/t.IMGFMT': Permission denied"
38
+# Discarded clusters are only marked as such in the qcow2 metadata, but
40
+
39
+# they can contain stale data in the external data file. Instead, zero
41
+if echo "$output" | grep -q "$reference"; then
40
+# clusters must be zeroed in the external data file too.
42
+ echo "Writing to read-only export failed: OK"
41
echo
43
+elif echo "$output" | grep -q "write failed: Permission denied"; then
42
-$QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.data"
44
+ # With CAP_DAC_OVERRIDE (e.g. when running this test as root), the export
43
+$QEMU_IO -c 'read -P 0 0 1M' \
45
+ # can be opened regardless of its file permissions, but writing will then
44
+ -c 'read -P 0x11 1M 1M' \
46
+ # fail. This is not the result for which we want to test, so count this as
45
+ -c 'read -P 0 3M 3M' \
47
+ # a SKIP.
46
+ -f raw "$TEST_IMG".data |
48
+ _casenotrun "Opening RO export as R/W succeeded, perhaps because of" \
47
+ _filter_qemu_io
49
+ "CAP_DAC_OVERRIDE"
48
50
+
49
echo -n "qcow2 file size after I/O: "
51
+ # Still, write this to the reference output to make the test pass
50
du -b $TEST_IMG | cut -f1
52
+ echo "Writing to read-only export failed: OK"
51
diff --git a/tests/qemu-iotests/244.out b/tests/qemu-iotests/244.out
53
+else
54
+ echo "Writing to read-only export failed: ERROR"
55
+ echo "$output"
56
+fi
57
58
# But here it should work
59
$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io
60
diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out
52
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
53
--- a/tests/qemu-iotests/244.out
62
--- a/tests/qemu-iotests/308.out
54
+++ b/tests/qemu-iotests/244.out
63
+++ b/tests/qemu-iotests/308.out
55
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
64
@@ -XXX,XX +XXX,XX @@ virtual size: 0 B (0 bytes)
56
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
65
'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true
57
read 1048576/1048576 bytes at offset 1048576
66
} }
58
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
{"return": {}}
59
-read 2097152/2097152 bytes at offset 2097152
68
-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT': Permission denied
60
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
69
+Writing to read-only export failed: OK
61
read 1048576/1048576 bytes at offset 4194304
70
wrote 65536/65536 bytes at offset 1048576
62
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
63
read 1048576/1048576 bytes at offset 5242880
72
wrote 65536/65536 bytes at offset 1048576
64
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
65
read 4194304/4194304 bytes at offset 2097152
66
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
67
68
-Images are identical.
69
+read 1048576/1048576 bytes at offset 0
70
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
71
+read 1048576/1048576 bytes at offset 1048576
72
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
73
+read 3145728/3145728 bytes at offset 3145728
74
+3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
75
qcow2 file size after I/O: 327680
76
77
=== bdrv_co_block_status test for file and offset=0 ===
78
--
73
--
79
2.25.3
74
2.31.1
80
75
81
76
diff view generated by jsdifflib
1
If BDRV_REQ_ZERO_WRITE is set and we're extending the image, calling
1
The size of the qcow size was calculated so that only the FAT partition
2
qcow2_cluster_zeroize() with flags=0 does the right thing: It doesn't
2
would fit on it, but not the whole disk. However, offsets relative to
3
undo any previous preallocation, but just adds the zero flag to all
3
the whole disk are used to access it, so increase its size to be large
4
relevant L2 entries. If an external data file is in use, a write_zeroes
4
enough for that.
5
request to the data file is made instead.
6
5
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20200424125448.63318-5-kwolf@redhat.com>
7
Message-Id: <20211209151815.23495-1-kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
9
---
13
block/qcow2-cluster.c | 2 +-
10
block/vvfat.c | 7 +++----
14
block/qcow2.c | 34 ++++++++++++++++++++++++++++++++++
11
1 file changed, 3 insertions(+), 4 deletions(-)
15
2 files changed, 35 insertions(+), 1 deletion(-)
16
12
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
13
diff --git a/block/vvfat.c b/block/vvfat.c
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
15
--- a/block/vvfat.c
20
+++ b/block/qcow2-cluster.c
16
+++ b/block/vvfat.c
21
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
17
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
22
/* Caller must pass aligned values, except at image end */
18
dirname, cyls, heads, secs));
23
assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
19
24
assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
20
s->sector_count = cyls * heads * secs - s->offset_to_bootsector;
25
- end_offset == bs->total_sectors << BDRV_SECTOR_BITS);
21
+ bs->total_sectors = cyls * heads * secs;
26
+ end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
22
27
23
if (qemu_opt_get_bool(opts, "rw", false)) {
28
/* The zero flag is only supported by version 3 and newer */
24
if (!bdrv_is_read_only(bs)) {
29
if (s->qcow_version < 3) {
25
@@ -XXX,XX +XXX,XX @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
30
diff --git a/block/qcow2.c b/block/qcow2.c
26
}
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/qcow2.c
33
+++ b/block/qcow2.c
34
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
35
36
bs->supported_zero_flags = header.version >= 3 ?
37
BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK : 0;
38
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
40
/* Repair image if dirty */
41
if (!(flags & (BDRV_O_CHECK | BDRV_O_INACTIVE)) && !bs->read_only &&
42
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
43
g_assert_not_reached();
44
}
27
}
45
28
46
+ if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
29
- bs->total_sectors = cyls * heads * secs;
47
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
30
-
48
+
31
if (init_directories(s, dirname, heads, secs, errp)) {
49
+ /*
32
ret = -EIO;
50
+ * Use zero clusters as much as we can. qcow2_cluster_zeroize()
33
goto fail;
51
+ * requires a cluster-aligned start. The end may be unaligned if it is
34
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
52
+ * at the end of the image (which it is here).
35
}
53
+ */
36
54
+ ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
37
opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort);
55
+ if (ret < 0) {
38
- qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512,
56
+ error_setg_errno(errp, -ret, "Failed to zero out new clusters");
39
- &error_abort);
57
+ goto fail;
40
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE,
58
+ }
41
+ bs->total_sectors * BDRV_SECTOR_SIZE, &error_abort);
59
+
42
qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort);
60
+ /* Write explicit zeros for the unaligned head */
43
61
+ if (zero_start > old_length) {
44
ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp);
62
+ uint64_t len = zero_start - old_length;
63
+ uint8_t *buf = qemu_blockalign0(bs, len);
64
+ QEMUIOVector qiov;
65
+ qemu_iovec_init_buf(&qiov, buf, len);
66
+
67
+ qemu_co_mutex_unlock(&s->lock);
68
+ ret = qcow2_co_pwritev_part(bs, old_length, len, &qiov, 0, 0);
69
+ qemu_co_mutex_lock(&s->lock);
70
+
71
+ qemu_vfree(buf);
72
+ if (ret < 0) {
73
+ error_setg_errno(errp, -ret, "Failed to zero out the new area");
74
+ goto fail;
75
+ }
76
+ }
77
+ }
78
+
79
if (prealloc != PREALLOC_MODE_OFF) {
80
/* Flush metadata before actually changing the image size */
81
ret = qcow2_write_caches(bs);
82
--
45
--
83
2.25.3
46
2.31.1
84
47
85
48
diff view generated by jsdifflib
1
When extending the size of an image that has a backing file larger than
1
The calculation in sector2cluster() is done relative to the offset of
2
its old size, make sure that the backing file data doesn't become
2
the root directory. Any writes to blocks before the start of the root
3
visible in the guest, but the added area is properly zeroed out.
3
directory (in particular, writes to the FAT) result in negative values,
4
which are not handled correctly in vvfat_write().
4
5
5
Consider the following scenario where the overlay is shorter than its
6
This changes sector2cluster() to return a signed value, and makes sure
6
backing file:
7
that vvfat_write() doesn't try to find mappings for negative cluster
7
8
number. It clarifies the code in vvfat_write() to make it more obvious
8
base.qcow2: AAAAAAAA
9
that the cluster numbers can be negative.
9
overlay.qcow2: BBBB
10
11
When resizing (extending) overlay.qcow2, the new blocks should not stay
12
unallocated and make the additional As from base.qcow2 visible like
13
before this patch, but zeros should be read.
14
15
A similar case happens with the various variants of a commit job when an
16
intermediate file is short (- for unallocated):
17
18
base.qcow2: A-A-AAAA
19
mid.qcow2: BB-B
20
top.qcow2: C--C--C-
21
22
After commit top.qcow2 to mid.qcow2, the following happens:
23
24
mid.qcow2: CB-C00C0 (correct result)
25
mid.qcow2: CB-C--C- (before this fix)
26
27
Without the fix, blocks that previously read as zeros on top.qcow2
28
suddenly turn into A.
29
10
30
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
31
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Message-Id: <20211209152231.23756-1-kwolf@redhat.com>
32
Message-Id: <20200424125448.63318-8-kwolf@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
14
---
36
block/io.c | 25 +++++++++++++++++++++++++
15
block/vvfat.c | 30 ++++++++++++++++++++++--------
37
1 file changed, 25 insertions(+)
16
1 file changed, 22 insertions(+), 8 deletions(-)
38
17
39
diff --git a/block/io.c b/block/io.c
18
diff --git a/block/vvfat.c b/block/vvfat.c
40
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
41
--- a/block/io.c
20
--- a/block/vvfat.c
42
+++ b/block/io.c
21
+++ b/block/vvfat.c
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_truncate(BdrvChild *child, int64_t offset, bool exact,
22
@@ -XXX,XX +XXX,XX @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
44
goto out;
23
return 0;
45
}
24
}
46
25
26
-static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
27
+static inline int32_t sector2cluster(BDRVVVFATState* s,off_t sector_num)
28
{
29
return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster;
30
}
31
@@ -XXX,XX +XXX,XX @@ static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
32
{
33
BDRVVVFATState *s = bs->opaque;
34
int i, ret;
35
+ int first_cluster, last_cluster;
36
37
DLOG(checkpoint());
38
39
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
40
if (sector_num < s->offset_to_fat)
41
return -1;
42
43
- for (i = sector2cluster(s, sector_num);
44
- i <= sector2cluster(s, sector_num + nb_sectors - 1);) {
45
- mapping_t* mapping = find_mapping_for_cluster(s, i);
47
+ /*
46
+ /*
48
+ * If the image has a backing file that is large enough that it would
47
+ * Values will be negative for writes to the FAT, which is located before
49
+ * provide data for the new area, we cannot leave it unallocated because
48
+ * the root directory.
50
+ * then the backing file content would become visible. Instead, zero-fill
51
+ * the new area.
52
+ *
53
+ * Note that if the image has a backing file, but was opened without the
54
+ * backing file, taking care of keeping things consistent with that backing
55
+ * file is the user's responsibility.
56
+ */
49
+ */
57
+ if (new_bytes && bs->backing) {
50
+ first_cluster = sector2cluster(s, sector_num);
58
+ int64_t backing_len;
51
+ last_cluster = sector2cluster(s, sector_num + nb_sectors - 1);
59
+
52
+
60
+ backing_len = bdrv_getlength(backing_bs(bs));
53
+ for (i = first_cluster; i <= last_cluster;) {
61
+ if (backing_len < 0) {
54
+ mapping_t *mapping = NULL;
62
+ ret = backing_len;
55
+
63
+ error_setg_errno(errp, -ret, "Could not get backing file size");
56
+ if (i >= 0) {
64
+ goto out;
57
+ mapping = find_mapping_for_cluster(s, i);
65
+ }
58
+ }
66
+
59
+
67
+ if (backing_len > old_size) {
60
if (mapping) {
68
+ flags |= BDRV_REQ_ZERO_WRITE;
61
if (mapping->read_only) {
62
fprintf(stderr, "Tried to write to write-protected file %s\n",
63
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
64
}
65
}
66
i = mapping->end;
67
- } else
68
+ } else {
69
i++;
70
+ }
71
}
72
73
/*
74
@@ -XXX,XX +XXX,XX @@ DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sec
75
return ret;
76
}
77
78
- for (i = sector2cluster(s, sector_num);
79
- i <= sector2cluster(s, sector_num + nb_sectors - 1); i++)
80
- if (i >= 0)
81
+ for (i = first_cluster; i <= last_cluster; i++) {
82
+ if (i >= 0) {
83
s->used_clusters[i] |= USED_ALLOCATED;
69
+ }
84
+ }
70
+ }
85
+ }
71
+
86
72
if (drv->bdrv_co_truncate) {
87
DLOG(checkpoint());
73
if (flags & ~bs->supported_truncate_flags) {
88
/* TODO: add timeout */
74
error_setg(errp, "Block driver does not support requested flags");
75
--
89
--
76
2.25.3
90
2.31.1
77
91
78
92
diff view generated by jsdifflib
1
For regular files, we always get BDRV_REQ_ZERO_WRITE behaviour from the
1
This demonstrates what happens when the block status changes in
2
OS, so we can advertise the flag and just ignore it.
2
sub-min_sparse granularity, but all of the parts are zeroed out. The
3
alignment logic in is_allocated_sectors() prevents that the target image
4
remains fully sparse as expected, but turns it into a data cluster of
5
explicit zeros.
3
6
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Message-Id: <20211217164654.1184218-2-vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Tested-by: Peter Lieven <pl@kamp.de>
8
Message-Id: <20200424125448.63318-7-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
12
---
11
block/file-posix.c | 4 ++++
13
tests/qemu-iotests/122 | 1 +
12
1 file changed, 4 insertions(+)
14
tests/qemu-iotests/122.out | 10 ++++++++--
15
2 files changed, 9 insertions(+), 2 deletions(-)
13
16
14
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
18
index XXXXXXX..XXXXXXX 100755
19
--- a/tests/qemu-iotests/122
20
+++ b/tests/qemu-iotests/122
21
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_test
22
$QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
23
$QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
24
$QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
25
+$QEMU_IO -c "write -P 0 65k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
26
27
for min_sparse in 4k 8k; do
28
echo
29
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
15
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
16
--- a/block/file-posix.c
31
--- a/tests/qemu-iotests/122.out
17
+++ b/block/file-posix.c
32
+++ b/tests/qemu-iotests/122.out
18
@@ -XXX,XX +XXX,XX @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
33
@@ -XXX,XX +XXX,XX @@ wrote 1024/1024 bytes at offset 8192
19
#endif
34
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
20
35
wrote 1024/1024 bytes at offset 17408
21
bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
36
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
22
+ if (S_ISREG(st.st_mode)) {
37
+wrote 1024/1024 bytes at offset 66560
23
+ /* When extending regular files, we get zeros from the OS */
38
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
24
+ bs->supported_truncate_flags = BDRV_REQ_ZERO_WRITE;
39
25
+ }
40
convert -S 4k
26
ret = 0;
41
[{ "start": 0, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
27
fail:
42
@@ -XXX,XX +XXX,XX @@ convert -S 4k
28
if (filename && (bdrv_flags & BDRV_O_TEMPORARY)) {
43
{ "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
44
{ "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false},
45
{ "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
46
-{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}]
47
+{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false},
48
+{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
49
+{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
50
51
convert -c -S 4k
52
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
53
@@ -XXX,XX +XXX,XX @@ convert -c -S 4k
54
55
convert -S 8k
56
[{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
57
-{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}]
58
+{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false},
59
+{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
60
+{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
61
62
convert -c -S 8k
63
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
29
--
64
--
30
2.25.3
65
2.31.1
31
66
32
67
diff view generated by jsdifflib
1
From: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
This patch introduces support for PMR that has been defined as part of NVMe 1.4
3
Consider the case when the whole buffer is zero and end is unaligned.
4
spec. User can now specify a pmrdev option that should point to HostMemoryBackend.
5
pmrdev memory region will subsequently be exposed as PCI BAR 2 in emulated NVMe
6
device. Guest OS can perform mmio read and writes to the PMR region that will stay
7
persistent across system reboot.
8
4
9
Signed-off-by: Andrzej Jakowski <andrzej.jakowski@linux.intel.com>
5
If i <= tail, we return 1 and do one unaligned WRITE, RMW happens.
10
Reviewed-by: Klaus Jensen <k.jensen@samsung.com>
6
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
If i > tail, we do on aligned WRITE_ZERO (or skip if target is zeroed)
12
Message-Id: <20200330164656.9348-1-andrzej.jakowski@linux.intel.com>
8
and again one unaligned WRITE, RMW happens.
13
Reviewed-by: Keith Busch <kbusch@kernel.org>
9
10
Let's do better: don't fragment the whole-zero buffer and report it as
11
ZERO: in case of zeroed target we just do nothing and avoid RMW. If
12
target is not zeroes, one unaligned WRITE_ZERO should not be much worse
13
than one unaligned WRITE.
14
15
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-Id: <20211217164654.1184218-3-vsementsov@virtuozzo.com>
17
Tested-by: Peter Lieven <pl@kamp.de>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
19
---
16
hw/block/nvme.h | 2 +
20
qemu-img.c | 23 +++++++++++++++++++----
17
include/block/nvme.h | 172 +++++++++++++++++++++++++++++++++++++++++
21
tests/qemu-iotests/122.out | 8 ++------
18
hw/block/nvme.c | 109 ++++++++++++++++++++++++++
22
2 files changed, 21 insertions(+), 10 deletions(-)
19
hw/block/Makefile.objs | 2 +-
20
hw/block/trace-events | 4 +
21
5 files changed, 288 insertions(+), 1 deletion(-)
22
23
23
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
24
diff --git a/qemu-img.c b/qemu-img.c
24
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/block/nvme.h
26
--- a/qemu-img.c
26
+++ b/hw/block/nvme.h
27
+++ b/qemu-img.c
27
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
28
@@ -XXX,XX +XXX,XX @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum,
28
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
29
}
29
30
char *serial;
31
+ HostMemoryBackend *pmrdev;
32
+
33
NvmeNamespace *namespaces;
34
NvmeSQueue **sq;
35
NvmeCQueue **cq;
36
diff --git a/include/block/nvme.h b/include/block/nvme.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/nvme.h
39
+++ b/include/block/nvme.h
40
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeBar {
41
uint64_t acq;
42
uint32_t cmbloc;
43
uint32_t cmbsz;
44
+ uint8_t padding[3520]; /* not used by QEMU */
45
+ uint32_t pmrcap;
46
+ uint32_t pmrctl;
47
+ uint32_t pmrsts;
48
+ uint32_t pmrebs;
49
+ uint32_t pmrswtp;
50
+ uint32_t pmrmsc;
51
} NvmeBar;
52
53
enum NvmeCapShift {
54
@@ -XXX,XX +XXX,XX @@ enum NvmeCapShift {
55
CAP_CSS_SHIFT = 37,
56
CAP_MPSMIN_SHIFT = 48,
57
CAP_MPSMAX_SHIFT = 52,
58
+ CAP_PMR_SHIFT = 56,
59
};
60
61
enum NvmeCapMask {
62
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
63
CAP_CSS_MASK = 0xff,
64
CAP_MPSMIN_MASK = 0xf,
65
CAP_MPSMAX_MASK = 0xf,
66
+ CAP_PMR_MASK = 0x1,
67
};
68
69
#define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK)
70
@@ -XXX,XX +XXX,XX @@ enum NvmeCapMask {
71
<< CAP_MPSMIN_SHIFT)
72
#define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\
73
<< CAP_MPSMAX_SHIFT)
74
+#define NVME_CAP_SET_PMRS(cap, val) (cap |= (uint64_t)(val & CAP_PMR_MASK)\
75
+ << CAP_PMR_SHIFT)
76
77
enum NvmeCcShift {
78
CC_EN_SHIFT = 0,
79
@@ -XXX,XX +XXX,XX @@ enum NvmeCmbszMask {
80
#define NVME_CMBSZ_GETSIZE(cmbsz) \
81
(NVME_CMBSZ_SZ(cmbsz) * (1 << (12 + 4 * NVME_CMBSZ_SZU(cmbsz))))
82
83
+enum NvmePmrcapShift {
84
+ PMRCAP_RDS_SHIFT = 3,
85
+ PMRCAP_WDS_SHIFT = 4,
86
+ PMRCAP_BIR_SHIFT = 5,
87
+ PMRCAP_PMRTU_SHIFT = 8,
88
+ PMRCAP_PMRWBM_SHIFT = 10,
89
+ PMRCAP_PMRTO_SHIFT = 16,
90
+ PMRCAP_CMSS_SHIFT = 24,
91
+};
92
+
93
+enum NvmePmrcapMask {
94
+ PMRCAP_RDS_MASK = 0x1,
95
+ PMRCAP_WDS_MASK = 0x1,
96
+ PMRCAP_BIR_MASK = 0x7,
97
+ PMRCAP_PMRTU_MASK = 0x3,
98
+ PMRCAP_PMRWBM_MASK = 0xf,
99
+ PMRCAP_PMRTO_MASK = 0xff,
100
+ PMRCAP_CMSS_MASK = 0x1,
101
+};
102
+
103
+#define NVME_PMRCAP_RDS(pmrcap) \
104
+ ((pmrcap >> PMRCAP_RDS_SHIFT) & PMRCAP_RDS_MASK)
105
+#define NVME_PMRCAP_WDS(pmrcap) \
106
+ ((pmrcap >> PMRCAP_WDS_SHIFT) & PMRCAP_WDS_MASK)
107
+#define NVME_PMRCAP_BIR(pmrcap) \
108
+ ((pmrcap >> PMRCAP_BIR_SHIFT) & PMRCAP_BIR_MASK)
109
+#define NVME_PMRCAP_PMRTU(pmrcap) \
110
+ ((pmrcap >> PMRCAP_PMRTU_SHIFT) & PMRCAP_PMRTU_MASK)
111
+#define NVME_PMRCAP_PMRWBM(pmrcap) \
112
+ ((pmrcap >> PMRCAP_PMRWBM_SHIFT) & PMRCAP_PMRWBM_MASK)
113
+#define NVME_PMRCAP_PMRTO(pmrcap) \
114
+ ((pmrcap >> PMRCAP_PMRTO_SHIFT) & PMRCAP_PMRTO_MASK)
115
+#define NVME_PMRCAP_CMSS(pmrcap) \
116
+ ((pmrcap >> PMRCAP_CMSS_SHIFT) & PMRCAP_CMSS_MASK)
117
+
118
+#define NVME_PMRCAP_SET_RDS(pmrcap, val) \
119
+ (pmrcap |= (uint64_t)(val & PMRCAP_RDS_MASK) << PMRCAP_RDS_SHIFT)
120
+#define NVME_PMRCAP_SET_WDS(pmrcap, val) \
121
+ (pmrcap |= (uint64_t)(val & PMRCAP_WDS_MASK) << PMRCAP_WDS_SHIFT)
122
+#define NVME_PMRCAP_SET_BIR(pmrcap, val) \
123
+ (pmrcap |= (uint64_t)(val & PMRCAP_BIR_MASK) << PMRCAP_BIR_SHIFT)
124
+#define NVME_PMRCAP_SET_PMRTU(pmrcap, val) \
125
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTU_MASK) << PMRCAP_PMRTU_SHIFT)
126
+#define NVME_PMRCAP_SET_PMRWBM(pmrcap, val) \
127
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRWBM_MASK) << PMRCAP_PMRWBM_SHIFT)
128
+#define NVME_PMRCAP_SET_PMRTO(pmrcap, val) \
129
+ (pmrcap |= (uint64_t)(val & PMRCAP_PMRTO_MASK) << PMRCAP_PMRTO_SHIFT)
130
+#define NVME_PMRCAP_SET_CMSS(pmrcap, val) \
131
+ (pmrcap |= (uint64_t)(val & PMRCAP_CMSS_MASK) << PMRCAP_CMSS_SHIFT)
132
+
133
+enum NvmePmrctlShift {
134
+ PMRCTL_EN_SHIFT = 0,
135
+};
136
+
137
+enum NvmePmrctlMask {
138
+ PMRCTL_EN_MASK = 0x1,
139
+};
140
+
141
+#define NVME_PMRCTL_EN(pmrctl) ((pmrctl >> PMRCTL_EN_SHIFT) & PMRCTL_EN_MASK)
142
+
143
+#define NVME_PMRCTL_SET_EN(pmrctl, val) \
144
+ (pmrctl |= (uint64_t)(val & PMRCTL_EN_MASK) << PMRCTL_EN_SHIFT)
145
+
146
+enum NvmePmrstsShift {
147
+ PMRSTS_ERR_SHIFT = 0,
148
+ PMRSTS_NRDY_SHIFT = 8,
149
+ PMRSTS_HSTS_SHIFT = 9,
150
+ PMRSTS_CBAI_SHIFT = 12,
151
+};
152
+
153
+enum NvmePmrstsMask {
154
+ PMRSTS_ERR_MASK = 0xff,
155
+ PMRSTS_NRDY_MASK = 0x1,
156
+ PMRSTS_HSTS_MASK = 0x7,
157
+ PMRSTS_CBAI_MASK = 0x1,
158
+};
159
+
160
+#define NVME_PMRSTS_ERR(pmrsts) \
161
+ ((pmrsts >> PMRSTS_ERR_SHIFT) & PMRSTS_ERR_MASK)
162
+#define NVME_PMRSTS_NRDY(pmrsts) \
163
+ ((pmrsts >> PMRSTS_NRDY_SHIFT) & PMRSTS_NRDY_MASK)
164
+#define NVME_PMRSTS_HSTS(pmrsts) \
165
+ ((pmrsts >> PMRSTS_HSTS_SHIFT) & PMRSTS_HSTS_MASK)
166
+#define NVME_PMRSTS_CBAI(pmrsts) \
167
+ ((pmrsts >> PMRSTS_CBAI_SHIFT) & PMRSTS_CBAI_MASK)
168
+
169
+#define NVME_PMRSTS_SET_ERR(pmrsts, val) \
170
+ (pmrsts |= (uint64_t)(val & PMRSTS_ERR_MASK) << PMRSTS_ERR_SHIFT)
171
+#define NVME_PMRSTS_SET_NRDY(pmrsts, val) \
172
+ (pmrsts |= (uint64_t)(val & PMRSTS_NRDY_MASK) << PMRSTS_NRDY_SHIFT)
173
+#define NVME_PMRSTS_SET_HSTS(pmrsts, val) \
174
+ (pmrsts |= (uint64_t)(val & PMRSTS_HSTS_MASK) << PMRSTS_HSTS_SHIFT)
175
+#define NVME_PMRSTS_SET_CBAI(pmrsts, val) \
176
+ (pmrsts |= (uint64_t)(val & PMRSTS_CBAI_MASK) << PMRSTS_CBAI_SHIFT)
177
+
178
+enum NvmePmrebsShift {
179
+ PMREBS_PMRSZU_SHIFT = 0,
180
+ PMREBS_RBB_SHIFT = 4,
181
+ PMREBS_PMRWBZ_SHIFT = 8,
182
+};
183
+
184
+enum NvmePmrebsMask {
185
+ PMREBS_PMRSZU_MASK = 0xf,
186
+ PMREBS_RBB_MASK = 0x1,
187
+ PMREBS_PMRWBZ_MASK = 0xffffff,
188
+};
189
+
190
+#define NVME_PMREBS_PMRSZU(pmrebs) \
191
+ ((pmrebs >> PMREBS_PMRSZU_SHIFT) & PMREBS_PMRSZU_MASK)
192
+#define NVME_PMREBS_RBB(pmrebs) \
193
+ ((pmrebs >> PMREBS_RBB_SHIFT) & PMREBS_RBB_MASK)
194
+#define NVME_PMREBS_PMRWBZ(pmrebs) \
195
+ ((pmrebs >> PMREBS_PMRWBZ_SHIFT) & PMREBS_PMRWBZ_MASK)
196
+
197
+#define NVME_PMREBS_SET_PMRSZU(pmrebs, val) \
198
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRSZU_MASK) << PMREBS_PMRSZU_SHIFT)
199
+#define NVME_PMREBS_SET_RBB(pmrebs, val) \
200
+ (pmrebs |= (uint64_t)(val & PMREBS_RBB_MASK) << PMREBS_RBB_SHIFT)
201
+#define NVME_PMREBS_SET_PMRWBZ(pmrebs, val) \
202
+ (pmrebs |= (uint64_t)(val & PMREBS_PMRWBZ_MASK) << PMREBS_PMRWBZ_SHIFT)
203
+
204
+enum NvmePmrswtpShift {
205
+ PMRSWTP_PMRSWTU_SHIFT = 0,
206
+ PMRSWTP_PMRSWTV_SHIFT = 8,
207
+};
208
+
209
+enum NvmePmrswtpMask {
210
+ PMRSWTP_PMRSWTU_MASK = 0xf,
211
+ PMRSWTP_PMRSWTV_MASK = 0xffffff,
212
+};
213
+
214
+#define NVME_PMRSWTP_PMRSWTU(pmrswtp) \
215
+ ((pmrswtp >> PMRSWTP_PMRSWTU_SHIFT) & PMRSWTP_PMRSWTU_MASK)
216
+#define NVME_PMRSWTP_PMRSWTV(pmrswtp) \
217
+ ((pmrswtp >> PMRSWTP_PMRSWTV_SHIFT) & PMRSWTP_PMRSWTV_MASK)
218
+
219
+#define NVME_PMRSWTP_SET_PMRSWTU(pmrswtp, val) \
220
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTU_MASK) << PMRSWTP_PMRSWTU_SHIFT)
221
+#define NVME_PMRSWTP_SET_PMRSWTV(pmrswtp, val) \
222
+ (pmrswtp |= (uint64_t)(val & PMRSWTP_PMRSWTV_MASK) << PMRSWTP_PMRSWTV_SHIFT)
223
+
224
+enum NvmePmrmscShift {
225
+ PMRMSC_CMSE_SHIFT = 1,
226
+ PMRMSC_CBA_SHIFT = 12,
227
+};
228
+
229
+enum NvmePmrmscMask {
230
+ PMRMSC_CMSE_MASK = 0x1,
231
+ PMRMSC_CBA_MASK = 0xfffffffffffff,
232
+};
233
+
234
+#define NVME_PMRMSC_CMSE(pmrmsc) \
235
+ ((pmrmsc >> PMRMSC_CMSE_SHIFT) & PMRMSC_CMSE_MASK)
236
+#define NVME_PMRMSC_CBA(pmrmsc) \
237
+ ((pmrmsc >> PMRMSC_CBA_SHIFT) & PMRMSC_CBA_MASK)
238
+
239
+#define NVME_PMRMSC_SET_CMSE(pmrmsc, val) \
240
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CMSE_MASK) << PMRMSC_CMSE_SHIFT)
241
+#define NVME_PMRMSC_SET_CBA(pmrmsc, val) \
242
+ (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
243
+
244
typedef struct NvmeCmd {
245
uint8_t opcode;
246
uint8_t fuse;
247
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
248
index XXXXXXX..XXXXXXX 100644
249
--- a/hw/block/nvme.c
250
+++ b/hw/block/nvme.c
251
@@ -XXX,XX +XXX,XX @@
252
* -drive file=<file>,if=none,id=<drive_id>
253
* -device nvme,drive=<drive_id>,serial=<serial>,id=<id[optional]>, \
254
* cmb_size_mb=<cmb_size_mb[optional]>, \
255
+ * [pmrdev=<mem_backend_file_id>,] \
256
* num_queues=<N[optional]>
257
*
258
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
259
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now.
260
+ *
261
+ * cmb_size_mb= and pmrdev= options are mutually exclusive due to limitation
262
+ * in available BAR's. cmb_size_mb= will take precedence over pmrdev= when
263
+ * both provided.
264
+ * Enabling pmr emulation can be achieved by pointing to memory-backend-file.
265
+ * For example:
266
+ * -object memory-backend-file,id=<mem_id>,share=on,mem-path=<file_path>, \
267
+ * size=<size> .... -device nvme,...,pmrdev=<mem_id>
268
*/
269
270
#include "qemu/osdep.h"
271
@@ -XXX,XX +XXX,XX @@
272
#include "sysemu/sysemu.h"
273
#include "qapi/error.h"
274
#include "qapi/visitor.h"
275
+#include "sysemu/hostmem.h"
276
#include "sysemu/block-backend.h"
277
+#include "exec/ram_addr.h"
278
279
#include "qemu/log.h"
280
#include "qemu/module.h"
281
@@ -XXX,XX +XXX,XX @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
282
NVME_GUEST_ERR(nvme_ub_mmiowr_cmbsz_readonly,
283
"invalid write to read only CMBSZ, ignored");
284
return;
285
+ case 0xE00: /* PMRCAP */
286
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrcap_readonly,
287
+ "invalid write to PMRCAP register, ignored");
288
+ return;
289
+ case 0xE04: /* TODO PMRCTL */
290
+ break;
291
+ case 0xE08: /* PMRSTS */
292
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrsts_readonly,
293
+ "invalid write to PMRSTS register, ignored");
294
+ return;
295
+ case 0xE0C: /* PMREBS */
296
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrebs_readonly,
297
+ "invalid write to PMREBS register, ignored");
298
+ return;
299
+ case 0xE10: /* PMRSWTP */
300
+ NVME_GUEST_ERR(nvme_ub_mmiowr_pmrswtp_readonly,
301
+ "invalid write to PMRSWTP register, ignored");
302
+ return;
303
+ case 0xE14: /* TODO PMRMSC */
304
+ break;
305
default:
306
NVME_GUEST_ERR(nvme_ub_mmiowr_invalid,
307
"invalid MMIO write,"
308
@@ -XXX,XX +XXX,XX @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
309
}
30
}
310
31
311
if (addr < sizeof(n->bar)) {
32
+ if (i == n) {
312
+ /*
33
+ /*
313
+ * When PMRWBM bit 1 is set then read from
34
+ * The whole buf is the same.
314
+ * from PMRSTS should ensure prior writes
35
+ * No reason to split it into chunks, so return now.
315
+ * made it to persistent media
316
+ */
36
+ */
317
+ if (addr == 0xE08 &&
37
+ *pnum = i;
318
+ (NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
38
+ return !is_zero;
319
+ qemu_ram_writeback(n->pmrdev->mr.ram_block,
320
+ 0, n->pmrdev->size);
321
+ }
322
memcpy(&val, ptr + addr, size);
323
} else {
324
NVME_GUEST_ERR(nvme_ub_mmiord_invalid_ofs,
325
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
326
error_setg(errp, "serial property not set");
327
return;
328
}
329
+
330
+ if (!n->cmb_size_mb && n->pmrdev) {
331
+ if (host_memory_backend_is_mapped(n->pmrdev)) {
332
+ char *path = object_get_canonical_path_component(OBJECT(n->pmrdev));
333
+ error_setg(errp, "can't use already busy memdev: %s", path);
334
+ g_free(path);
335
+ return;
336
+ }
337
+
338
+ if (!is_power_of_2(n->pmrdev->size)) {
339
+ error_setg(errp, "pmr backend size needs to be power of 2 in size");
340
+ return;
341
+ }
342
+
343
+ host_memory_backend_set_mapped(n->pmrdev, true);
344
+ }
39
+ }
345
+
40
+
346
blkconf_blocksizes(&n->conf);
41
tail = (sector_num + i) & (alignment - 1);
347
if (!blkconf_apply_backend_options(&n->conf, blk_is_read_only(n->conf.blk),
42
if (tail) {
348
false, errp)) {
43
if (is_zero && i <= tail) {
349
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
44
- /* treat unallocated areas which only consist
350
PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
45
- * of a small tail as allocated. */
351
PCI_BASE_ADDRESS_MEM_PREFETCH, &n->ctrl_mem);
46
+ /*
352
47
+ * For sure next sector after i is data, and it will rewrite this
353
+ } else if (n->pmrdev) {
48
+ * tail anyway due to RMW. So, let's just write data now.
354
+ /* Controller Capabilities register */
49
+ */
355
+ NVME_CAP_SET_PMRS(n->bar.cap, 1);
50
is_zero = false;
356
+
51
}
357
+ /* PMR Capabities register */
52
if (!is_zero) {
358
+ n->bar.pmrcap = 0;
53
- /* align up end offset of allocated areas. */
359
+ NVME_PMRCAP_SET_RDS(n->bar.pmrcap, 0);
54
+ /* If possible, align up end offset of allocated areas. */
360
+ NVME_PMRCAP_SET_WDS(n->bar.pmrcap, 0);
55
i += alignment - tail;
361
+ NVME_PMRCAP_SET_BIR(n->bar.pmrcap, 2);
56
i = MIN(i, n);
362
+ NVME_PMRCAP_SET_PMRTU(n->bar.pmrcap, 0);
57
} else {
363
+ /* Turn on bit 1 support */
58
- /* align down end offset of zero areas. */
364
+ NVME_PMRCAP_SET_PMRWBM(n->bar.pmrcap, 0x02);
59
+ /*
365
+ NVME_PMRCAP_SET_PMRTO(n->bar.pmrcap, 0);
60
+ * For sure next sector after i is data, and it will rewrite this
366
+ NVME_PMRCAP_SET_CMSS(n->bar.pmrcap, 0);
61
+ * tail anyway due to RMW. Better is avoid RMW and write zeroes up
367
+
62
+ * to aligned bound.
368
+ /* PMR Control register */
63
+ */
369
+ n->bar.pmrctl = 0;
64
i -= tail;
370
+ NVME_PMRCTL_SET_EN(n->bar.pmrctl, 0);
65
}
371
+
372
+ /* PMR Status register */
373
+ n->bar.pmrsts = 0;
374
+ NVME_PMRSTS_SET_ERR(n->bar.pmrsts, 0);
375
+ NVME_PMRSTS_SET_NRDY(n->bar.pmrsts, 0);
376
+ NVME_PMRSTS_SET_HSTS(n->bar.pmrsts, 0);
377
+ NVME_PMRSTS_SET_CBAI(n->bar.pmrsts, 0);
378
+
379
+ /* PMR Elasticity Buffer Size register */
380
+ n->bar.pmrebs = 0;
381
+ NVME_PMREBS_SET_PMRSZU(n->bar.pmrebs, 0);
382
+ NVME_PMREBS_SET_RBB(n->bar.pmrebs, 0);
383
+ NVME_PMREBS_SET_PMRWBZ(n->bar.pmrebs, 0);
384
+
385
+ /* PMR Sustained Write Throughput register */
386
+ n->bar.pmrswtp = 0;
387
+ NVME_PMRSWTP_SET_PMRSWTU(n->bar.pmrswtp, 0);
388
+ NVME_PMRSWTP_SET_PMRSWTV(n->bar.pmrswtp, 0);
389
+
390
+ /* PMR Memory Space Control register */
391
+ n->bar.pmrmsc = 0;
392
+ NVME_PMRMSC_SET_CMSE(n->bar.pmrmsc, 0);
393
+ NVME_PMRMSC_SET_CBA(n->bar.pmrmsc, 0);
394
+
395
+ pci_register_bar(pci_dev, NVME_PMRCAP_BIR(n->bar.pmrcap),
396
+ PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64 |
397
+ PCI_BASE_ADDRESS_MEM_PREFETCH, &n->pmrdev->mr);
398
}
66
}
399
67
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
400
for (i = 0; i < n->num_namespaces; i++) {
401
@@ -XXX,XX +XXX,XX @@ static void nvme_exit(PCIDevice *pci_dev)
402
if (n->cmb_size_mb) {
403
g_free(n->cmbuf);
404
}
405
+
406
+ if (n->pmrdev) {
407
+ host_memory_backend_set_mapped(n->pmrdev, false);
408
+ }
409
msix_uninit_exclusive_bar(pci_dev);
410
}
411
412
static Property nvme_props[] = {
413
DEFINE_BLOCK_PROPERTIES(NvmeCtrl, conf),
414
+ DEFINE_PROP_LINK("pmrdev", NvmeCtrl, pmrdev, TYPE_MEMORY_BACKEND,
415
+ HostMemoryBackend *),
416
DEFINE_PROP_STRING("serial", NvmeCtrl, serial),
417
DEFINE_PROP_UINT32("cmb_size_mb", NvmeCtrl, cmb_size_mb, 0),
418
DEFINE_PROP_UINT32("num_queues", NvmeCtrl, num_queues, 64),
419
diff --git a/hw/block/Makefile.objs b/hw/block/Makefile.objs
420
index XXXXXXX..XXXXXXX 100644
68
index XXXXXXX..XXXXXXX 100644
421
--- a/hw/block/Makefile.objs
69
--- a/tests/qemu-iotests/122.out
422
+++ b/hw/block/Makefile.objs
70
+++ b/tests/qemu-iotests/122.out
423
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
71
@@ -XXX,XX +XXX,XX @@ convert -S 4k
424
common-obj-$(CONFIG_XEN) += xen-block.o
72
{ "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
425
common-obj-$(CONFIG_ECC) += ecc.o
73
{ "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false},
426
common-obj-$(CONFIG_ONENAND) += onenand.o
74
{ "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
427
-common-obj-$(CONFIG_NVME_PCI) += nvme.o
75
-{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false},
428
common-obj-$(CONFIG_SWIM) += swim.o
76
-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
429
77
-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
430
common-obj-$(CONFIG_SH4) += tc58128.o
78
+{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}]
431
79
432
obj-$(CONFIG_VIRTIO_BLK) += virtio-blk.o
80
convert -c -S 4k
433
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk.o
81
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
434
+obj-$(CONFIG_NVME_PCI) += nvme.o
82
@@ -XXX,XX +XXX,XX @@ convert -c -S 4k
435
83
436
obj-y += dataplane/
84
convert -S 8k
437
diff --git a/hw/block/trace-events b/hw/block/trace-events
85
[{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
438
index XXXXXXX..XXXXXXX 100644
86
-{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false},
439
--- a/hw/block/trace-events
87
-{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET},
440
+++ b/hw/block/trace-events
88
-{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}]
441
@@ -XXX,XX +XXX,XX @@ nvme_ub_mmiowr_ssreset_w1c_unsupported(void) "attempted to W1C CSTS.NSSRO but CA
89
+{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}]
442
nvme_ub_mmiowr_ssreset_unsupported(void) "attempted NVM subsystem reset but CAP.NSSRS is zero (not supported)"
90
443
nvme_ub_mmiowr_cmbloc_reserved(void) "invalid write to reserved CMBLOC when CMBSZ is zero, ignored"
91
convert -c -S 8k
444
nvme_ub_mmiowr_cmbsz_readonly(void) "invalid write to read only CMBSZ, ignored"
92
[{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true},
445
+nvme_ub_mmiowr_pmrcap_readonly(void) "invalid write to read only PMRCAP, ignored"
446
+nvme_ub_mmiowr_pmrsts_readonly(void) "invalid write to read only PMRSTS, ignored"
447
+nvme_ub_mmiowr_pmrebs_readonly(void) "invalid write to read only PMREBS, ignored"
448
+nvme_ub_mmiowr_pmrswtp_readonly(void) "invalid write to read only PMRSWTP, ignored"
449
nvme_ub_mmiowr_invalid(uint64_t offset, uint64_t data) "invalid MMIO write, offset=0x%"PRIx64", data=0x%"PRIx64""
450
nvme_ub_mmiord_misaligned32(uint64_t offset) "MMIO read not 32-bit aligned, offset=0x%"PRIx64""
451
nvme_ub_mmiord_toosmall(uint64_t offset) "MMIO read smaller than 32-bits, offset=0x%"PRIx64""
452
--
93
--
453
2.25.3
94
2.31.1
454
95
455
96
diff view generated by jsdifflib
1
Now that node level interface bdrv_truncate() supports passing request
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
flags to the block driver, expose this on the BlockBackend level, too.
2
3
3
First, this permission never protected a node from being changed, as
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
generic child-replacing functions don't check it.
5
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
5
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Second, it's a strange thing: it presents a permission of parent node
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
to change its child. But generally, children are replaced by different
8
Message-Id: <20200424125448.63318-4-kwolf@redhat.com>
8
mechanisms, like jobs or qmp commands, not by nodes.
9
10
Graph-mod permission is hard to understand. All other permissions
11
describe operations which done by parent node on its child: read,
12
write, resize. Graph modification operations are something completely
13
different.
14
15
The only place where BLK_PERM_GRAPH_MOD is used as "perm" (not shared
16
perm) is mirror_start_job, for s->target. Still modern code should use
17
bdrv_freeze_backing_chain() to protect from graph modification, if we
18
don't do it somewhere it may be considered as a bug. So, it's a bit
19
risky to drop GRAPH_MOD, and analyzing of possible loss of protection
20
is hard. But one day we should do it, let's do it now.
21
22
One more bit of information is that locking the corresponding byte in
23
file-posix doesn't make sense at all.
24
25
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
26
Message-Id: <20210902093754.2352-1-vsementsov@virtuozzo.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
28
---
11
include/sysemu/block-backend.h | 2 +-
29
qapi/block-core.json | 7 ++-----
12
block.c | 3 ++-
30
include/block/block.h | 9 +++++----
13
block/block-backend.c | 4 ++--
31
block.c | 7 +------
14
block/commit.c | 4 ++--
32
block/commit.c | 1 -
15
block/crypto.c | 2 +-
33
block/mirror.c | 15 +++------------
16
block/mirror.c | 2 +-
34
hw/block/block.c | 3 +--
17
block/qcow2.c | 4 ++--
35
scripts/render_block_graph.py | 1 -
18
block/qed.c | 2 +-
36
tests/qemu-iotests/273.out | 4 ----
19
block/vdi.c | 2 +-
37
8 files changed, 12 insertions(+), 35 deletions(-)
20
block/vhdx.c | 4 ++--
38
21
block/vmdk.c | 6 +++---
39
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
block/vpc.c | 2 +-
40
index XXXXXXX..XXXXXXX 100644
23
blockdev.c | 2 +-
41
--- a/qapi/block-core.json
24
qemu-img.c | 2 +-
42
+++ b/qapi/block-core.json
25
qemu-io-cmds.c | 2 +-
43
@@ -XXX,XX +XXX,XX @@
26
15 files changed, 22 insertions(+), 21 deletions(-)
44
#
27
45
# @resize: This permission is required to change the size of a block node.
28
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
46
#
29
index XXXXXXX..XXXXXXX 100644
47
-# @graph-mod: This permission is required to change the node that this
30
--- a/include/sysemu/block-backend.h
48
-# BdrvChild points to.
31
+++ b/include/sysemu/block-backend.h
49
-#
32
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
50
# Since: 4.0
33
int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
51
##
34
int bytes);
52
{ 'enum': 'BlockPermission',
35
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
53
- 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize',
36
- PreallocMode prealloc, Error **errp);
54
- 'graph-mod' ] }
37
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
55
+ 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize' ] }
38
int blk_pdiscard(BlockBackend *blk, int64_t offset, int bytes);
56
+
39
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
57
##
40
int64_t pos, int size);
58
# @XDbgBlockGraphEdge:
59
#
60
diff --git a/include/block/block.h b/include/block/block.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/include/block/block.h
63
+++ b/include/block/block.h
64
@@ -XXX,XX +XXX,XX @@ enum {
65
BLK_PERM_RESIZE = 0x08,
66
67
/**
68
- * This permission is required to change the node that this BdrvChild
69
- * points to.
70
+ * There was a now-removed bit BLK_PERM_GRAPH_MOD, with value of 0x10. QEMU
71
+ * 6.1 and earlier may still lock the corresponding byte in block/file-posix
72
+ * locking. So, implementing some new permission should be very careful to
73
+ * not interfere with this old unused thing.
74
*/
75
- BLK_PERM_GRAPH_MOD = 0x10,
76
77
- BLK_PERM_ALL = 0x1f,
78
+ BLK_PERM_ALL = 0x0f,
79
80
DEFAULT_PERM_PASSTHROUGH = BLK_PERM_CONSISTENT_READ
81
| BLK_PERM_WRITE
41
diff --git a/block.c b/block.c
82
diff --git a/block.c b/block.c
42
index XXXXXXX..XXXXXXX 100644
83
index XXXXXXX..XXXXXXX 100644
43
--- a/block.c
84
--- a/block.c
44
+++ b/block.c
85
+++ b/block.c
45
@@ -XXX,XX +XXX,XX @@ static int64_t create_file_fallback_truncate(BlockBackend *blk,
86
@@ -XXX,XX +XXX,XX @@ char *bdrv_perm_names(uint64_t perm)
46
int64_t size;
87
{ BLK_PERM_WRITE, "write" },
47
int ret;
88
{ BLK_PERM_WRITE_UNCHANGED, "write unchanged" },
48
89
{ BLK_PERM_RESIZE, "resize" },
49
- ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, &local_err);
90
- { BLK_PERM_GRAPH_MOD, "change children" },
50
+ ret = blk_truncate(blk, minimum_size, false, PREALLOC_MODE_OFF, 0,
91
{ 0, NULL }
51
+ &local_err);
92
};
52
if (ret < 0 && ret != -ENOTSUP) {
93
53
error_propagate(errp, local_err);
94
@@ -XXX,XX +XXX,XX @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c,
54
return ret;
95
shared = 0;
55
diff --git a/block/block-backend.c b/block/block-backend.c
96
}
56
index XXXXXXX..XXXXXXX 100644
97
57
--- a/block/block-backend.c
98
- shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD |
58
+++ b/block/block-backend.c
99
- BLK_PERM_WRITE_UNCHANGED;
59
@@ -XXX,XX +XXX,XX @@ int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
100
+ shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
60
}
101
61
102
if (bs->open_flags & BDRV_O_INACTIVE) {
62
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
103
shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE;
63
- PreallocMode prealloc, Error **errp)
104
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
64
+ PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
105
[BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE,
65
{
106
[BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED,
66
if (!blk_is_available(blk)) {
107
[BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE,
67
error_setg(errp, "No medium inserted");
108
- [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD,
68
return -ENOMEDIUM;
109
};
69
}
110
70
111
QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX);
71
- return bdrv_truncate(blk->root, offset, exact, prealloc, 0, errp);
112
@@ -XXX,XX +XXX,XX @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base,
72
+ return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
113
update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top);
73
}
114
74
115
/* success - we can delete the intermediate states, and link top->base */
75
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
116
- /* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once
117
- * we've figured out how they should work. */
118
if (!backing_file_str) {
119
bdrv_refresh_filename(base);
120
backing_file_str = base->filename;
76
diff --git a/block/commit.c b/block/commit.c
121
diff --git a/block/commit.c b/block/commit.c
77
index XXXXXXX..XXXXXXX 100644
122
index XXXXXXX..XXXXXXX 100644
78
--- a/block/commit.c
123
--- a/block/commit.c
79
+++ b/block/commit.c
124
+++ b/block/commit.c
80
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
125
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
81
}
126
s->base = blk_new(s->common.job.aio_context,
82
127
base_perms,
83
if (base_len < len) {
128
BLK_PERM_CONSISTENT_READ
84
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, NULL);
129
- | BLK_PERM_GRAPH_MOD
85
+ ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
130
| BLK_PERM_WRITE_UNCHANGED);
86
if (ret) {
131
ret = blk_insert_bs(s->base, base, errp);
87
goto out;
132
if (ret < 0) {
88
}
89
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
90
* grow the backing file image if possible. If not possible,
91
* we must return an error */
92
if (length > backing_length) {
93
- ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF,
94
+ ret = blk_truncate(backing, length, false, PREALLOC_MODE_OFF, 0,
95
&local_err);
96
if (ret < 0) {
97
error_report_err(local_err);
98
diff --git a/block/crypto.c b/block/crypto.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/crypto.c
101
+++ b/block/crypto.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_init_func(QCryptoBlock *block,
103
* which will be used by the crypto header
104
*/
105
return blk_truncate(data->blk, data->size + headerlen, false,
106
- data->prealloc, errp);
107
+ data->prealloc, 0, errp);
108
}
109
110
111
diff --git a/block/mirror.c b/block/mirror.c
133
diff --git a/block/mirror.c b/block/mirror.c
112
index XXXXXXX..XXXXXXX 100644
134
index XXXXXXX..XXXXXXX 100644
113
--- a/block/mirror.c
135
--- a/block/mirror.c
114
+++ b/block/mirror.c
136
+++ b/block/mirror.c
115
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
137
@@ -XXX,XX +XXX,XX @@ static void mirror_complete(Job *job, Error **errp)
116
138
replace_aio_context = bdrv_get_aio_context(s->to_replace);
117
if (s->bdev_length > base_length) {
139
aio_context_acquire(replace_aio_context);
118
ret = blk_truncate(s->target, s->bdev_length, false,
140
119
- PREALLOC_MODE_OFF, NULL);
141
- /* TODO Translate this into permission system. Current definition of
120
+ PREALLOC_MODE_OFF, 0, NULL);
142
- * GRAPH_MOD would require to request it for the parents; they might
121
if (ret < 0) {
143
- * not even be BlockDriverStates, however, so a BdrvChild can't address
122
goto immediate_exit;
144
- * them. May need redefinition of GRAPH_MOD. */
123
}
145
+ /* TODO Translate this into child freeze system. */
124
diff --git a/block/qcow2.c b/block/qcow2.c
146
error_setg(&s->replace_blocker,
125
index XXXXXXX..XXXXXXX 100644
147
"block device is in use by block-job-complete");
126
--- a/block/qcow2.c
148
bdrv_op_block_all(s->to_replace, s->replace_blocker);
127
+++ b/block/qcow2.c
149
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
128
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
150
s = block_job_create(job_id, driver, NULL, mirror_top_bs,
129
151
BLK_PERM_CONSISTENT_READ,
130
/* Okay, now that we have a valid image, let's give it the right size */
152
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
131
ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
153
- BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed,
132
- errp);
154
+ BLK_PERM_WRITE, speed,
133
+ 0, errp);
155
creation_flags, cb, opaque, errp);
134
if (ret < 0) {
156
if (!s) {
135
error_prepend(errp, "Could not resize image: ");
157
goto fail;
136
goto out;
158
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
137
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
159
target_perms |= BLK_PERM_RESIZE;
138
* Amending image options should ensure that the image has
139
* exactly the given new values, so pass exact=true here.
140
*/
141
- ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, errp);
142
+ ret = blk_truncate(blk, new_size, true, PREALLOC_MODE_OFF, 0, errp);
143
blk_unref(blk);
144
if (ret < 0) {
145
return ret;
146
diff --git a/block/qed.c b/block/qed.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/qed.c
149
+++ b/block/qed.c
150
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
151
* The QED format associates file length with allocation status,
152
* so a new file (which is empty) must have a length of 0.
153
*/
154
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, errp);
155
+ ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
156
if (ret < 0) {
157
goto out;
158
}
159
diff --git a/block/vdi.c b/block/vdi.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/vdi.c
162
+++ b/block/vdi.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
164
165
if (image_type == VDI_TYPE_STATIC) {
166
ret = blk_truncate(blk, offset + blocks * block_size, false,
167
- PREALLOC_MODE_OFF, errp);
168
+ PREALLOC_MODE_OFF, 0, errp);
169
if (ret < 0) {
170
error_prepend(errp, "Failed to statically allocate file");
171
goto exit;
172
diff --git a/block/vhdx.c b/block/vhdx.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/vhdx.c
175
+++ b/block/vhdx.c
176
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
177
/* All zeroes, so we can just extend the file - the end of the BAT
178
* is the furthest thing we have written yet */
179
ret = blk_truncate(blk, data_file_offset, false, PREALLOC_MODE_OFF,
180
- errp);
181
+ 0, errp);
182
if (ret < 0) {
183
goto exit;
184
}
160
}
185
} else if (type == VHDX_TYPE_FIXED) {
161
186
ret = blk_truncate(blk, data_file_offset + image_size, false,
162
- target_shared_perms |= BLK_PERM_CONSISTENT_READ
187
- PREALLOC_MODE_OFF, errp);
163
- | BLK_PERM_WRITE
188
+ PREALLOC_MODE_OFF, 0, errp);
164
- | BLK_PERM_GRAPH_MOD;
189
if (ret < 0) {
165
+ target_shared_perms |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE;
190
goto exit;
166
} else if (bdrv_chain_contains(bs, bdrv_skip_filters(target))) {
191
}
167
/*
192
diff --git a/block/vmdk.c b/block/vmdk.c
168
* We may want to allow this in the future, but it would
193
index XXXXXXX..XXXXXXX 100644
169
@@ -XXX,XX +XXX,XX @@ static BlockJob *mirror_start_job(
194
--- a/block/vmdk.c
170
goto fail;
195
+++ b/block/vmdk.c
171
}
196
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
172
197
int gd_buf_size;
173
- if (backing_mode != MIRROR_LEAVE_BACKING_CHAIN) {
198
174
- target_perms |= BLK_PERM_GRAPH_MOD;
199
if (flat) {
175
- }
200
- ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, errp);
176
-
201
+ ret = blk_truncate(blk, filesize, false, PREALLOC_MODE_OFF, 0, errp);
177
s->target = blk_new(s->common.job.aio_context,
202
goto exit;
178
target_perms, target_shared_perms);
203
}
179
ret = blk_insert_bs(s->target, target, errp);
204
magic = cpu_to_be32(VMDK4_MAGIC);
180
diff --git a/hw/block/block.c b/hw/block/block.c
205
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
181
index XXXXXXX..XXXXXXX 100644
206
}
182
--- a/hw/block/block.c
207
183
+++ b/hw/block/block.c
208
ret = blk_truncate(blk, le64_to_cpu(header.grain_offset) << 9, false,
184
@@ -XXX,XX +XXX,XX @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly,
209
- PREALLOC_MODE_OFF, errp);
185
perm |= BLK_PERM_WRITE;
210
+ PREALLOC_MODE_OFF, 0, errp);
186
}
211
if (ret < 0) {
187
212
goto exit;
188
- shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
213
}
189
- BLK_PERM_GRAPH_MOD;
214
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
190
+ shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED;
215
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
191
if (resizable) {
216
* for description file */
192
shared_perm |= BLK_PERM_RESIZE;
217
if (desc_offset == 0) {
193
}
218
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, errp);
194
diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py
219
+ ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
195
index XXXXXXX..XXXXXXX 100755
220
if (ret < 0) {
196
--- a/scripts/render_block_graph.py
221
goto exit;
197
+++ b/scripts/render_block_graph.py
222
}
198
@@ -XXX,XX +XXX,XX @@ def perm(arr):
223
diff --git a/block/vpc.c b/block/vpc.c
199
s = 'w' if 'write' in arr else '_'
224
index XXXXXXX..XXXXXXX 100644
200
s += 'r' if 'consistent-read' in arr else '_'
225
--- a/block/vpc.c
201
s += 'u' if 'write-unchanged' in arr else '_'
226
+++ b/block/vpc.c
202
- s += 'g' if 'graph-mod' in arr else '_'
227
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, uint8_t *buf,
203
s += 's' if 'resize' in arr else '_'
228
/* Add footer to total size */
204
return s
229
total_size += HEADER_SIZE;
205
230
206
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
231
- ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, errp);
207
index XXXXXXX..XXXXXXX 100644
232
+ ret = blk_truncate(blk, total_size, false, PREALLOC_MODE_OFF, 0, errp);
208
--- a/tests/qemu-iotests/273.out
233
if (ret < 0) {
209
+++ b/tests/qemu-iotests/273.out
234
return ret;
210
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
235
}
211
"name": "file",
236
diff --git a/blockdev.c b/blockdev.c
212
"parent": 5,
237
index XXXXXXX..XXXXXXX 100644
213
"shared-perm": [
238
--- a/blockdev.c
214
- "graph-mod",
239
+++ b/blockdev.c
215
"write-unchanged",
240
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
216
"consistent-read"
241
}
217
],
242
218
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
243
bdrv_drained_begin(bs);
219
"name": "backing",
244
- ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, errp);
220
"parent": 5,
245
+ ret = blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
221
"shared-perm": [
246
bdrv_drained_end(bs);
222
- "graph-mod",
247
223
"resize",
248
out:
224
"write-unchanged",
249
diff --git a/qemu-img.c b/qemu-img.c
225
"write",
250
index XXXXXXX..XXXXXXX 100644
226
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
251
--- a/qemu-img.c
227
"name": "file",
252
+++ b/qemu-img.c
228
"parent": 3,
253
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
229
"shared-perm": [
254
* resizing, so pass @exact=true. It is of no use to report
230
- "graph-mod",
255
* success when the image has not actually been resized.
231
"write-unchanged",
256
*/
232
"consistent-read"
257
- ret = blk_truncate(blk, total_size, true, prealloc, &err);
233
],
258
+ ret = blk_truncate(blk, total_size, true, prealloc, 0, &err);
234
@@ -XXX,XX +XXX,XX @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
259
if (!ret) {
235
"name": "backing",
260
qprintf(quiet, "Image resized.\n");
236
"parent": 3,
261
} else {
237
"shared-perm": [
262
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
238
- "graph-mod",
263
index XXXXXXX..XXXXXXX 100644
239
"resize",
264
--- a/qemu-io-cmds.c
240
"write-unchanged",
265
+++ b/qemu-io-cmds.c
241
"write",
266
@@ -XXX,XX +XXX,XX @@ static int truncate_f(BlockBackend *blk, int argc, char **argv)
267
* exact=true. It is better to err on the "emit more errors" side
268
* than to be overly permissive.
269
*/
270
- ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, &local_err);
271
+ ret = blk_truncate(blk, offset, true, PREALLOC_MODE_OFF, 0, &local_err);
272
if (ret < 0) {
273
error_report_err(local_err);
274
return ret;
275
--
242
--
276
2.25.3
243
2.31.1
277
244
278
245
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
2
3
Backing files and raw external data files are mutually exclusive.
3
A lot of Optional[] types doesn't make code beautiful.
4
The documentation of the raw external data bit (in autoclear_features)
4
test_field_width defaults to 8, but that is never used in the code.
5
already indicates that, but we should also mention it on the other
6
side.
7
5
8
Suggested-by: Eric Blake <eblake@redhat.com>
6
More over, if we want some default behavior for single call of
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
test_run(), it should just print the whole test name, not limiting or
10
Message-Id: <20200410121816.8334-1-berto@igalia.com>
8
expanding its width, so 8 is bad default.
11
Reviewed-by: Eric Blake <eblake@redhat.com>
9
10
So, just drop the default as unused for now.
11
12
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-Id: <20211210201450.101576-1-vsementsov@virtuozzo.com>
14
Reviewed-by: John Snow <jsnow@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
16
---
14
docs/interop/qcow2.txt | 3 +++
17
tests/qemu-iotests/testrunner.py | 21 ++++++++++-----------
15
1 file changed, 3 insertions(+)
18
1 file changed, 10 insertions(+), 11 deletions(-)
16
19
17
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
20
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
18
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/interop/qcow2.txt
22
--- a/tests/qemu-iotests/testrunner.py
20
+++ b/docs/interop/qcow2.txt
23
+++ b/tests/qemu-iotests/testrunner.py
21
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
24
@@ -XXX,XX +XXX,XX @@ def __enter__(self) -> 'TestRunner':
22
is stored (NB: The string is not null terminated). 0 if the
25
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
23
image doesn't have a backing file.
26
self._stack.close()
24
27
25
+ Note: backing files are incompatible with raw external data
28
- def test_print_one_line(self, test: str, starttime: str,
26
+ files (auto-clear feature bit 1).
29
+ def test_print_one_line(self, test: str,
27
+
30
+ test_field_width: int,
28
16 - 19: backing_file_size
31
+ starttime: str,
29
Length of the backing file name in bytes. Must not be
32
endtime: Optional[str] = None, status: str = '...',
30
longer than 1023 bytes. Undefined if the image doesn't have
33
lasttime: Optional[float] = None,
34
thistime: Optional[float] = None,
35
description: str = '',
36
- test_field_width: Optional[int] = None,
37
end: str = '\n') -> None:
38
""" Print short test info before/after test run """
39
test = os.path.basename(test)
40
41
- if test_field_width is None:
42
- test_field_width = 8
43
-
44
if self.makecheck and status != '...':
45
if status and status != 'pass':
46
status = f' [{status}]'
47
@@ -XXX,XX +XXX,XX @@ def do_run_test(self, test: str, mp: bool) -> TestResult:
48
casenotrun=casenotrun)
49
50
def run_test(self, test: str,
51
- test_field_width: Optional[int] = None,
52
+ test_field_width: int,
53
mp: bool = False) -> TestResult:
54
"""
55
Run one test and print short status
56
@@ -XXX,XX +XXX,XX @@ def run_test(self, test: str,
57
58
if not self.makecheck:
59
self.test_print_one_line(test=test,
60
+ test_field_width=test_field_width,
61
status = 'started' if mp else '...',
62
starttime=start,
63
lasttime=last_el,
64
- end = '\n' if mp else '\r',
65
- test_field_width=test_field_width)
66
+ end = '\n' if mp else '\r')
67
68
res = self.do_run_test(test, mp)
69
70
end = datetime.datetime.now().strftime('%H:%M:%S')
71
- self.test_print_one_line(test=test, status=res.status,
72
+ self.test_print_one_line(test=test,
73
+ test_field_width=test_field_width,
74
+ status=res.status,
75
starttime=start, endtime=end,
76
lasttime=last_el, thistime=res.elapsed,
77
- description=res.description,
78
- test_field_width=test_field_width)
79
+ description=res.description)
80
81
if res.casenotrun:
82
print(res.casenotrun)
31
--
83
--
32
2.25.3
84
2.31.1
33
85
34
86
diff view generated by jsdifflib