1
The following changes since commit a0def594286d9110a6035e02eef558cf3cf5d847:
1
The following changes since commit 30aa19446d82358a30eac3b556b4d6641e00b7c1:
2
2
3
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2017-01-30 10:23:20 +0000)
3
Merge remote-tracking branch 'remotes/cschoenebeck/tags/pull-9p-20200812' into staging (2020-08-24 16:39:53 +0100)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
https://github.com/codyprime/qemu-kvm-jtc.git tags/block-pull-request
7
https://github.com/XanClic/qemu.git tags/pull-block-2020-08-25
8
8
9
for you to fetch changes up to acf6e5f0962c4be670d4a93ede77423512521876:
9
for you to fetch changes up to c576fd97d4ca77b5a1a27728df11a61083dbfa98:
10
10
11
sheepdog: reorganize check for overlapping requests (2017-02-01 00:17:20 -0500)
11
iotests: Add tests for qcow2 images with extended L2 entries (2020-08-25 10:20:18 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches
14
Block patches:
15
- qcow2 subclusters (extended L2 entries)
16
15
----------------------------------------------------------------
17
----------------------------------------------------------------
18
Alberto Garcia (34):
19
qcow2: Make Qcow2AioTask store the full host offset
20
qcow2: Convert qcow2_get_cluster_offset() into qcow2_get_host_offset()
21
qcow2: Add calculate_l2_meta()
22
qcow2: Split cluster_needs_cow() out of count_cow_clusters()
23
qcow2: Process QCOW2_CLUSTER_ZERO_ALLOC clusters in handle_copied()
24
qcow2: Add get_l2_entry() and set_l2_entry()
25
qcow2: Document the Extended L2 Entries feature
26
qcow2: Add dummy has_subclusters() function
27
qcow2: Add subcluster-related fields to BDRVQcow2State
28
qcow2: Add offset_to_sc_index()
29
qcow2: Add offset_into_subcluster() and size_to_subclusters()
30
qcow2: Add l2_entry_size()
31
qcow2: Update get/set_l2_entry() and add get/set_l2_bitmap()
32
qcow2: Add QCow2SubclusterType and qcow2_get_subcluster_type()
33
qcow2: Add qcow2_get_subcluster_range_type()
34
qcow2: Add qcow2_cluster_is_allocated()
35
qcow2: Add cluster type parameter to qcow2_get_host_offset()
36
qcow2: Replace QCOW2_CLUSTER_* with QCOW2_SUBCLUSTER_*
37
qcow2: Handle QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC
38
qcow2: Add subcluster support to calculate_l2_meta()
39
qcow2: Add subcluster support to qcow2_get_host_offset()
40
qcow2: Add subcluster support to zero_in_l2_slice()
41
qcow2: Add subcluster support to discard_in_l2_slice()
42
qcow2: Add subcluster support to check_refcounts_l2()
43
qcow2: Update L2 bitmap in qcow2_alloc_cluster_link_l2()
44
qcow2: Clear the L2 bitmap when allocating a compressed cluster
45
qcow2: Add subcluster support to handle_alloc_space()
46
qcow2: Add subcluster support to qcow2_co_pwrite_zeroes()
47
qcow2: Add subcluster support to qcow2_measure()
48
qcow2: Add prealloc field to QCowL2Meta
49
qcow2: Add the 'extended_l2' option and the QCOW2_INCOMPAT_EXTL2 bit
50
qcow2: Allow preallocation and backing files if extended_l2 is set
51
qcow2: Assert that expand_zero_clusters_in_l1() does not support
52
subclusters
53
iotests: Add tests for qcow2 images with extended L2 entries
16
54
17
Paolo Bonzini (5):
55
docs/interop/qcow2.txt | 68 ++-
18
sheepdog: remove unused cancellation support
56
docs/qcow2-cache.txt | 19 +-
19
sheepdog: reorganize coroutine flow
57
qapi/block-core.json | 7 +
20
sheepdog: do not use BlockAIOCB
58
block/qcow2.h | 211 ++++++-
21
sheepdog: simplify inflight_aio_head management
59
include/block/block_int.h | 1 +
22
sheepdog: reorganize check for overlapping requests
60
block/qcow2-cluster.c | 906 +++++++++++++++++++++----------
23
61
block/qcow2-refcount.c | 47 +-
24
block/sheepdog.c | 289 ++++++++++++++++---------------------------------------
62
block/qcow2.c | 302 +++++++----
25
1 file changed, 84 insertions(+), 205 deletions(-)
63
block/trace-events | 2 +-
64
tests/qemu-iotests/031.out | 8 +-
65
tests/qemu-iotests/036.out | 4 +-
66
tests/qemu-iotests/049.out | 102 ++--
67
tests/qemu-iotests/060.out | 3 +-
68
tests/qemu-iotests/061 | 6 +
69
tests/qemu-iotests/061.out | 25 +-
70
tests/qemu-iotests/065 | 12 +-
71
tests/qemu-iotests/082.out | 39 +-
72
tests/qemu-iotests/085.out | 38 +-
73
tests/qemu-iotests/144.out | 4 +-
74
tests/qemu-iotests/182.out | 2 +-
75
tests/qemu-iotests/185.out | 8 +-
76
tests/qemu-iotests/198 | 2 +
77
tests/qemu-iotests/206.out | 6 +-
78
tests/qemu-iotests/242.out | 5 +
79
tests/qemu-iotests/255.out | 8 +-
80
tests/qemu-iotests/271 | 901 ++++++++++++++++++++++++++++++
81
tests/qemu-iotests/271.out | 726 +++++++++++++++++++++++++
82
tests/qemu-iotests/274.out | 49 +-
83
tests/qemu-iotests/280.out | 2 +-
84
tests/qemu-iotests/291.out | 2 +
85
tests/qemu-iotests/302.out | 1 +
86
tests/qemu-iotests/303.out | 4 +-
87
tests/qemu-iotests/common.filter | 1 +
88
tests/qemu-iotests/group | 1 +
89
34 files changed, 2952 insertions(+), 570 deletions(-)
90
create mode 100755 tests/qemu-iotests/271
91
create mode 100644 tests/qemu-iotests/271.out
26
92
27
--
93
--
28
2.9.3
94
2.26.2
29
95
30
96
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
The file_cluster_offset field of Qcow2AioTask stores a cluster-aligned
4
host offset. In practice this is not very useful because all users(*)
5
of this structure need the final host offset into the cluster, which
6
they calculate using
7
8
host_offset = file_cluster_offset + offset_into_cluster(s, offset)
9
10
There is no reason why Qcow2AioTask cannot store host_offset directly
11
and that is what this patch does.
12
13
(*) compressed clusters are the exception: in this case what
14
file_cluster_offset was storing was the full compressed cluster
15
descriptor (offset + size). This does not change with this patch
16
but it is documented now.
17
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
22
Message-Id: <07c4b15c644dcf06c9459f98846ac1c4ea96e26f.1594396418.git.berto@igalia.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
block/qcow2.c | 69 ++++++++++++++++++++++------------------------
26
block/trace-events | 2 +-
27
2 files changed, 34 insertions(+), 37 deletions(-)
28
29
diff --git a/block/qcow2.c b/block/qcow2.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2.c
32
+++ b/block/qcow2.c
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
34
35
static int coroutine_fn
36
qcow2_co_preadv_compressed(BlockDriverState *bs,
37
- uint64_t file_cluster_offset,
38
+ uint64_t cluster_descriptor,
39
uint64_t offset,
40
uint64_t bytes,
41
QEMUIOVector *qiov,
42
@@ -XXX,XX +XXX,XX @@ out:
43
44
static coroutine_fn int
45
qcow2_co_preadv_encrypted(BlockDriverState *bs,
46
- uint64_t file_cluster_offset,
47
+ uint64_t host_offset,
48
uint64_t offset,
49
uint64_t bytes,
50
QEMUIOVector *qiov,
51
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_encrypted(BlockDriverState *bs,
52
}
53
54
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
55
- ret = bdrv_co_pread(s->data_file,
56
- file_cluster_offset + offset_into_cluster(s, offset),
57
- bytes, buf, 0);
58
+ ret = bdrv_co_pread(s->data_file, host_offset, bytes, buf, 0);
59
if (ret < 0) {
60
goto fail;
61
}
62
63
- if (qcow2_co_decrypt(bs,
64
- file_cluster_offset + offset_into_cluster(s, offset),
65
- offset, buf, bytes) < 0)
66
+ if (qcow2_co_decrypt(bs, host_offset, offset, buf, bytes) < 0)
67
{
68
ret = -EIO;
69
goto fail;
70
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2AioTask {
71
72
BlockDriverState *bs;
73
QCow2ClusterType cluster_type; /* only for read */
74
- uint64_t file_cluster_offset;
75
+ uint64_t host_offset; /* or full descriptor in compressed clusters */
76
uint64_t offset;
77
uint64_t bytes;
78
QEMUIOVector *qiov;
79
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
80
AioTaskPool *pool,
81
AioTaskFunc func,
82
QCow2ClusterType cluster_type,
83
- uint64_t file_cluster_offset,
84
+ uint64_t host_offset,
85
uint64_t offset,
86
uint64_t bytes,
87
QEMUIOVector *qiov,
88
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
89
.bs = bs,
90
.cluster_type = cluster_type,
91
.qiov = qiov,
92
- .file_cluster_offset = file_cluster_offset,
93
+ .host_offset = host_offset,
94
.offset = offset,
95
.bytes = bytes,
96
.qiov_offset = qiov_offset,
97
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
98
99
trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
100
func == qcow2_co_preadv_task_entry ? "read" : "write",
101
- cluster_type, file_cluster_offset, offset, bytes,
102
+ cluster_type, host_offset, offset, bytes,
103
qiov, qiov_offset);
104
105
if (!pool) {
106
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
107
108
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
109
QCow2ClusterType cluster_type,
110
- uint64_t file_cluster_offset,
111
+ uint64_t host_offset,
112
uint64_t offset, uint64_t bytes,
113
QEMUIOVector *qiov,
114
size_t qiov_offset)
115
{
116
BDRVQcow2State *s = bs->opaque;
117
- int offset_in_cluster = offset_into_cluster(s, offset);
118
119
switch (cluster_type) {
120
case QCOW2_CLUSTER_ZERO_PLAIN:
121
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
122
qiov, qiov_offset, 0);
123
124
case QCOW2_CLUSTER_COMPRESSED:
125
- return qcow2_co_preadv_compressed(bs, file_cluster_offset,
126
+ return qcow2_co_preadv_compressed(bs, host_offset,
127
offset, bytes, qiov, qiov_offset);
128
129
case QCOW2_CLUSTER_NORMAL:
130
- assert(offset_into_cluster(s, file_cluster_offset) == 0);
131
if (bs->encrypted) {
132
- return qcow2_co_preadv_encrypted(bs, file_cluster_offset,
133
+ return qcow2_co_preadv_encrypted(bs, host_offset,
134
offset, bytes, qiov, qiov_offset);
135
}
136
137
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
138
- return bdrv_co_preadv_part(s->data_file,
139
- file_cluster_offset + offset_in_cluster,
140
+ return bdrv_co_preadv_part(s->data_file, host_offset,
141
bytes, qiov, qiov_offset, 0);
142
143
default:
144
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
145
146
assert(!t->l2meta);
147
148
- return qcow2_co_preadv_task(t->bs, t->cluster_type, t->file_cluster_offset,
149
+ return qcow2_co_preadv_task(t->bs, t->cluster_type, t->host_offset,
150
t->offset, t->bytes, t->qiov, t->qiov_offset);
151
}
152
153
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
154
{
155
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
156
} else {
157
+ /*
158
+ * For compressed clusters the variable cluster_offset
159
+ * does not actually store the offset but the full
160
+ * descriptor. We need to leave it unchanged because
161
+ * that's what qcow2_co_preadv_compressed() expects.
162
+ */
163
+ uint64_t host_offset = (ret == QCOW2_CLUSTER_COMPRESSED) ?
164
+ cluster_offset :
165
+ cluster_offset + offset_into_cluster(s, offset);
166
if (!aio && cur_bytes != bytes) {
167
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
168
}
169
ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
170
- cluster_offset, offset, cur_bytes,
171
+ host_offset, offset, cur_bytes,
172
qiov, qiov_offset, NULL);
173
if (ret < 0) {
174
goto out;
175
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
176
* not use it somehow after qcow2_co_pwritev_task() call
177
*/
178
static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
179
- uint64_t file_cluster_offset,
180
+ uint64_t host_offset,
181
uint64_t offset, uint64_t bytes,
182
QEMUIOVector *qiov,
183
uint64_t qiov_offset,
184
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
185
int ret;
186
BDRVQcow2State *s = bs->opaque;
187
void *crypt_buf = NULL;
188
- int offset_in_cluster = offset_into_cluster(s, offset);
189
QEMUIOVector encrypted_qiov;
190
191
if (bs->encrypted) {
192
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
193
}
194
qemu_iovec_to_buf(qiov, qiov_offset, crypt_buf, bytes);
195
196
- if (qcow2_co_encrypt(bs, file_cluster_offset + offset_in_cluster,
197
- offset, crypt_buf, bytes) < 0)
198
- {
199
+ if (qcow2_co_encrypt(bs, host_offset, offset, crypt_buf, bytes) < 0) {
200
ret = -EIO;
201
goto out_unlocked;
202
}
203
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_task(BlockDriverState *bs,
204
*/
205
if (!merge_cow(offset, bytes, qiov, qiov_offset, l2meta)) {
206
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
207
- trace_qcow2_writev_data(qemu_coroutine_self(),
208
- file_cluster_offset + offset_in_cluster);
209
- ret = bdrv_co_pwritev_part(s->data_file,
210
- file_cluster_offset + offset_in_cluster,
211
+ trace_qcow2_writev_data(qemu_coroutine_self(), host_offset);
212
+ ret = bdrv_co_pwritev_part(s->data_file, host_offset,
213
bytes, qiov, qiov_offset, 0);
214
if (ret < 0) {
215
goto out_unlocked;
216
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
217
218
assert(!t->cluster_type);
219
220
- return qcow2_co_pwritev_task(t->bs, t->file_cluster_offset,
221
+ return qcow2_co_pwritev_task(t->bs, t->host_offset,
222
t->offset, t->bytes, t->qiov, t->qiov_offset,
223
t->l2meta);
224
}
225
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_part(
226
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
227
}
228
ret = qcow2_add_task(bs, aio, qcow2_co_pwritev_task_entry, 0,
229
- cluster_offset, offset, cur_bytes,
230
- qiov, qiov_offset, l2meta);
231
+ cluster_offset + offset_in_cluster, offset,
232
+ cur_bytes, qiov, qiov_offset, l2meta);
233
l2meta = NULL; /* l2meta is consumed by qcow2_co_pwritev_task() */
234
if (ret < 0) {
235
goto fail_nometa;
236
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
237
238
static int coroutine_fn
239
qcow2_co_preadv_compressed(BlockDriverState *bs,
240
- uint64_t file_cluster_offset,
241
+ uint64_t cluster_descriptor,
242
uint64_t offset,
243
uint64_t bytes,
244
QEMUIOVector *qiov,
245
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
246
uint8_t *buf, *out_buf;
247
int offset_in_cluster = offset_into_cluster(s, offset);
248
249
- coffset = file_cluster_offset & s->cluster_offset_mask;
250
- nb_csectors = ((file_cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
251
+ coffset = cluster_descriptor & s->cluster_offset_mask;
252
+ nb_csectors = ((cluster_descriptor >> s->csize_shift) & s->csize_mask) + 1;
253
csize = nb_csectors * QCOW2_COMPRESSED_SECTOR_SIZE -
254
(coffset & ~QCOW2_COMPRESSED_SECTOR_MASK);
255
256
diff --git a/block/trace-events b/block/trace-events
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/trace-events
259
+++ b/block/trace-events
260
@@ -XXX,XX +XXX,XX @@ luring_io_uring_submit(void *s, int ret) "LuringState %p ret %d"
261
luring_resubmit_short_read(void *s, void *luringcb, int nread) "LuringState %p luringcb %p nread %d"
262
263
# qcow2.c
264
-qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t file_cluster_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
265
+qcow2_add_task(void *co, void *bs, void *pool, const char *action, int cluster_type, uint64_t host_offset, uint64_t offset, uint64_t bytes, void *qiov, size_t qiov_offset) "co %p bs %p pool %p: %s: cluster_type %d file_cluster_offset %" PRIu64 " offset %" PRIu64 " bytes %" PRIu64 " qiov %p qiov_offset %zu"
266
qcow2_writev_start_req(void *co, int64_t offset, int bytes) "co %p offset 0x%" PRIx64 " bytes %d"
267
qcow2_writev_done_req(void *co, int ret) "co %p ret %d"
268
qcow2_writev_start_part(void *co) "co %p"
269
--
270
2.26.2
271
272
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
qcow2_get_cluster_offset() takes an (unaligned) guest offset and
4
returns the (aligned) offset of the corresponding cluster in the qcow2
5
image.
6
7
In practice none of the callers need to know where the cluster starts
8
so this patch makes the function calculate and return the final host
9
offset directly. The function is also renamed accordingly.
10
11
There is a pre-existing exception with compressed clusters: in this
12
case the function returns the complete cluster descriptor (containing
13
the offset and size of the compressed data). This does not change with
14
this patch but it is now documented.
15
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-Id: <ffae6cdc5ca8950e8280ac0f696dcc376cb07095.1594396418.git.berto@igalia.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
21
block/qcow2.h | 4 ++--
22
block/qcow2-cluster.c | 41 +++++++++++++++++++++++------------------
23
block/qcow2.c | 24 +++++++-----------------
24
3 files changed, 32 insertions(+), 37 deletions(-)
25
26
diff --git a/block/qcow2.h b/block/qcow2.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/qcow2.h
29
+++ b/block/qcow2.h
30
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
31
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
32
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
33
34
-int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
35
- unsigned int *bytes, uint64_t *cluster_offset);
36
+int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
37
+ unsigned int *bytes, uint64_t *host_offset);
38
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
39
unsigned int *bytes, uint64_t *host_offset,
40
QCowL2Meta **m);
41
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/qcow2-cluster.c
44
+++ b/block/qcow2-cluster.c
45
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
46
47
48
/*
49
- * get_cluster_offset
50
+ * get_host_offset
51
*
52
- * For a given offset of the virtual disk, find the cluster type and offset in
53
- * the qcow2 file. The offset is stored in *cluster_offset.
54
+ * For a given offset of the virtual disk find the equivalent host
55
+ * offset in the qcow2 file and store it in *host_offset. Neither
56
+ * offset needs to be aligned to a cluster boundary.
57
+ *
58
+ * If the cluster is unallocated then *host_offset will be 0.
59
+ * If the cluster is compressed then *host_offset will contain the
60
+ * complete compressed cluster descriptor.
61
*
62
* On entry, *bytes is the maximum number of contiguous bytes starting at
63
* offset that we are interested in.
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
65
* Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error
66
* cases.
67
*/
68
-int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
69
- unsigned int *bytes, uint64_t *cluster_offset)
70
+int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
71
+ unsigned int *bytes, uint64_t *host_offset)
72
{
73
BDRVQcow2State *s = bs->opaque;
74
unsigned int l2_index;
75
- uint64_t l1_index, l2_offset, *l2_slice;
76
+ uint64_t l1_index, l2_offset, *l2_slice, l2_entry;
77
int c;
78
unsigned int offset_in_cluster;
79
uint64_t bytes_available, bytes_needed, nb_clusters;
80
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
81
bytes_needed = bytes_available;
82
}
83
84
- *cluster_offset = 0;
85
+ *host_offset = 0;
86
87
/* seek to the l2 offset in the l1 table */
88
89
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
90
/* find the cluster offset for the given disk offset */
91
92
l2_index = offset_to_l2_slice_index(s, offset);
93
- *cluster_offset = be64_to_cpu(l2_slice[l2_index]);
94
+ l2_entry = be64_to_cpu(l2_slice[l2_index]);
95
96
nb_clusters = size_to_clusters(s, bytes_needed);
97
/* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned
98
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
99
* true */
100
assert(nb_clusters <= INT_MAX);
101
102
- type = qcow2_get_cluster_type(bs, *cluster_offset);
103
+ type = qcow2_get_cluster_type(bs, l2_entry);
104
if (s->qcow_version < 3 && (type == QCOW2_CLUSTER_ZERO_PLAIN ||
105
type == QCOW2_CLUSTER_ZERO_ALLOC)) {
106
qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found"
107
@@ -XXX,XX +XXX,XX @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
108
}
109
/* Compressed clusters can only be processed one by one */
110
c = 1;
111
- *cluster_offset &= L2E_COMPRESSED_OFFSET_SIZE_MASK;
112
+ *host_offset = l2_entry & L2E_COMPRESSED_OFFSET_SIZE_MASK;
113
break;
114
case QCOW2_CLUSTER_ZERO_PLAIN:
115
case QCOW2_CLUSTER_UNALLOCATED:
116
/* how many empty clusters ? */
117
c = count_contiguous_clusters_unallocated(bs, nb_clusters,
118
&l2_slice[l2_index], type);
119
- *cluster_offset = 0;
120
break;
121
case QCOW2_CLUSTER_ZERO_ALLOC:
122
- case QCOW2_CLUSTER_NORMAL:
123
+ case QCOW2_CLUSTER_NORMAL: {
124
+ uint64_t host_cluster_offset = l2_entry & L2E_OFFSET_MASK;
125
+ *host_offset = host_cluster_offset + offset_in_cluster;
126
/* how many allocated clusters ? */
127
c = count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
128
&l2_slice[l2_index], QCOW_OFLAG_ZERO);
129
- *cluster_offset &= L2E_OFFSET_MASK;
130
- if (offset_into_cluster(s, *cluster_offset)) {
131
+ if (offset_into_cluster(s, host_cluster_offset)) {
132
qcow2_signal_corruption(bs, true, -1, -1,
133
"Cluster allocation offset %#"
134
PRIx64 " unaligned (L2 offset: %#" PRIx64
135
- ", L2 index: %#x)", *cluster_offset,
136
+ ", L2 index: %#x)", host_cluster_offset,
137
l2_offset, l2_index);
138
ret = -EIO;
139
goto fail;
140
}
141
- if (has_data_file(bs) && *cluster_offset != offset - offset_in_cluster)
142
- {
143
+ if (has_data_file(bs) && *host_offset != offset) {
144
qcow2_signal_corruption(bs, true, -1, -1,
145
"External data file host cluster offset %#"
146
PRIx64 " does not match guest cluster "
147
"offset: %#" PRIx64
148
- ", L2 index: %#x)", *cluster_offset,
149
+ ", L2 index: %#x)", host_cluster_offset,
150
offset - offset_in_cluster, l2_index);
151
ret = -EIO;
152
goto fail;
153
}
154
break;
155
+ }
156
default:
157
abort();
158
}
159
diff --git a/block/qcow2.c b/block/qcow2.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/qcow2.c
162
+++ b/block/qcow2.c
163
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
164
BlockDriverState **file)
165
{
166
BDRVQcow2State *s = bs->opaque;
167
- uint64_t cluster_offset;
168
+ uint64_t host_offset;
169
unsigned int bytes;
170
int ret, status = 0;
171
172
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
173
}
174
175
bytes = MIN(INT_MAX, count);
176
- ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
177
+ ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset);
178
qemu_co_mutex_unlock(&s->lock);
179
if (ret < 0) {
180
return ret;
181
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
182
183
if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) &&
184
!s->crypto) {
185
- *map = cluster_offset | offset_into_cluster(s, offset);
186
+ *map = host_offset;
187
*file = s->data_file->bs;
188
status |= BDRV_BLOCK_OFFSET_VALID;
189
}
190
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
191
BDRVQcow2State *s = bs->opaque;
192
int ret = 0;
193
unsigned int cur_bytes; /* number of bytes in current iteration */
194
- uint64_t cluster_offset = 0;
195
+ uint64_t host_offset = 0;
196
AioTaskPool *aio = NULL;
197
198
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
199
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
200
}
201
202
qemu_co_mutex_lock(&s->lock);
203
- ret = qcow2_get_cluster_offset(bs, offset, &cur_bytes, &cluster_offset);
204
+ ret = qcow2_get_host_offset(bs, offset, &cur_bytes, &host_offset);
205
qemu_co_mutex_unlock(&s->lock);
206
if (ret < 0) {
207
goto out;
208
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
209
{
210
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
211
} else {
212
- /*
213
- * For compressed clusters the variable cluster_offset
214
- * does not actually store the offset but the full
215
- * descriptor. We need to leave it unchanged because
216
- * that's what qcow2_co_preadv_compressed() expects.
217
- */
218
- uint64_t host_offset = (ret == QCOW2_CLUSTER_COMPRESSED) ?
219
- cluster_offset :
220
- cluster_offset + offset_into_cluster(s, offset);
221
if (!aio && cur_bytes != bytes) {
222
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
223
}
224
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
225
offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
226
bytes = s->cluster_size;
227
nr = s->cluster_size;
228
- ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
229
+ ret = qcow2_get_host_offset(bs, offset, &nr, &off);
230
if (ret != QCOW2_CLUSTER_UNALLOCATED &&
231
ret != QCOW2_CLUSTER_ZERO_PLAIN &&
232
ret != QCOW2_CLUSTER_ZERO_ALLOC) {
233
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
234
cur_bytes = MIN(bytes, INT_MAX);
235
cur_write_flags = write_flags;
236
237
- ret = qcow2_get_cluster_offset(bs, src_offset, &cur_bytes, &copy_offset);
238
+ ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes, &copy_offset);
239
if (ret < 0) {
240
goto out;
241
}
242
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
243
244
case QCOW2_CLUSTER_NORMAL:
245
child = s->data_file;
246
- copy_offset += offset_into_cluster(s, src_offset);
247
break;
248
249
default:
250
--
251
2.26.2
252
253
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
handle_alloc() creates a QCowL2Meta structure in order to update the
4
image metadata and perform the necessary copy-on-write operations.
5
6
This patch moves that code to a separate function so it can be used
7
from other places.
8
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Max Reitz <mreitz@redhat.com>
11
Message-Id: <e5bc4a648dac31972bfa7a0e554be8064be78799.1594396418.git.berto@igalia.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/qcow2-cluster.c | 77 +++++++++++++++++++++++++++++--------------
15
1 file changed, 53 insertions(+), 24 deletions(-)
16
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
20
+++ b/block/qcow2-cluster.c
21
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
22
}
23
}
24
25
+/*
26
+ * For a given write request, create a new QCowL2Meta structure, add
27
+ * it to @m and the BDRVQcow2State.cluster_allocs list.
28
+ *
29
+ * @host_cluster_offset points to the beginning of the first cluster.
30
+ *
31
+ * @guest_offset and @bytes indicate the offset and length of the
32
+ * request.
33
+ *
34
+ * If @keep_old is true it means that the clusters were already
35
+ * allocated and will be overwritten. If false then the clusters are
36
+ * new and we have to decrease the reference count of the old ones.
37
+ */
38
+static void calculate_l2_meta(BlockDriverState *bs,
39
+ uint64_t host_cluster_offset,
40
+ uint64_t guest_offset, unsigned bytes,
41
+ QCowL2Meta **m, bool keep_old)
42
+{
43
+ BDRVQcow2State *s = bs->opaque;
44
+ unsigned cow_start_from = 0;
45
+ unsigned cow_start_to = offset_into_cluster(s, guest_offset);
46
+ unsigned cow_end_from = cow_start_to + bytes;
47
+ unsigned cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
48
+ unsigned nb_clusters = size_to_clusters(s, cow_end_from);
49
+ QCowL2Meta *old_m = *m;
50
+
51
+ *m = g_malloc0(sizeof(**m));
52
+ **m = (QCowL2Meta) {
53
+ .next = old_m,
54
+
55
+ .alloc_offset = host_cluster_offset,
56
+ .offset = start_of_cluster(s, guest_offset),
57
+ .nb_clusters = nb_clusters,
58
+
59
+ .keep_old_clusters = keep_old,
60
+
61
+ .cow_start = {
62
+ .offset = cow_start_from,
63
+ .nb_bytes = cow_start_to - cow_start_from,
64
+ },
65
+ .cow_end = {
66
+ .offset = cow_end_from,
67
+ .nb_bytes = cow_end_to - cow_end_from,
68
+ },
69
+ };
70
+
71
+ qemu_co_queue_init(&(*m)->dependent_requests);
72
+ QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
73
+}
74
+
75
/*
76
* Returns the number of contiguous clusters that can be used for an allocating
77
* write, but require COW to be performed (this includes yet unallocated space,
78
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
79
uint64_t requested_bytes = *bytes + offset_into_cluster(s, guest_offset);
80
int avail_bytes = nb_clusters << s->cluster_bits;
81
int nb_bytes = MIN(requested_bytes, avail_bytes);
82
- QCowL2Meta *old_m = *m;
83
-
84
- *m = g_malloc0(sizeof(**m));
85
-
86
- **m = (QCowL2Meta) {
87
- .next = old_m,
88
-
89
- .alloc_offset = alloc_cluster_offset,
90
- .offset = start_of_cluster(s, guest_offset),
91
- .nb_clusters = nb_clusters,
92
-
93
- .keep_old_clusters = keep_old_clusters,
94
-
95
- .cow_start = {
96
- .offset = 0,
97
- .nb_bytes = offset_into_cluster(s, guest_offset),
98
- },
99
- .cow_end = {
100
- .offset = nb_bytes,
101
- .nb_bytes = avail_bytes - nb_bytes,
102
- },
103
- };
104
- qemu_co_queue_init(&(*m)->dependent_requests);
105
- QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
106
107
*host_offset = alloc_cluster_offset + offset_into_cluster(s, guest_offset);
108
*bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset));
109
assert(*bytes != 0);
110
111
+ calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes,
112
+ m, keep_old_clusters);
113
+
114
return 1;
115
116
fail:
117
--
118
2.26.2
119
120
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
We are going to need it in other places.
4
5
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <65e5d9627ca2ebe7e62deaeddf60949c33067d9d.1594396418.git.berto@igalia.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qcow2-cluster.c | 34 +++++++++++++++++++---------------
12
1 file changed, 19 insertions(+), 15 deletions(-)
13
14
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2-cluster.c
17
+++ b/block/qcow2-cluster.c
18
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
19
QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
20
}
21
22
+/* Returns true if writing to a cluster requires COW */
23
+static bool cluster_needs_cow(BlockDriverState *bs, uint64_t l2_entry)
24
+{
25
+ switch (qcow2_get_cluster_type(bs, l2_entry)) {
26
+ case QCOW2_CLUSTER_NORMAL:
27
+ if (l2_entry & QCOW_OFLAG_COPIED) {
28
+ return false;
29
+ }
30
+ case QCOW2_CLUSTER_UNALLOCATED:
31
+ case QCOW2_CLUSTER_COMPRESSED:
32
+ case QCOW2_CLUSTER_ZERO_PLAIN:
33
+ case QCOW2_CLUSTER_ZERO_ALLOC:
34
+ return true;
35
+ default:
36
+ abort();
37
+ }
38
+}
39
+
40
/*
41
* Returns the number of contiguous clusters that can be used for an allocating
42
* write, but require COW to be performed (this includes yet unallocated space,
43
@@ -XXX,XX +XXX,XX @@ static int count_cow_clusters(BlockDriverState *bs, int nb_clusters,
44
45
for (i = 0; i < nb_clusters; i++) {
46
uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
47
- QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry);
48
-
49
- switch(cluster_type) {
50
- case QCOW2_CLUSTER_NORMAL:
51
- if (l2_entry & QCOW_OFLAG_COPIED) {
52
- goto out;
53
- }
54
+ if (!cluster_needs_cow(bs, l2_entry)) {
55
break;
56
- case QCOW2_CLUSTER_UNALLOCATED:
57
- case QCOW2_CLUSTER_COMPRESSED:
58
- case QCOW2_CLUSTER_ZERO_PLAIN:
59
- case QCOW2_CLUSTER_ZERO_ALLOC:
60
- break;
61
- default:
62
- abort();
63
}
64
}
65
66
-out:
67
assert(i <= nb_clusters);
68
return i;
69
}
70
--
71
2.26.2
72
73
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
When writing to a qcow2 file there are two functions that take a
4
virtual offset and return a host offset, possibly allocating new
5
clusters if necessary:
6
7
- handle_copied() looks for normal data clusters that are already
8
allocated and have a reference count of 1. In those clusters we
9
can simply write the data and there is no need to perform any
10
copy-on-write.
11
12
- handle_alloc() looks for clusters that do need copy-on-write,
13
either because they haven't been allocated yet, because their
14
reference count is != 1 or because they are ZERO_ALLOC clusters.
15
16
The ZERO_ALLOC case is a bit special because those are clusters that
17
are already allocated and they could perfectly be dealt with in
18
handle_copied() (as long as copy-on-write is performed when required).
19
20
In fact, there is extra code specifically for them in handle_alloc()
21
that tries to reuse the existing allocation if possible and frees them
22
otherwise.
23
24
This patch changes the handling of ZERO_ALLOC clusters so the
25
semantics of these two functions are now like this:
26
27
- handle_copied() looks for clusters that are already allocated and
28
which we can overwrite (NORMAL and ZERO_ALLOC clusters with a
29
reference count of 1).
30
31
- handle_alloc() looks for clusters for which we need a new
32
allocation (all other cases).
33
34
One important difference after this change is that clusters found
35
in handle_copied() may now require copy-on-write, but this will be
36
necessary anyway once we add support for subclusters.
37
38
Signed-off-by: Alberto Garcia <berto@igalia.com>
39
Reviewed-by: Eric Blake <eblake@redhat.com>
40
Reviewed-by: Max Reitz <mreitz@redhat.com>
41
Message-Id: <eb17fc938f6be7be2e8d8ff42763d2c19241f866.1594396418.git.berto@igalia.com>
42
Signed-off-by: Max Reitz <mreitz@redhat.com>
43
---
44
block/qcow2-cluster.c | 252 +++++++++++++++++++++++-------------------
45
1 file changed, 139 insertions(+), 113 deletions(-)
46
47
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/block/qcow2-cluster.c
50
+++ b/block/qcow2-cluster.c
51
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
52
53
/*
54
* For a given write request, create a new QCowL2Meta structure, add
55
- * it to @m and the BDRVQcow2State.cluster_allocs list.
56
+ * it to @m and the BDRVQcow2State.cluster_allocs list. If the write
57
+ * request does not need copy-on-write or changes to the L2 metadata
58
+ * then this function does nothing.
59
*
60
* @host_cluster_offset points to the beginning of the first cluster.
61
*
62
* @guest_offset and @bytes indicate the offset and length of the
63
* request.
64
*
65
+ * @l2_slice contains the L2 entries of all clusters involved in this
66
+ * write request.
67
+ *
68
* If @keep_old is true it means that the clusters were already
69
* allocated and will be overwritten. If false then the clusters are
70
* new and we have to decrease the reference count of the old ones.
71
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
72
static void calculate_l2_meta(BlockDriverState *bs,
73
uint64_t host_cluster_offset,
74
uint64_t guest_offset, unsigned bytes,
75
- QCowL2Meta **m, bool keep_old)
76
+ uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
77
{
78
BDRVQcow2State *s = bs->opaque;
79
- unsigned cow_start_from = 0;
80
+ int l2_index = offset_to_l2_slice_index(s, guest_offset);
81
+ uint64_t l2_entry;
82
+ unsigned cow_start_from, cow_end_to;
83
unsigned cow_start_to = offset_into_cluster(s, guest_offset);
84
unsigned cow_end_from = cow_start_to + bytes;
85
- unsigned cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
86
unsigned nb_clusters = size_to_clusters(s, cow_end_from);
87
QCowL2Meta *old_m = *m;
88
+ QCow2ClusterType type;
89
+
90
+ assert(nb_clusters <= s->l2_slice_size - l2_index);
91
+
92
+ /* Return if there's no COW (all clusters are normal and we keep them) */
93
+ if (keep_old) {
94
+ int i;
95
+ for (i = 0; i < nb_clusters; i++) {
96
+ l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
97
+ if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
98
+ break;
99
+ }
100
+ }
101
+ if (i == nb_clusters) {
102
+ return;
103
+ }
104
+ }
105
+
106
+ /* Get the L2 entry of the first cluster */
107
+ l2_entry = be64_to_cpu(l2_slice[l2_index]);
108
+ type = qcow2_get_cluster_type(bs, l2_entry);
109
+
110
+ if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
111
+ cow_start_from = cow_start_to;
112
+ } else {
113
+ cow_start_from = 0;
114
+ }
115
+
116
+ /* Get the L2 entry of the last cluster */
117
+ l2_entry = be64_to_cpu(l2_slice[l2_index + nb_clusters - 1]);
118
+ type = qcow2_get_cluster_type(bs, l2_entry);
119
+
120
+ if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
121
+ cow_end_to = cow_end_from;
122
+ } else {
123
+ cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
124
+ }
125
126
*m = g_malloc0(sizeof(**m));
127
**m = (QCowL2Meta) {
128
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
129
QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
130
}
131
132
-/* Returns true if writing to a cluster requires COW */
133
-static bool cluster_needs_cow(BlockDriverState *bs, uint64_t l2_entry)
134
+/*
135
+ * Returns true if writing to the cluster pointed to by @l2_entry
136
+ * requires a new allocation (that is, if the cluster is unallocated
137
+ * or has refcount > 1 and therefore cannot be written in-place).
138
+ */
139
+static bool cluster_needs_new_alloc(BlockDriverState *bs, uint64_t l2_entry)
140
{
141
switch (qcow2_get_cluster_type(bs, l2_entry)) {
142
case QCOW2_CLUSTER_NORMAL:
143
+ case QCOW2_CLUSTER_ZERO_ALLOC:
144
if (l2_entry & QCOW_OFLAG_COPIED) {
145
return false;
146
}
147
case QCOW2_CLUSTER_UNALLOCATED:
148
case QCOW2_CLUSTER_COMPRESSED:
149
case QCOW2_CLUSTER_ZERO_PLAIN:
150
- case QCOW2_CLUSTER_ZERO_ALLOC:
151
return true;
152
default:
153
abort();
154
@@ -XXX,XX +XXX,XX @@ static bool cluster_needs_cow(BlockDriverState *bs, uint64_t l2_entry)
155
}
156
157
/*
158
- * Returns the number of contiguous clusters that can be used for an allocating
159
- * write, but require COW to be performed (this includes yet unallocated space,
160
- * which must copy from the backing file)
161
+ * Returns the number of contiguous clusters that can be written to
162
+ * using one single write request, starting from @l2_index.
163
+ * At most @nb_clusters are checked.
164
+ *
165
+ * If @new_alloc is true this counts clusters that are either
166
+ * unallocated, or allocated but with refcount > 1 (so they need to be
167
+ * newly allocated and COWed).
168
+ *
169
+ * If @new_alloc is false this counts clusters that are already
170
+ * allocated and can be overwritten in-place (this includes clusters
171
+ * of type QCOW2_CLUSTER_ZERO_ALLOC).
172
*/
173
-static int count_cow_clusters(BlockDriverState *bs, int nb_clusters,
174
- uint64_t *l2_slice, int l2_index)
175
+static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters,
176
+ uint64_t *l2_slice, int l2_index,
177
+ bool new_alloc)
178
{
179
+ BDRVQcow2State *s = bs->opaque;
180
+ uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index]);
181
+ uint64_t expected_offset = l2_entry & L2E_OFFSET_MASK;
182
int i;
183
184
for (i = 0; i < nb_clusters; i++) {
185
- uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
186
- if (!cluster_needs_cow(bs, l2_entry)) {
187
+ l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
188
+ if (cluster_needs_new_alloc(bs, l2_entry) != new_alloc) {
189
break;
190
}
191
+ if (!new_alloc) {
192
+ if (expected_offset != (l2_entry & L2E_OFFSET_MASK)) {
193
+ break;
194
+ }
195
+ expected_offset += s->cluster_size;
196
+ }
197
}
198
199
assert(i <= nb_clusters);
200
@@ -XXX,XX +XXX,XX @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
201
}
202
203
/*
204
- * Checks how many already allocated clusters that don't require a copy on
205
- * write there are at the given guest_offset (up to *bytes). If *host_offset is
206
- * not INV_OFFSET, only physically contiguous clusters beginning at this host
207
- * offset are counted.
208
+ * Checks how many already allocated clusters that don't require a new
209
+ * allocation there are at the given guest_offset (up to *bytes).
210
+ * If *host_offset is not INV_OFFSET, only physically contiguous clusters
211
+ * beginning at this host offset are counted.
212
*
213
* Note that guest_offset may not be cluster aligned. In this case, the
214
* returned *host_offset points to exact byte referenced by guest_offset and
215
@@ -XXX,XX +XXX,XX @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
216
* Returns:
217
* 0: if no allocated clusters are available at the given offset.
218
* *bytes is normally unchanged. It is set to 0 if the cluster
219
- * is allocated and doesn't need COW, but doesn't have the right
220
- * physical offset.
221
+ * is allocated and can be overwritten in-place but doesn't have
222
+ * the right physical offset.
223
*
224
- * 1: if allocated clusters that don't require a COW are available at
225
- * the requested offset. *bytes may have decreased and describes
226
- * the length of the area that can be written to.
227
+ * 1: if allocated clusters that can be overwritten in place are
228
+ * available at the requested offset. *bytes may have decreased
229
+ * and describes the length of the area that can be written to.
230
*
231
* -errno: in error cases
232
*/
233
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
234
{
235
BDRVQcow2State *s = bs->opaque;
236
int l2_index;
237
- uint64_t cluster_offset;
238
+ uint64_t l2_entry, cluster_offset;
239
uint64_t *l2_slice;
240
uint64_t nb_clusters;
241
unsigned int keep_clusters;
242
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
243
244
l2_index = offset_to_l2_slice_index(s, guest_offset);
245
nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
246
- assert(nb_clusters <= INT_MAX);
247
+ /* Limit total byte count to BDRV_REQUEST_MAX_BYTES */
248
+ nb_clusters = MIN(nb_clusters, BDRV_REQUEST_MAX_BYTES >> s->cluster_bits);
249
250
/* Find L2 entry for the first involved cluster */
251
ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index);
252
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
253
return ret;
254
}
255
256
- cluster_offset = be64_to_cpu(l2_slice[l2_index]);
257
-
258
- /* Check how many clusters are already allocated and don't need COW */
259
- if (qcow2_get_cluster_type(bs, cluster_offset) == QCOW2_CLUSTER_NORMAL
260
- && (cluster_offset & QCOW_OFLAG_COPIED))
261
- {
262
- /* If a specific host_offset is required, check it */
263
- bool offset_matches =
264
- (cluster_offset & L2E_OFFSET_MASK) == *host_offset;
265
-
266
- if (offset_into_cluster(s, cluster_offset & L2E_OFFSET_MASK)) {
267
- qcow2_signal_corruption(bs, true, -1, -1, "Data cluster offset "
268
- "%#llx unaligned (guest offset: %#" PRIx64
269
- ")", cluster_offset & L2E_OFFSET_MASK,
270
- guest_offset);
271
+ l2_entry = be64_to_cpu(l2_slice[l2_index]);
272
+ cluster_offset = l2_entry & L2E_OFFSET_MASK;
273
+
274
+ if (!cluster_needs_new_alloc(bs, l2_entry)) {
275
+ if (offset_into_cluster(s, cluster_offset)) {
276
+ qcow2_signal_corruption(bs, true, -1, -1, "%s cluster offset "
277
+ "%#" PRIx64 " unaligned (guest offset: %#"
278
+ PRIx64 ")", l2_entry & QCOW_OFLAG_ZERO ?
279
+ "Preallocated zero" : "Data",
280
+ cluster_offset, guest_offset);
281
ret = -EIO;
282
goto out;
283
}
284
285
- if (*host_offset != INV_OFFSET && !offset_matches) {
286
+ /* If a specific host_offset is required, check it */
287
+ if (*host_offset != INV_OFFSET && cluster_offset != *host_offset) {
288
*bytes = 0;
289
ret = 0;
290
goto out;
291
}
292
293
/* We keep all QCOW_OFLAG_COPIED clusters */
294
- keep_clusters =
295
- count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
296
- &l2_slice[l2_index],
297
- QCOW_OFLAG_COPIED | QCOW_OFLAG_ZERO);
298
+ keep_clusters = count_single_write_clusters(bs, nb_clusters, l2_slice,
299
+ l2_index, false);
300
assert(keep_clusters <= nb_clusters);
301
302
*bytes = MIN(*bytes,
303
keep_clusters * s->cluster_size
304
- offset_into_cluster(s, guest_offset));
305
+ assert(*bytes != 0);
306
+
307
+ calculate_l2_meta(bs, cluster_offset, guest_offset,
308
+ *bytes, l2_slice, m, true);
309
310
ret = 1;
311
} else {
312
@@ -XXX,XX +XXX,XX @@ out:
313
/* Only return a host offset if we actually made progress. Otherwise we
314
* would make requirements for handle_alloc() that it can't fulfill */
315
if (ret > 0) {
316
- *host_offset = (cluster_offset & L2E_OFFSET_MASK)
317
- + offset_into_cluster(s, guest_offset);
318
+ *host_offset = cluster_offset + offset_into_cluster(s, guest_offset);
319
}
320
321
return ret;
322
@@ -XXX,XX +XXX,XX @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
323
}
324
325
/*
326
- * Allocates new clusters for an area that either is yet unallocated or needs a
327
- * copy on write. If *host_offset is not INV_OFFSET, clusters are only
328
- * allocated if the new allocation can match the specified host offset.
329
+ * Allocates new clusters for an area that is either still unallocated or
330
+ * cannot be overwritten in-place. If *host_offset is not INV_OFFSET,
331
+ * clusters are only allocated if the new allocation can match the specified
332
+ * host offset.
333
*
334
* Note that guest_offset may not be cluster aligned. In this case, the
335
* returned *host_offset points to exact byte referenced by guest_offset and
336
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
337
BDRVQcow2State *s = bs->opaque;
338
int l2_index;
339
uint64_t *l2_slice;
340
- uint64_t entry;
341
uint64_t nb_clusters;
342
int ret;
343
- bool keep_old_clusters = false;
344
345
- uint64_t alloc_cluster_offset = INV_OFFSET;
346
+ uint64_t alloc_cluster_offset;
347
348
trace_qcow2_handle_alloc(qemu_coroutine_self(), guest_offset, *host_offset,
349
*bytes);
350
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
351
352
l2_index = offset_to_l2_slice_index(s, guest_offset);
353
nb_clusters = MIN(nb_clusters, s->l2_slice_size - l2_index);
354
- assert(nb_clusters <= INT_MAX);
355
-
356
- /* Limit total allocation byte count to INT_MAX */
357
- nb_clusters = MIN(nb_clusters, INT_MAX >> s->cluster_bits);
358
+ /* Limit total allocation byte count to BDRV_REQUEST_MAX_BYTES */
359
+ nb_clusters = MIN(nb_clusters, BDRV_REQUEST_MAX_BYTES >> s->cluster_bits);
360
361
/* Find L2 entry for the first involved cluster */
362
ret = get_cluster_table(bs, guest_offset, &l2_slice, &l2_index);
363
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
364
return ret;
365
}
366
367
- entry = be64_to_cpu(l2_slice[l2_index]);
368
- nb_clusters = count_cow_clusters(bs, nb_clusters, l2_slice, l2_index);
369
+ nb_clusters = count_single_write_clusters(bs, nb_clusters,
370
+ l2_slice, l2_index, true);
371
372
/* This function is only called when there were no non-COW clusters, so if
373
* we can't find any unallocated or COW clusters either, something is
374
* wrong with our code. */
375
assert(nb_clusters > 0);
376
377
- if (qcow2_get_cluster_type(bs, entry) == QCOW2_CLUSTER_ZERO_ALLOC &&
378
- (entry & QCOW_OFLAG_COPIED) &&
379
- (*host_offset == INV_OFFSET ||
380
- start_of_cluster(s, *host_offset) == (entry & L2E_OFFSET_MASK)))
381
- {
382
- int preallocated_nb_clusters;
383
-
384
- if (offset_into_cluster(s, entry & L2E_OFFSET_MASK)) {
385
- qcow2_signal_corruption(bs, true, -1, -1, "Preallocated zero "
386
- "cluster offset %#llx unaligned (guest "
387
- "offset: %#" PRIx64 ")",
388
- entry & L2E_OFFSET_MASK, guest_offset);
389
- ret = -EIO;
390
- goto fail;
391
- }
392
-
393
- /* Try to reuse preallocated zero clusters; contiguous normal clusters
394
- * would be fine, too, but count_cow_clusters() above has limited
395
- * nb_clusters already to a range of COW clusters */
396
- preallocated_nb_clusters =
397
- count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
398
- &l2_slice[l2_index], QCOW_OFLAG_COPIED);
399
- assert(preallocated_nb_clusters > 0);
400
-
401
- nb_clusters = preallocated_nb_clusters;
402
- alloc_cluster_offset = entry & L2E_OFFSET_MASK;
403
-
404
- /* We want to reuse these clusters, so qcow2_alloc_cluster_link_l2()
405
- * should not free them. */
406
- keep_old_clusters = true;
407
+ /* Allocate at a given offset in the image file */
408
+ alloc_cluster_offset = *host_offset == INV_OFFSET ? INV_OFFSET :
409
+ start_of_cluster(s, *host_offset);
410
+ ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
411
+ &nb_clusters);
412
+ if (ret < 0) {
413
+ goto out;
414
}
415
416
- qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
417
-
418
- if (alloc_cluster_offset == INV_OFFSET) {
419
- /* Allocate, if necessary at a given offset in the image file */
420
- alloc_cluster_offset = *host_offset == INV_OFFSET ? INV_OFFSET :
421
- start_of_cluster(s, *host_offset);
422
- ret = do_alloc_cluster_offset(bs, guest_offset, &alloc_cluster_offset,
423
- &nb_clusters);
424
- if (ret < 0) {
425
- goto fail;
426
- }
427
-
428
- /* Can't extend contiguous allocation */
429
- if (nb_clusters == 0) {
430
- *bytes = 0;
431
- return 0;
432
- }
433
-
434
- assert(alloc_cluster_offset != INV_OFFSET);
435
+ /* Can't extend contiguous allocation */
436
+ if (nb_clusters == 0) {
437
+ *bytes = 0;
438
+ ret = 0;
439
+ goto out;
440
}
441
442
+ assert(alloc_cluster_offset != INV_OFFSET);
443
+
444
/*
445
* Save info needed for meta data update.
446
*
447
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
448
*bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset));
449
assert(*bytes != 0);
450
451
- calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes,
452
- m, keep_old_clusters);
453
+ calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes, l2_slice,
454
+ m, false);
455
456
- return 1;
457
+ ret = 1;
458
459
-fail:
460
- if (*m && (*m)->nb_clusters > 0) {
461
+out:
462
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
463
+ if (ret < 0 && *m && (*m)->nb_clusters > 0) {
464
QLIST_REMOVE(*m, next_in_flight);
465
}
466
return ret;
467
--
468
2.26.2
469
470
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
The size of an L2 entry is 64 bits, but if we want to have subclusters
4
we need extended L2 entries. This means that we have to access L2
5
tables and slices differently depending on whether an image has
6
extended L2 entries or not.
7
8
This patch replaces all l2_slice[] accesses with calls to
9
get_l2_entry() and set_l2_entry().
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <9586363531fec125ba1386e561762d3e4224e9fc.1594396418.git.berto@igalia.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/qcow2.h | 12 ++++++++
19
block/qcow2-cluster.c | 63 ++++++++++++++++++++++--------------------
20
block/qcow2-refcount.c | 17 ++++++------
21
3 files changed, 54 insertions(+), 38 deletions(-)
22
23
diff --git a/block/qcow2.h b/block/qcow2.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block/qcow2.h
26
+++ b/block/qcow2.h
27
@@ -XXX,XX +XXX,XX @@ typedef enum QCow2MetadataOverlap {
28
29
#define INV_OFFSET (-1ULL)
30
31
+static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
32
+ int idx)
33
+{
34
+ return be64_to_cpu(l2_slice[idx]);
35
+}
36
+
37
+static inline void set_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
38
+ int idx, uint64_t entry)
39
+{
40
+ l2_slice[idx] = cpu_to_be64(entry);
41
+}
42
+
43
static inline bool has_data_file(BlockDriverState *bs)
44
{
45
BDRVQcow2State *s = bs->opaque;
46
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/qcow2-cluster.c
49
+++ b/block/qcow2-cluster.c
50
@@ -XXX,XX +XXX,XX @@ fail:
51
* cluster which may require a different handling)
52
*/
53
static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
54
- int cluster_size, uint64_t *l2_slice, uint64_t stop_flags)
55
+ int cluster_size, uint64_t *l2_slice, int l2_index, uint64_t stop_flags)
56
{
57
+ BDRVQcow2State *s = bs->opaque;
58
int i;
59
QCow2ClusterType first_cluster_type;
60
uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
61
- uint64_t first_entry = be64_to_cpu(l2_slice[0]);
62
+ uint64_t first_entry = get_l2_entry(s, l2_slice, l2_index);
63
uint64_t offset = first_entry & mask;
64
65
first_cluster_type = qcow2_get_cluster_type(bs, first_entry);
66
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
67
first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
68
69
for (i = 0; i < nb_clusters; i++) {
70
- uint64_t l2_entry = be64_to_cpu(l2_slice[i]) & mask;
71
+ uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index + i) & mask;
72
if (offset + (uint64_t) i * cluster_size != l2_entry) {
73
break;
74
}
75
@@ -XXX,XX +XXX,XX @@ static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
76
static int count_contiguous_clusters_unallocated(BlockDriverState *bs,
77
int nb_clusters,
78
uint64_t *l2_slice,
79
+ int l2_index,
80
QCow2ClusterType wanted_type)
81
{
82
+ BDRVQcow2State *s = bs->opaque;
83
int i;
84
85
assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
86
wanted_type == QCOW2_CLUSTER_UNALLOCATED);
87
for (i = 0; i < nb_clusters; i++) {
88
- uint64_t entry = be64_to_cpu(l2_slice[i]);
89
+ uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
90
QCow2ClusterType type = qcow2_get_cluster_type(bs, entry);
91
92
if (type != wanted_type) {
93
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
94
/* find the cluster offset for the given disk offset */
95
96
l2_index = offset_to_l2_slice_index(s, offset);
97
- l2_entry = be64_to_cpu(l2_slice[l2_index]);
98
+ l2_entry = get_l2_entry(s, l2_slice, l2_index);
99
100
nb_clusters = size_to_clusters(s, bytes_needed);
101
/* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned
102
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
103
case QCOW2_CLUSTER_UNALLOCATED:
104
/* how many empty clusters ? */
105
c = count_contiguous_clusters_unallocated(bs, nb_clusters,
106
- &l2_slice[l2_index], type);
107
+ l2_slice, l2_index, type);
108
break;
109
case QCOW2_CLUSTER_ZERO_ALLOC:
110
case QCOW2_CLUSTER_NORMAL: {
111
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
112
*host_offset = host_cluster_offset + offset_in_cluster;
113
/* how many allocated clusters ? */
114
c = count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
115
- &l2_slice[l2_index], QCOW_OFLAG_ZERO);
116
+ l2_slice, l2_index, QCOW_OFLAG_ZERO);
117
if (offset_into_cluster(s, host_cluster_offset)) {
118
qcow2_signal_corruption(bs, true, -1, -1,
119
"Cluster allocation offset %#"
120
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
121
122
/* Compression can't overwrite anything. Fail if the cluster was already
123
* allocated. */
124
- cluster_offset = be64_to_cpu(l2_slice[l2_index]);
125
+ cluster_offset = get_l2_entry(s, l2_slice, l2_index);
126
if (cluster_offset & L2E_OFFSET_MASK) {
127
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
128
return -EIO;
129
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
130
131
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
132
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
133
- l2_slice[l2_index] = cpu_to_be64(cluster_offset);
134
+ set_l2_entry(s, l2_slice, l2_index, cluster_offset);
135
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
136
137
*host_offset = cluster_offset & s->cluster_offset_mask;
138
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
139
* cluster the second one has to do RMW (which is done above by
140
* perform_cow()), update l2 table with its cluster pointer and free
141
* old cluster. This is what this loop does */
142
- if (l2_slice[l2_index + i] != 0) {
143
- old_cluster[j++] = l2_slice[l2_index + i];
144
+ if (get_l2_entry(s, l2_slice, l2_index + i) != 0) {
145
+ old_cluster[j++] = get_l2_entry(s, l2_slice, l2_index + i);
146
}
147
148
/* The offset must fit in the offset field of the L2 table entry */
149
assert((offset & L2E_OFFSET_MASK) == offset);
150
151
- l2_slice[l2_index + i] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
152
+ set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED);
153
}
154
155
156
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
157
*/
158
if (!m->keep_old_clusters && j != 0) {
159
for (i = 0; i < j; i++) {
160
- qcow2_free_any_clusters(bs, be64_to_cpu(old_cluster[i]), 1,
161
- QCOW2_DISCARD_NEVER);
162
+ qcow2_free_any_clusters(bs, old_cluster[i], 1, QCOW2_DISCARD_NEVER);
163
}
164
}
165
166
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
167
if (keep_old) {
168
int i;
169
for (i = 0; i < nb_clusters; i++) {
170
- l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
171
+ l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
172
if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
173
break;
174
}
175
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
176
}
177
178
/* Get the L2 entry of the first cluster */
179
- l2_entry = be64_to_cpu(l2_slice[l2_index]);
180
+ l2_entry = get_l2_entry(s, l2_slice, l2_index);
181
type = qcow2_get_cluster_type(bs, l2_entry);
182
183
if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
184
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
185
}
186
187
/* Get the L2 entry of the last cluster */
188
- l2_entry = be64_to_cpu(l2_slice[l2_index + nb_clusters - 1]);
189
+ l2_entry = get_l2_entry(s, l2_slice, l2_index + nb_clusters - 1);
190
type = qcow2_get_cluster_type(bs, l2_entry);
191
192
if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
193
@@ -XXX,XX +XXX,XX @@ static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters,
194
bool new_alloc)
195
{
196
BDRVQcow2State *s = bs->opaque;
197
- uint64_t l2_entry = be64_to_cpu(l2_slice[l2_index]);
198
+ uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index);
199
uint64_t expected_offset = l2_entry & L2E_OFFSET_MASK;
200
int i;
201
202
for (i = 0; i < nb_clusters; i++) {
203
- l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
204
+ l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
205
if (cluster_needs_new_alloc(bs, l2_entry) != new_alloc) {
206
break;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
209
return ret;
210
}
211
212
- l2_entry = be64_to_cpu(l2_slice[l2_index]);
213
+ l2_entry = get_l2_entry(s, l2_slice, l2_index);
214
cluster_offset = l2_entry & L2E_OFFSET_MASK;
215
216
if (!cluster_needs_new_alloc(bs, l2_entry)) {
217
@@ -XXX,XX +XXX,XX @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
218
for (i = 0; i < nb_clusters; i++) {
219
uint64_t old_l2_entry;
220
221
- old_l2_entry = be64_to_cpu(l2_slice[l2_index + i]);
222
+ old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
223
224
/*
225
* If full_discard is false, make sure that a discarded area reads back
226
@@ -XXX,XX +XXX,XX @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
227
/* First remove L2 entries */
228
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
229
if (!full_discard && s->qcow_version >= 3) {
230
- l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
231
+ set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
232
} else {
233
- l2_slice[l2_index + i] = cpu_to_be64(0);
234
+ set_l2_entry(s, l2_slice, l2_index + i, 0);
235
}
236
237
/* Then decrease the refcount */
238
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
239
uint64_t old_offset;
240
QCow2ClusterType cluster_type;
241
242
- old_offset = be64_to_cpu(l2_slice[l2_index + i]);
243
+ old_offset = get_l2_entry(s, l2_slice, l2_index + i);
244
245
/*
246
* Minimize L2 changes if the cluster already reads back as
247
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
248
249
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
250
if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
251
- l2_slice[l2_index + i] = cpu_to_be64(QCOW_OFLAG_ZERO);
252
+ set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
253
qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
254
} else {
255
- l2_slice[l2_index + i] |= cpu_to_be64(QCOW_OFLAG_ZERO);
256
+ uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
257
+ set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO);
258
}
259
}
260
261
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
262
}
263
264
for (j = 0; j < s->l2_slice_size; j++) {
265
- uint64_t l2_entry = be64_to_cpu(l2_slice[j]);
266
+ uint64_t l2_entry = get_l2_entry(s, l2_slice, j);
267
int64_t offset = l2_entry & L2E_OFFSET_MASK;
268
QCow2ClusterType cluster_type =
269
qcow2_get_cluster_type(bs, l2_entry);
270
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
271
if (!bs->backing) {
272
/* not backed; therefore we can simply deallocate the
273
* cluster */
274
- l2_slice[j] = 0;
275
+ set_l2_entry(s, l2_slice, j, 0);
276
l2_dirty = true;
277
continue;
278
}
279
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
280
}
281
282
if (l2_refcount == 1) {
283
- l2_slice[j] = cpu_to_be64(offset | QCOW_OFLAG_COPIED);
284
+ set_l2_entry(s, l2_slice, j, offset | QCOW_OFLAG_COPIED);
285
} else {
286
- l2_slice[j] = cpu_to_be64(offset);
287
+ set_l2_entry(s, l2_slice, j, offset);
288
}
289
l2_dirty = true;
290
}
291
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
292
index XXXXXXX..XXXXXXX 100644
293
--- a/block/qcow2-refcount.c
294
+++ b/block/qcow2-refcount.c
295
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
296
uint64_t cluster_index;
297
uint64_t offset;
298
299
- entry = be64_to_cpu(l2_slice[j]);
300
+ entry = get_l2_entry(s, l2_slice, j);
301
old_entry = entry;
302
entry &= ~QCOW_OFLAG_COPIED;
303
offset = entry & L2E_OFFSET_MASK;
304
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
305
qcow2_cache_set_dependency(bs, s->l2_table_cache,
306
s->refcount_block_cache);
307
}
308
- l2_slice[j] = cpu_to_be64(entry);
309
+ set_l2_entry(s, l2_slice, j, entry);
310
qcow2_cache_entry_mark_dirty(s->l2_table_cache,
311
l2_slice);
312
}
313
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
314
315
/* Do the actual checks */
316
for(i = 0; i < s->l2_size; i++) {
317
- l2_entry = be64_to_cpu(l2_table[i]);
318
+ l2_entry = get_l2_entry(s, l2_table, i);
319
320
switch (qcow2_get_cluster_type(bs, l2_entry)) {
321
case QCOW2_CLUSTER_COMPRESSED:
322
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
323
QCOW2_OL_INACTIVE_L2;
324
325
l2_entry = QCOW_OFLAG_ZERO;
326
- l2_table[i] = cpu_to_be64(l2_entry);
327
+ set_l2_entry(s, l2_table, i, l2_entry);
328
ret = qcow2_pre_write_overlap_check(bs, ign,
329
l2e_offset, sizeof(uint64_t), false);
330
if (ret < 0) {
331
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
332
}
333
334
for (j = 0; j < s->l2_size; j++) {
335
- uint64_t l2_entry = be64_to_cpu(l2_table[j]);
336
+ uint64_t l2_entry = get_l2_entry(s, l2_table, j);
337
uint64_t data_offset = l2_entry & L2E_OFFSET_MASK;
338
QCow2ClusterType cluster_type = qcow2_get_cluster_type(bs, l2_entry);
339
340
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
341
"l2_entry=%" PRIx64 " refcount=%" PRIu64 "\n",
342
repair ? "Repairing" : "ERROR", l2_entry, refcount);
343
if (repair) {
344
- l2_table[j] = cpu_to_be64(refcount == 1
345
- ? l2_entry | QCOW_OFLAG_COPIED
346
- : l2_entry & ~QCOW_OFLAG_COPIED);
347
+ set_l2_entry(s, l2_table, j,
348
+ refcount == 1 ?
349
+ l2_entry | QCOW_OFLAG_COPIED :
350
+ l2_entry & ~QCOW_OFLAG_COPIED);
351
l2_dirty++;
352
}
353
}
354
--
355
2.26.2
356
357
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Subcluster allocation in qcow2 is implemented by extending the
4
existing L2 table entries and adding additional information to
5
indicate the allocation status of each subcluster.
6
7
This patch documents the changes to the qcow2 format and how they
8
affect the calculation of the L2 cache size.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Message-Id: <5199f2e1c717bcaa58b48142c9062b803145ff7f.1594396418.git.berto@igalia.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
docs/interop/qcow2.txt | 68 ++++++++++++++++++++++++++++++++++++++++--
17
docs/qcow2-cache.txt | 19 +++++++++++-
18
2 files changed, 83 insertions(+), 4 deletions(-)
19
20
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
21
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/interop/qcow2.txt
23
+++ b/docs/interop/qcow2.txt
24
@@ -XXX,XX +XXX,XX @@ The first cluster of a qcow2 image contains the file header:
25
as the maximum cluster size and won't be able to open images
26
with larger cluster sizes.
27
28
+ Note: if the image has Extended L2 Entries then cluster_bits
29
+ must be at least 14 (i.e. 16384 byte clusters).
30
+
31
24 - 31: size
32
Virtual disk size in bytes.
33
34
@@ -XXX,XX +XXX,XX @@ the next fields through header_length.
35
clusters. The compression_type field must be
36
present and not zero.
37
38
- Bits 4-63: Reserved (set to 0)
39
+ Bit 4: Extended L2 Entries. If this bit is set then
40
+ L2 table entries use an extended format that
41
+ allows subcluster-based allocation. See the
42
+ Extended L2 Entries section for more details.
43
+
44
+ Bits 5-63: Reserved (set to 0)
45
46
80 - 87: compatible_features
47
Bitmask of compatible features. An implementation can
48
@@ -XXX,XX +XXX,XX @@ cannot be relaxed without an incompatible layout change).
49
Given an offset into the virtual disk, the offset into the image file can be
50
obtained as follows:
51
52
- l2_entries = (cluster_size / sizeof(uint64_t))
53
+ l2_entries = (cluster_size / sizeof(uint64_t)) [*]
54
55
l2_index = (offset / cluster_size) % l2_entries
56
l1_index = (offset / cluster_size) / l2_entries
57
@@ -XXX,XX +XXX,XX @@ obtained as follows:
58
59
return cluster_offset + (offset % cluster_size)
60
61
+ [*] this changes if Extended L2 Entries are enabled, see next section
62
+
63
L1 table entry:
64
65
Bit 0 - 8: Reserved (set to 0)
66
@@ -XXX,XX +XXX,XX @@ Standard Cluster Descriptor:
67
nor is data read from the backing file if the cluster is
68
unallocated.
69
70
- With version 2, this is always 0.
71
+ With version 2 or with extended L2 entries (see the next
72
+ section), this is always 0.
73
74
1 - 8: Reserved (set to 0)
75
76
@@ -XXX,XX +XXX,XX @@ file (except if bit 0 in the Standard Cluster Descriptor is set). If there is
77
no backing file or the backing file is smaller than the image, they shall read
78
zeros for all parts that are not covered by the backing file.
79
80
+== Extended L2 Entries ==
81
+
82
+An image uses Extended L2 Entries if bit 4 is set on the incompatible_features
83
+field of the header.
84
+
85
+In these images standard data clusters are divided into 32 subclusters of the
86
+same size. They are contiguous and start from the beginning of the cluster.
87
+Subclusters can be allocated independently and the L2 entry contains information
88
+indicating the status of each one of them. Compressed data clusters don't have
89
+subclusters so they are treated the same as in images without this feature.
90
+
91
+The size of an extended L2 entry is 128 bits so the number of entries per table
92
+is calculated using this formula:
93
+
94
+ l2_entries = (cluster_size / (2 * sizeof(uint64_t)))
95
+
96
+The first 64 bits have the same format as the standard L2 table entry described
97
+in the previous section, with the exception of bit 0 of the standard cluster
98
+descriptor.
99
+
100
+The last 64 bits contain a subcluster allocation bitmap with this format:
101
+
102
+Subcluster Allocation Bitmap (for standard clusters):
103
+
104
+ Bit 0 - 31: Allocation status (one bit per subcluster)
105
+
106
+ 1: the subcluster is allocated. In this case the
107
+ host cluster offset field must contain a valid
108
+ offset.
109
+ 0: the subcluster is not allocated. In this case
110
+ read requests shall go to the backing file or
111
+ return zeros if there is no backing file data.
112
+
113
+ Bits are assigned starting from the least significant
114
+ one (i.e. bit x is used for subcluster x).
115
+
116
+ 32 - 63 Subcluster reads as zeros (one bit per subcluster)
117
+
118
+ 1: the subcluster reads as zeros. In this case the
119
+ allocation status bit must be unset. The host
120
+ cluster offset field may or may not be set.
121
+ 0: no effect.
122
+
123
+ Bits are assigned starting from the least significant
124
+ one (i.e. bit x is used for subcluster x - 32).
125
+
126
+Subcluster Allocation Bitmap (for compressed clusters):
127
+
128
+ Bit 0 - 63: Reserved (set to 0)
129
+ Compressed clusters don't have subclusters,
130
+ so this field is not used.
131
132
== Snapshots ==
133
134
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
135
index XXXXXXX..XXXXXXX 100644
136
--- a/docs/qcow2-cache.txt
137
+++ b/docs/qcow2-cache.txt
138
@@ -XXX,XX +XXX,XX @@
139
qcow2 L2/refcount cache configuration
140
=====================================
141
-Copyright (C) 2015, 2018 Igalia, S.L.
142
+Copyright (C) 2015, 2018-2020 Igalia, S.L.
143
Author: Alberto Garcia <berto@igalia.com>
144
145
This work is licensed under the terms of the GNU GPL, version 2 or
146
@@ -XXX,XX +XXX,XX @@ support this functionality, and is 0 (disabled) on other platforms.
147
This functionality currently relies on the MADV_DONTNEED argument for
148
madvise() to actually free the memory. This is a Linux-specific feature,
149
so cache-clean-interval is not supported on other systems.
150
+
151
+
152
+Extended L2 Entries
153
+-------------------
154
+All numbers shown in this document are valid for qcow2 images with normal
155
+64-bit L2 entries.
156
+
157
+Images with extended L2 entries need twice as much L2 metadata, so the L2
158
+cache size must be twice as large for the same disk space.
159
+
160
+ disk_size = l2_cache_size * cluster_size / 16
161
+
162
+i.e.
163
+
164
+ l2_cache_size = disk_size * 16 / cluster_size
165
+
166
+Refcount blocks are not affected by this.
167
--
168
2.26.2
169
170
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This function will be used by the qcow2 code to check if an image has
4
subclusters or not.
5
6
At the moment this simply returns false. Once all patches needed for
7
subcluster support are ready then QEMU will be able to create and
8
read images with subclusters and this function will return the actual
9
value.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <905526221083581a1b7057bca1585487661c5c13.1594396418.git.berto@igalia.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/qcow2.h | 6 ++++++
19
1 file changed, 6 insertions(+)
20
21
diff --git a/block/qcow2.h b/block/qcow2.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2.h
24
+++ b/block/qcow2.h
25
@@ -XXX,XX +XXX,XX @@ typedef enum QCow2MetadataOverlap {
26
27
#define INV_OFFSET (-1ULL)
28
29
+static inline bool has_subclusters(BDRVQcow2State *s)
30
+{
31
+ /* FIXME: Return false until this feature is complete */
32
+ return false;
33
+}
34
+
35
static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
36
int idx)
37
{
38
--
39
2.26.2
40
41
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This patch adds the following new fields to BDRVQcow2State:
4
5
- subclusters_per_cluster: Number of subclusters in a cluster
6
- subcluster_size: The size of each subcluster, in bytes
7
- subcluster_bits: No. of bits so 1 << subcluster_bits = subcluster_size
8
9
Images without subclusters are treated as if they had exactly one
10
subcluster per cluster (i.e. subcluster_size = cluster_size).
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
15
Message-Id: <55bfeac86b092fa2c9d182a95cbeb479ff7eca4f.1594396418.git.berto@igalia.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/qcow2.h | 5 +++++
19
block/qcow2.c | 5 +++++
20
2 files changed, 10 insertions(+)
21
22
diff --git a/block/qcow2.h b/block/qcow2.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2.h
25
+++ b/block/qcow2.h
26
@@ -XXX,XX +XXX,XX @@
27
/* The cluster reads as all zeros */
28
#define QCOW_OFLAG_ZERO (1ULL << 0)
29
30
+#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
31
+
32
#define MIN_CLUSTER_BITS 9
33
#define MAX_CLUSTER_BITS 21
34
35
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
36
int cluster_bits;
37
int cluster_size;
38
int l2_slice_size;
39
+ int subcluster_bits;
40
+ int subcluster_size;
41
+ int subclusters_per_cluster;
42
int l2_bits;
43
int l2_size;
44
int l1_size;
45
diff --git a/block/qcow2.c b/block/qcow2.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/block/qcow2.c
48
+++ b/block/qcow2.c
49
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
50
}
51
}
52
53
+ s->subclusters_per_cluster =
54
+ has_subclusters(s) ? QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER : 1;
55
+ s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
56
+ s->subcluster_bits = ctz32(s->subcluster_size);
57
+
58
/* Check support for various header values */
59
if (header.refcount_order > 6) {
60
error_setg(errp, "Reference count entry width too large; may not "
61
--
62
2.26.2
63
64
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
For a given offset, return the subcluster number within its cluster
4
(i.e. with 32 subclusters per cluster it returns a number between 0
5
and 31).
6
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Message-Id: <56e3e4ac0d827c6a2f5f259106c5ddb7c4ca2653.1594396418.git.berto@igalia.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
12
---
13
block/qcow2.h | 5 +++++
14
1 file changed, 5 insertions(+)
15
16
diff --git a/block/qcow2.h b/block/qcow2.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.h
19
+++ b/block/qcow2.h
20
@@ -XXX,XX +XXX,XX @@ static inline int offset_to_l2_slice_index(BDRVQcow2State *s, int64_t offset)
21
return (offset >> s->cluster_bits) & (s->l2_slice_size - 1);
22
}
23
24
+static inline int offset_to_sc_index(BDRVQcow2State *s, int64_t offset)
25
+{
26
+ return (offset >> s->subcluster_bits) & (s->subclusters_per_cluster - 1);
27
+}
28
+
29
static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
30
{
31
return (int64_t)s->l1_vm_state_index << (s->cluster_bits + s->l2_bits);
32
--
33
2.26.2
34
35
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Like offset_into_cluster() and size_to_clusters(), but for
4
subclusters.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <3cc2390dcdef3d234d47c741b708bd8734490862.1594396418.git.berto@igalia.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
block/qcow2.h | 10 ++++++++++
13
1 file changed, 10 insertions(+)
14
15
diff --git a/block/qcow2.h b/block/qcow2.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/qcow2.h
18
+++ b/block/qcow2.h
19
@@ -XXX,XX +XXX,XX @@ static inline int64_t offset_into_cluster(BDRVQcow2State *s, int64_t offset)
20
return offset & (s->cluster_size - 1);
21
}
22
23
+static inline int64_t offset_into_subcluster(BDRVQcow2State *s, int64_t offset)
24
+{
25
+ return offset & (s->subcluster_size - 1);
26
+}
27
+
28
static inline uint64_t size_to_clusters(BDRVQcow2State *s, uint64_t size)
29
{
30
return (size + (s->cluster_size - 1)) >> s->cluster_bits;
31
}
32
33
+static inline uint64_t size_to_subclusters(BDRVQcow2State *s, uint64_t size)
34
+{
35
+ return (size + (s->subcluster_size - 1)) >> s->subcluster_bits;
36
+}
37
+
38
static inline int64_t size_to_l1(BDRVQcow2State *s, int64_t size)
39
{
40
int shift = s->cluster_bits + s->l2_bits;
41
--
42
2.26.2
43
44
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
qcow2 images with subclusters have 128-bit L2 entries. The first 64
4
bits contain the same information as traditional images and the last
5
64 bits form a bitmap with the status of each individual subcluster.
6
7
Because of that we cannot assume that L2 entries are sizeof(uint64_t)
8
anymore. This function returns the proper value for the image.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <d34d578bd0380e739e2dde3e8dd6187d3d249fa9.1594396418.git.berto@igalia.com>
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
---
15
block/qcow2.h | 9 +++++++++
16
block/qcow2-cluster.c | 12 ++++++------
17
block/qcow2-refcount.c | 14 ++++++++------
18
block/qcow2.c | 8 ++++----
19
4 files changed, 27 insertions(+), 16 deletions(-)
20
21
diff --git a/block/qcow2.h b/block/qcow2.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2.h
24
+++ b/block/qcow2.h
25
@@ -XXX,XX +XXX,XX @@
26
27
#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
28
29
+/* Size of normal and extended L2 entries */
30
+#define L2E_SIZE_NORMAL (sizeof(uint64_t))
31
+#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2)
32
+
33
#define MIN_CLUSTER_BITS 9
34
#define MAX_CLUSTER_BITS 21
35
36
@@ -XXX,XX +XXX,XX @@ static inline bool has_subclusters(BDRVQcow2State *s)
37
return false;
38
}
39
40
+static inline size_t l2_entry_size(BDRVQcow2State *s)
41
+{
42
+ return has_subclusters(s) ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
43
+}
44
+
45
static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
46
int idx)
47
{
48
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/qcow2-cluster.c
51
+++ b/block/qcow2-cluster.c
52
@@ -XXX,XX +XXX,XX @@ static int l2_load(BlockDriverState *bs, uint64_t offset,
53
uint64_t l2_offset, uint64_t **l2_slice)
54
{
55
BDRVQcow2State *s = bs->opaque;
56
- int start_of_slice = sizeof(uint64_t) *
57
+ int start_of_slice = l2_entry_size(s) *
58
(offset_to_l2_index(s, offset) - offset_to_l2_slice_index(s, offset));
59
60
return qcow2_cache_get(bs, s->l2_table_cache, l2_offset + start_of_slice,
61
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
62
63
/* allocate a new l2 entry */
64
65
- l2_offset = qcow2_alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
66
+ l2_offset = qcow2_alloc_clusters(bs, s->l2_size * l2_entry_size(s));
67
if (l2_offset < 0) {
68
ret = l2_offset;
69
goto fail;
70
@@ -XXX,XX +XXX,XX @@ static int l2_allocate(BlockDriverState *bs, int l1_index)
71
72
/* allocate a new entry in the l2 cache */
73
74
- slice_size2 = s->l2_slice_size * sizeof(uint64_t);
75
+ slice_size2 = s->l2_slice_size * l2_entry_size(s);
76
n_slices = s->cluster_size / slice_size2;
77
78
trace_qcow2_l2_allocate_get_empty(bs, l1_index);
79
@@ -XXX,XX +XXX,XX @@ fail:
80
}
81
s->l1_table[l1_index] = old_l2_offset;
82
if (l2_offset > 0) {
83
- qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
84
+ qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
85
QCOW2_DISCARD_ALWAYS);
86
}
87
return ret;
88
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
89
90
/* Then decrease the refcount of the old table */
91
if (l2_offset) {
92
- qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t),
93
+ qcow2_free_clusters(bs, l2_offset, s->l2_size * l2_entry_size(s),
94
QCOW2_DISCARD_OTHER);
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
98
int ret;
99
int i, j;
100
101
- slice_size2 = s->l2_slice_size * sizeof(uint64_t);
102
+ slice_size2 = s->l2_slice_size * l2_entry_size(s);
103
n_slices = s->cluster_size / slice_size2;
104
105
if (!is_active_l1) {
106
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/qcow2-refcount.c
109
+++ b/block/qcow2-refcount.c
110
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
111
l2_slice = NULL;
112
l1_table = NULL;
113
l1_size2 = l1_size * sizeof(uint64_t);
114
- slice_size2 = s->l2_slice_size * sizeof(uint64_t);
115
+ slice_size2 = s->l2_slice_size * l2_entry_size(s);
116
n_slices = s->cluster_size / slice_size2;
117
118
s->cache_discards = true;
119
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
120
int i, l2_size, nb_csectors, ret;
121
122
/* Read L2 table from disk */
123
- l2_size = s->l2_size * sizeof(uint64_t);
124
+ l2_size = s->l2_size * l2_entry_size(s);
125
l2_table = g_malloc(l2_size);
126
127
ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size);
128
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
129
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
130
offset);
131
if (fix & BDRV_FIX_ERRORS) {
132
+ int idx = i * (l2_entry_size(s) / sizeof(uint64_t));
133
uint64_t l2e_offset =
134
- l2_offset + (uint64_t)i * sizeof(uint64_t);
135
+ l2_offset + (uint64_t)i * l2_entry_size(s);
136
int ign = active ? QCOW2_OL_ACTIVE_L2 :
137
QCOW2_OL_INACTIVE_L2;
138
139
l2_entry = QCOW_OFLAG_ZERO;
140
set_l2_entry(s, l2_table, i, l2_entry);
141
ret = qcow2_pre_write_overlap_check(bs, ign,
142
- l2e_offset, sizeof(uint64_t), false);
143
+ l2e_offset, l2_entry_size(s), false);
144
if (ret < 0) {
145
fprintf(stderr, "ERROR: Overlap check failed\n");
146
res->check_errors++;
147
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
148
}
149
150
ret = bdrv_pwrite_sync(bs->file, l2e_offset,
151
- &l2_table[i], sizeof(uint64_t));
152
+ &l2_table[idx],
153
+ l2_entry_size(s));
154
if (ret < 0) {
155
fprintf(stderr, "ERROR: Failed to overwrite L2 "
156
"table entry: %s\n", strerror(-ret));
157
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
158
}
159
160
ret = bdrv_pread(bs->file, l2_offset, l2_table,
161
- s->l2_size * sizeof(uint64_t));
162
+ s->l2_size * l2_entry_size(s));
163
if (ret < 0) {
164
fprintf(stderr, "ERROR: Could not read L2 table: %s\n",
165
strerror(-ret));
166
diff --git a/block/qcow2.c b/block/qcow2.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
171
uint64_t max_l2_entries = DIV_ROUND_UP(virtual_disk_size, s->cluster_size);
172
/* An L2 table is always one cluster in size so the max cache size
173
* should be a multiple of the cluster size. */
174
- uint64_t max_l2_cache = ROUND_UP(max_l2_entries * sizeof(uint64_t),
175
+ uint64_t max_l2_cache = ROUND_UP(max_l2_entries * l2_entry_size(s),
176
s->cluster_size);
177
178
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
179
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
180
}
181
}
182
183
- r->l2_slice_size = l2_cache_entry_size / sizeof(uint64_t);
184
+ r->l2_slice_size = l2_cache_entry_size / l2_entry_size(s);
185
r->l2_table_cache = qcow2_cache_create(bs, l2_cache_size,
186
l2_cache_entry_size);
187
r->refcount_block_cache = qcow2_cache_create(bs, refcount_cache_size,
188
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
189
bs->encrypted = true;
190
}
191
192
- s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
193
+ s->l2_bits = s->cluster_bits - ctz32(l2_entry_size(s));
194
s->l2_size = 1 << s->l2_bits;
195
/* 2^(s->refcount_order - 3) is the refcount width in bytes */
196
s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3);
197
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
198
* preallocation. All that matters is that we will not have to allocate
199
* new refcount structures for them.) */
200
nb_new_l2_tables = DIV_ROUND_UP(nb_new_data_clusters,
201
- s->cluster_size / sizeof(uint64_t));
202
+ s->cluster_size / l2_entry_size(s));
203
/* The cluster range may not be aligned to L2 boundaries, so add one L2
204
* table for a potential head/tail */
205
nb_new_l2_tables++;
206
--
207
2.26.2
208
209
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Extended L2 entries are 128-bit wide: 64 bits for the entry itself and
4
64 bits for the subcluster allocation bitmap.
5
6
In order to support them correctly get/set_l2_entry() need to be
7
updated so they take the entry width into account in order to
8
calculate the correct offset.
9
10
This patch also adds the get/set_l2_bitmap() functions that are
11
used to access the bitmaps. For convenience we allow calling
12
get_l2_bitmap() on images without subclusters. In this case the
13
returned value is always 0 and has no meaning.
14
15
Signed-off-by: Alberto Garcia <berto@igalia.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-Id: <6ee0f81ae3329c991de125618b3675e1e46acdbb.1594396418.git.berto@igalia.com>
19
Signed-off-by: Max Reitz <mreitz@redhat.com>
20
---
21
block/qcow2.h | 21 +++++++++++++++++++++
22
1 file changed, 21 insertions(+)
23
24
diff --git a/block/qcow2.h b/block/qcow2.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.h
27
+++ b/block/qcow2.h
28
@@ -XXX,XX +XXX,XX @@ static inline size_t l2_entry_size(BDRVQcow2State *s)
29
static inline uint64_t get_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
30
int idx)
31
{
32
+ idx *= l2_entry_size(s) / sizeof(uint64_t);
33
return be64_to_cpu(l2_slice[idx]);
34
}
35
36
+static inline uint64_t get_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
37
+ int idx)
38
+{
39
+ if (has_subclusters(s)) {
40
+ idx *= l2_entry_size(s) / sizeof(uint64_t);
41
+ return be64_to_cpu(l2_slice[idx + 1]);
42
+ } else {
43
+ return 0; /* For convenience only; this value has no meaning. */
44
+ }
45
+}
46
+
47
static inline void set_l2_entry(BDRVQcow2State *s, uint64_t *l2_slice,
48
int idx, uint64_t entry)
49
{
50
+ idx *= l2_entry_size(s) / sizeof(uint64_t);
51
l2_slice[idx] = cpu_to_be64(entry);
52
}
53
54
+static inline void set_l2_bitmap(BDRVQcow2State *s, uint64_t *l2_slice,
55
+ int idx, uint64_t bitmap)
56
+{
57
+ assert(has_subclusters(s));
58
+ idx *= l2_entry_size(s) / sizeof(uint64_t);
59
+ l2_slice[idx + 1] = cpu_to_be64(bitmap);
60
+}
61
+
62
static inline bool has_data_file(BlockDriverState *bs)
63
{
64
BDRVQcow2State *s = bs->opaque;
65
--
66
2.26.2
67
68
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
This patch adds QCow2SubclusterType, which is the subcluster-level
4
version of QCow2ClusterType. All QCOW2_SUBCLUSTER_* values have the
5
the same meaning as their QCOW2_CLUSTER_* equivalents (when they
6
exist). See below for details and caveats.
7
8
In images without extended L2 entries clusters are treated as having
9
exactly one subcluster so it is possible to replace one data type with
10
the other while keeping the exact same semantics.
11
12
With extended L2 entries there are new possible values, and every
13
subcluster in the same cluster can obviously have a different
14
QCow2SubclusterType so functions need to be adapted to work on the
15
subcluster level.
16
17
There are several things that have to be taken into account:
18
19
a) QCOW2_SUBCLUSTER_COMPRESSED means that the whole cluster is
20
compressed. We do not support compression at the subcluster
21
level.
22
23
b) There are two different values for unallocated subclusters:
24
QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN which means that the whole
25
cluster is unallocated, and QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC
26
which means that the cluster is allocated but the subcluster is
27
not. The latter can only happen in images with extended L2
28
entries.
29
30
c) QCOW2_SUBCLUSTER_INVALID is used to detect the cases where an L2
31
entry has a value that violates the specification. The caller is
32
responsible for handling these situations.
33
34
To prevent compatibility problems with images that have invalid
35
values but are currently being read by QEMU without causing side
36
effects, QCOW2_SUBCLUSTER_INVALID is only returned for images
37
with extended L2 entries.
38
39
qcow2_cluster_to_subcluster_type() is added as a separate function
40
from qcow2_get_subcluster_type(), but this is only temporary and both
41
will be merged in a subsequent patch.
42
43
Signed-off-by: Alberto Garcia <berto@igalia.com>
44
Reviewed-by: Eric Blake <eblake@redhat.com>
45
Reviewed-by: Max Reitz <mreitz@redhat.com>
46
Message-Id: <26ef38e270f25851c98b51278852b4c4a7f97e69.1594396418.git.berto@igalia.com>
47
Signed-off-by: Max Reitz <mreitz@redhat.com>
48
---
49
block/qcow2.h | 126 +++++++++++++++++++++++++++++++++++++++++++++++++-
50
1 file changed, 125 insertions(+), 1 deletion(-)
51
52
diff --git a/block/qcow2.h b/block/qcow2.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/qcow2.h
55
+++ b/block/qcow2.h
56
@@ -XXX,XX +XXX,XX @@
57
58
#define QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER 32
59
60
+/* The subcluster X [0..31] is allocated */
61
+#define QCOW_OFLAG_SUB_ALLOC(X) (1ULL << (X))
62
+/* The subcluster X [0..31] reads as zeroes */
63
+#define QCOW_OFLAG_SUB_ZERO(X) (QCOW_OFLAG_SUB_ALLOC(X) << 32)
64
+/* Subclusters [X, Y) (0 <= X <= Y <= 32) are allocated */
65
+#define QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) \
66
+ (QCOW_OFLAG_SUB_ALLOC(Y) - QCOW_OFLAG_SUB_ALLOC(X))
67
+/* Subclusters [X, Y) (0 <= X <= Y <= 32) read as zeroes */
68
+#define QCOW_OFLAG_SUB_ZERO_RANGE(X, Y) \
69
+ (QCOW_OFLAG_SUB_ALLOC_RANGE(X, Y) << 32)
70
+/* L2 entry bitmap with all allocation bits set */
71
+#define QCOW_L2_BITMAP_ALL_ALLOC (QCOW_OFLAG_SUB_ALLOC_RANGE(0, 32))
72
+/* L2 entry bitmap with all "read as zeroes" bits set */
73
+#define QCOW_L2_BITMAP_ALL_ZEROES (QCOW_OFLAG_SUB_ZERO_RANGE(0, 32))
74
+
75
/* Size of normal and extended L2 entries */
76
#define L2E_SIZE_NORMAL (sizeof(uint64_t))
77
#define L2E_SIZE_EXTENDED (sizeof(uint64_t) * 2)
78
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
79
QLIST_ENTRY(QCowL2Meta) next_in_flight;
80
} QCowL2Meta;
81
82
+/*
83
+ * In images with standard L2 entries all clusters are treated as if
84
+ * they had one subcluster so QCow2ClusterType and QCow2SubclusterType
85
+ * can be mapped to each other and have the exact same meaning
86
+ * (QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC cannot happen in these images).
87
+ *
88
+ * In images with extended L2 entries QCow2ClusterType refers to the
89
+ * complete cluster and QCow2SubclusterType to each of the individual
90
+ * subclusters, so there are several possible combinations:
91
+ *
92
+ * |--------------+---------------------------|
93
+ * | Cluster type | Possible subcluster types |
94
+ * |--------------+---------------------------|
95
+ * | UNALLOCATED | UNALLOCATED_PLAIN |
96
+ * | | ZERO_PLAIN |
97
+ * |--------------+---------------------------|
98
+ * | NORMAL | UNALLOCATED_ALLOC |
99
+ * | | ZERO_ALLOC |
100
+ * | | NORMAL |
101
+ * |--------------+---------------------------|
102
+ * | COMPRESSED | COMPRESSED |
103
+ * |--------------+---------------------------|
104
+ *
105
+ * QCOW2_SUBCLUSTER_INVALID means that the L2 entry is incorrect and
106
+ * the image should be marked corrupt.
107
+ */
108
+
109
typedef enum QCow2ClusterType {
110
QCOW2_CLUSTER_UNALLOCATED,
111
QCOW2_CLUSTER_ZERO_PLAIN,
112
@@ -XXX,XX +XXX,XX @@ typedef enum QCow2ClusterType {
113
QCOW2_CLUSTER_COMPRESSED,
114
} QCow2ClusterType;
115
116
+typedef enum QCow2SubclusterType {
117
+ QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN,
118
+ QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC,
119
+ QCOW2_SUBCLUSTER_ZERO_PLAIN,
120
+ QCOW2_SUBCLUSTER_ZERO_ALLOC,
121
+ QCOW2_SUBCLUSTER_NORMAL,
122
+ QCOW2_SUBCLUSTER_COMPRESSED,
123
+ QCOW2_SUBCLUSTER_INVALID,
124
+} QCow2SubclusterType;
125
+
126
typedef enum QCow2MetadataOverlap {
127
QCOW2_OL_MAIN_HEADER_BITNR = 0,
128
QCOW2_OL_ACTIVE_L1_BITNR = 1,
129
@@ -XXX,XX +XXX,XX @@ static inline int64_t qcow2_vm_state_offset(BDRVQcow2State *s)
130
static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs,
131
uint64_t l2_entry)
132
{
133
+ BDRVQcow2State *s = bs->opaque;
134
+
135
if (l2_entry & QCOW_OFLAG_COMPRESSED) {
136
return QCOW2_CLUSTER_COMPRESSED;
137
- } else if (l2_entry & QCOW_OFLAG_ZERO) {
138
+ } else if ((l2_entry & QCOW_OFLAG_ZERO) && !has_subclusters(s)) {
139
if (l2_entry & L2E_OFFSET_MASK) {
140
return QCOW2_CLUSTER_ZERO_ALLOC;
141
}
142
@@ -XXX,XX +XXX,XX @@ static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs,
143
}
144
}
145
146
+/*
147
+ * For an image without extended L2 entries, return the
148
+ * QCow2SubclusterType equivalent of a given QCow2ClusterType.
149
+ */
150
+static inline
151
+QCow2SubclusterType qcow2_cluster_to_subcluster_type(QCow2ClusterType type)
152
+{
153
+ switch (type) {
154
+ case QCOW2_CLUSTER_COMPRESSED:
155
+ return QCOW2_SUBCLUSTER_COMPRESSED;
156
+ case QCOW2_CLUSTER_ZERO_PLAIN:
157
+ return QCOW2_SUBCLUSTER_ZERO_PLAIN;
158
+ case QCOW2_CLUSTER_ZERO_ALLOC:
159
+ return QCOW2_SUBCLUSTER_ZERO_ALLOC;
160
+ case QCOW2_CLUSTER_NORMAL:
161
+ return QCOW2_SUBCLUSTER_NORMAL;
162
+ case QCOW2_CLUSTER_UNALLOCATED:
163
+ return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
164
+ default:
165
+ g_assert_not_reached();
166
+ }
167
+}
168
+
169
+/*
170
+ * In an image without subsclusters @l2_bitmap is ignored and
171
+ * @sc_index must be 0.
172
+ * Return QCOW2_SUBCLUSTER_INVALID if an invalid l2 entry is detected
173
+ * (this checks the whole entry and bitmap, not only the bits related
174
+ * to subcluster @sc_index).
175
+ */
176
+static inline
177
+QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs,
178
+ uint64_t l2_entry,
179
+ uint64_t l2_bitmap,
180
+ unsigned sc_index)
181
+{
182
+ BDRVQcow2State *s = bs->opaque;
183
+ QCow2ClusterType type = qcow2_get_cluster_type(bs, l2_entry);
184
+ assert(sc_index < s->subclusters_per_cluster);
185
+
186
+ if (has_subclusters(s)) {
187
+ switch (type) {
188
+ case QCOW2_CLUSTER_COMPRESSED:
189
+ return QCOW2_SUBCLUSTER_COMPRESSED;
190
+ case QCOW2_CLUSTER_NORMAL:
191
+ if ((l2_bitmap >> 32) & l2_bitmap) {
192
+ return QCOW2_SUBCLUSTER_INVALID;
193
+ } else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) {
194
+ return QCOW2_SUBCLUSTER_ZERO_ALLOC;
195
+ } else if (l2_bitmap & QCOW_OFLAG_SUB_ALLOC(sc_index)) {
196
+ return QCOW2_SUBCLUSTER_NORMAL;
197
+ } else {
198
+ return QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC;
199
+ }
200
+ case QCOW2_CLUSTER_UNALLOCATED:
201
+ if (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC) {
202
+ return QCOW2_SUBCLUSTER_INVALID;
203
+ } else if (l2_bitmap & QCOW_OFLAG_SUB_ZERO(sc_index)) {
204
+ return QCOW2_SUBCLUSTER_ZERO_PLAIN;
205
+ } else {
206
+ return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
207
+ }
208
+ default:
209
+ g_assert_not_reached();
210
+ }
211
+ } else {
212
+ return qcow2_cluster_to_subcluster_type(type);
213
+ }
214
+}
215
+
216
/* Check whether refcounts are eager or lazy */
217
static inline bool qcow2_need_accurate_refcounts(BDRVQcow2State *s)
218
{
219
--
220
2.26.2
221
222
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Wrap the code that was copied repeatedly in the two functions,
3
There are situations in which we want to know how many contiguous
4
sd_aio_setup and sd_aio_complete.
4
subclusters of the same type there are in a given cluster. This can be
5
done by simply iterating over the subclusters and repeatedly calling
6
qcow2_get_subcluster_type() for each one of them.
5
7
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
However once we determined the type of a subcluster we can check the
7
Message-id: 20161129113245.32724-6-pbonzini@redhat.com
9
rest efficiently by counting the number of adjacent ones (or zeroes)
8
Signed-off-by: Jeff Cody <jcody@redhat.com>
10
in the bitmap. This is what this function does.
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <db917263d568ec6ffb4a41cac3c9100f96bf6c18.1594396418.git.berto@igalia.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
17
---
10
block/sheepdog.c | 66 ++++++++++++++++++++++++++------------------------------
18
block/qcow2-cluster.c | 51 +++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 30 insertions(+), 36 deletions(-)
19
1 file changed, 51 insertions(+)
12
20
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
21
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
23
--- a/block/qcow2-cluster.c
16
+++ b/block/sheepdog.c
24
+++ b/block/qcow2-cluster.c
17
@@ -XXX,XX +XXX,XX @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
25
@@ -XXX,XX +XXX,XX @@ fail:
18
return aio_req;
26
return ret;
19
}
27
}
20
28
21
+static void wait_for_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *acb)
29
+/*
30
+ * For a given L2 entry, count the number of contiguous subclusters of
31
+ * the same type starting from @sc_from. Compressed clusters are
32
+ * treated as if they were divided into subclusters of size
33
+ * s->subcluster_size.
34
+ *
35
+ * Return the number of contiguous subclusters and set @type to the
36
+ * subcluster type.
37
+ *
38
+ * If the L2 entry is invalid return -errno and set @type to
39
+ * QCOW2_SUBCLUSTER_INVALID.
40
+ */
41
+G_GNUC_UNUSED
42
+static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
43
+ uint64_t l2_entry,
44
+ uint64_t l2_bitmap,
45
+ unsigned sc_from,
46
+ QCow2SubclusterType *type)
22
+{
47
+{
23
+ SheepdogAIOCB *cb;
48
+ BDRVQcow2State *s = bs->opaque;
49
+ uint32_t val;
24
+
50
+
25
+retry:
51
+ *type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_from);
26
+ QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
52
+
27
+ if (AIOCBOverlapping(acb, cb)) {
53
+ if (*type == QCOW2_SUBCLUSTER_INVALID) {
28
+ qemu_co_queue_wait(&s->overlapping_queue);
54
+ return -EINVAL;
29
+ goto retry;
55
+ } else if (!has_subclusters(s) || *type == QCOW2_SUBCLUSTER_COMPRESSED) {
30
+ }
56
+ return s->subclusters_per_cluster - sc_from;
57
+ }
58
+
59
+ switch (*type) {
60
+ case QCOW2_SUBCLUSTER_NORMAL:
61
+ val = l2_bitmap | QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
62
+ return cto32(val) - sc_from;
63
+
64
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
65
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
66
+ val = (l2_bitmap | QCOW_OFLAG_SUB_ZERO_RANGE(0, sc_from)) >> 32;
67
+ return cto32(val) - sc_from;
68
+
69
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
70
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
71
+ val = ((l2_bitmap >> 32) | l2_bitmap)
72
+ & ~QCOW_OFLAG_SUB_ALLOC_RANGE(0, sc_from);
73
+ return ctz32(val) - sc_from;
74
+
75
+ default:
76
+ g_assert_not_reached();
31
+ }
77
+ }
32
+}
78
+}
33
+
79
+
34
static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
80
/*
35
QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
81
* Checks how many clusters in a given L2 slice are contiguous in the image
36
int type)
82
* file. As soon as one of the flags in the bitmask stop_flags changes compared
37
@@ -XXX,XX +XXX,XX @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
38
acb->min_dirty_data_idx = UINT32_MAX;
39
acb->max_dirty_data_idx = 0;
40
acb->aiocb_type = type;
41
+
42
+ if (type == AIOCB_FLUSH_CACHE) {
43
+ return;
44
+ }
45
+
46
+ wait_for_overlapping_aiocb(s, acb);
47
+ QLIST_INSERT_HEAD(&s->inflight_aiocb_head, acb, aiocb_siblings);
48
}
49
50
/* Return -EIO in case of error, file descriptor on success */
51
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
52
}
53
}
54
55
-static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
56
+static void sd_aio_complete(SheepdogAIOCB *acb)
57
{
58
- SheepdogAIOCB *cb;
59
-
60
- QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
61
- if (AIOCBOverlapping(aiocb, cb)) {
62
- return true;
63
- }
64
+ if (acb->aiocb_type == AIOCB_FLUSH_CACHE) {
65
+ return;
66
}
67
68
- QLIST_INSERT_HEAD(&s->inflight_aiocb_head, aiocb, aiocb_siblings);
69
- return false;
70
+ QLIST_REMOVE(acb, aiocb_siblings);
71
+ qemu_co_queue_restart_all(&acb->s->overlapping_queue);
72
}
73
74
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
75
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
76
}
77
78
sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_WRITE_UDATA);
79
-
80
-retry:
81
- if (check_overlapping_aiocb(s, &acb)) {
82
- qemu_co_queue_wait(&s->overlapping_queue);
83
- goto retry;
84
- }
85
-
86
sd_co_rw_vector(&acb);
87
sd_write_done(&acb);
88
+ sd_aio_complete(&acb);
89
90
- QLIST_REMOVE(&acb, aiocb_siblings);
91
- qemu_co_queue_restart_all(&s->overlapping_queue);
92
return acb.ret;
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
96
BDRVSheepdogState *s = bs->opaque;
97
98
sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_READ_UDATA);
99
-
100
-retry:
101
- if (check_overlapping_aiocb(s, &acb)) {
102
- qemu_co_queue_wait(&s->overlapping_queue);
103
- goto retry;
104
- }
105
-
106
sd_co_rw_vector(&acb);
107
+ sd_aio_complete(&acb);
108
109
- QLIST_REMOVE(&acb, aiocb_siblings);
110
- qemu_co_queue_restart_all(&s->overlapping_queue);
111
return acb.ret;
112
}
113
114
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
115
if (--acb.nr_pending) {
116
qemu_coroutine_yield();
117
}
118
+
119
+ sd_aio_complete(&acb);
120
return acb.ret;
121
}
122
123
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
124
}
125
sd_aio_setup(&acb, s, &discard_iov, offset >> BDRV_SECTOR_BITS,
126
count >> BDRV_SECTOR_BITS, AIOCB_DISCARD_OBJ);
127
-
128
-retry:
129
- if (check_overlapping_aiocb(s, &acb)) {
130
- qemu_co_queue_wait(&s->overlapping_queue);
131
- goto retry;
132
- }
133
-
134
sd_co_rw_vector(&acb);
135
+ sd_aio_complete(&acb);
136
137
- QLIST_REMOVE(&acb, aiocb_siblings);
138
- qemu_co_queue_restart_all(&s->overlapping_queue);
139
return acb.ret;
140
}
141
142
--
83
--
143
2.9.3
84
2.26.2
144
85
145
86
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Add to the list in add_aio_request and, indirectly, resend_aioreq. Inline
3
This helper function tells us if a cluster is allocated (that is,
4
free_aio_req in the caller, it does not simply undo alloc_aio_req's job.
4
there is an associated host offset for it).
5
5
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Message-id: 20161129113245.32724-5-pbonzini@redhat.com
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Jeff Cody <jcody@redhat.com>
8
Reviewed-by: Max Reitz <mreitz@redhat.com>
9
Message-Id: <6d8771c5c79cbdc6c519875a5078e1cc85856d63.1594396418.git.berto@igalia.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
11
---
10
block/sheepdog.c | 23 ++++++-----------------
12
block/qcow2.h | 6 ++++++
11
1 file changed, 6 insertions(+), 17 deletions(-)
13
1 file changed, 6 insertions(+)
12
14
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
15
diff --git a/block/qcow2.h b/block/qcow2.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
17
--- a/block/qcow2.h
16
+++ b/block/sheepdog.c
18
+++ b/block/qcow2.h
17
@@ -XXX,XX +XXX,XX @@ static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
19
@@ -XXX,XX +XXX,XX @@ QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs,
18
return aio_req;
19
}
20
21
-static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
22
-{
23
- SheepdogAIOCB *acb = aio_req->aiocb;
24
-
25
- QLIST_REMOVE(aio_req, aio_siblings);
26
- g_free(aio_req);
27
-
28
- acb->nr_pending--;
29
-}
30
-
31
static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
32
QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
33
int type)
34
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void reconnect_to_sdog(void *opaque)
35
while (!QLIST_EMPTY(&s->failed_aio_head)) {
36
aio_req = QLIST_FIRST(&s->failed_aio_head);
37
QLIST_REMOVE(aio_req, aio_siblings);
38
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
39
resend_aioreq(s, aio_req);
40
}
20
}
41
}
21
}
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
22
43
*/
23
+static inline bool qcow2_cluster_is_allocated(QCow2ClusterType type)
44
s->co_recv = NULL;
24
+{
45
25
+ return (type == QCOW2_CLUSTER_COMPRESSED || type == QCOW2_CLUSTER_NORMAL ||
46
+ QLIST_REMOVE(aio_req, aio_siblings);
26
+ type == QCOW2_CLUSTER_ZERO_ALLOC);
47
switch (rsp.result) {
27
+}
48
case SD_RES_SUCCESS:
49
break;
50
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
51
break;
52
}
53
54
- free_aio_req(s, aio_req);
55
- if (!acb->nr_pending) {
56
+ g_free(aio_req);
57
+
28
+
58
+ if (!--acb->nr_pending) {
29
/* Check whether refcounts are eager or lazy */
59
/*
30
static inline bool qcow2_need_accurate_refcounts(BDRVQcow2State *s)
60
* We've finished all requests which belong to the AIOCB, so
31
{
61
* we can switch back to sd_co_readv/writev now.
62
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
63
uint64_t old_oid = aio_req->base_oid;
64
bool create = aio_req->create;
65
66
+ QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
67
+
68
if (!nr_copies) {
69
error_report("bug");
70
}
71
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
72
iov.iov_len = sizeof(s->inode);
73
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
74
data_len, offset, 0, false, 0, offset);
75
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
76
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
77
if (--acb->nr_pending) {
78
qemu_coroutine_yield();
79
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
80
old_oid,
81
acb->aiocb_type == AIOCB_DISCARD_OBJ ?
82
0 : done);
83
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
84
-
85
add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
86
acb->aiocb_type);
87
done:
88
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
89
acb.nr_pending++;
90
aio_req = alloc_aio_req(s, &acb, vid_to_vdi_oid(s->inode.vdi_id),
91
0, 0, 0, false, 0, 0);
92
- QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
93
add_aio_request(s, aio_req, NULL, 0, acb.aiocb_type);
94
95
if (--acb.nr_pending) {
96
--
32
--
97
2.9.3
33
2.26.2
98
34
99
35
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This function returns an integer that can be either an error code or a
4
cluster type (a value from the QCow2ClusterType enum).
5
6
We are going to start using subcluster types instead of cluster types
7
in some functions so it's better to use the exact data types instead
8
of integers for clarity and in order to detect errors more easily.
9
10
This patch makes qcow2_get_host_offset() return 0 on success and
11
puts the returned cluster type in a separate parameter. There are no
12
semantic changes.
13
14
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
16
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
17
Message-Id: <396b6eab1859a271551dcd7dcba77f8934aa3c3f.1594396418.git.berto@igalia.com>
18
Signed-off-by: Max Reitz <mreitz@redhat.com>
19
---
20
block/qcow2.h | 3 ++-
21
block/qcow2-cluster.c | 11 +++++++----
22
block/qcow2.c | 37 ++++++++++++++++++++++---------------
23
3 files changed, 31 insertions(+), 20 deletions(-)
24
25
diff --git a/block/qcow2.h b/block/qcow2.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/qcow2.h
28
+++ b/block/qcow2.h
29
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
30
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
31
32
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
33
- unsigned int *bytes, uint64_t *host_offset);
34
+ unsigned int *bytes, uint64_t *host_offset,
35
+ QCow2ClusterType *cluster_type);
36
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
37
unsigned int *bytes, uint64_t *host_offset,
38
QCowL2Meta **m);
39
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2-cluster.c
42
+++ b/block/qcow2-cluster.c
43
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
44
*
45
* On exit, *bytes is the number of bytes starting at offset that have the same
46
* cluster type and (if applicable) are stored contiguously in the image file.
47
+ * The cluster type is stored in *cluster_type.
48
* Compressed clusters are always returned one by one.
49
*
50
- * Returns the cluster type (QCOW2_CLUSTER_*) on success, -errno in error
51
- * cases.
52
+ * Returns 0 on success, -errno in error cases.
53
*/
54
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
55
- unsigned int *bytes, uint64_t *host_offset)
56
+ unsigned int *bytes, uint64_t *host_offset,
57
+ QCow2ClusterType *cluster_type)
58
{
59
BDRVQcow2State *s = bs->opaque;
60
unsigned int l2_index;
61
@@ -XXX,XX +XXX,XX @@ out:
62
assert(bytes_available - offset_in_cluster <= UINT_MAX);
63
*bytes = bytes_available - offset_in_cluster;
64
65
- return type;
66
+ *cluster_type = type;
67
+
68
+ return 0;
69
70
fail:
71
qcow2_cache_put(s->l2_table_cache, (void **)&l2_slice);
72
diff --git a/block/qcow2.c b/block/qcow2.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/qcow2.c
75
+++ b/block/qcow2.c
76
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
77
BDRVQcow2State *s = bs->opaque;
78
uint64_t host_offset;
79
unsigned int bytes;
80
+ QCow2ClusterType type;
81
int ret, status = 0;
82
83
qemu_co_mutex_lock(&s->lock);
84
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
85
}
86
87
bytes = MIN(INT_MAX, count);
88
- ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset);
89
+ ret = qcow2_get_host_offset(bs, offset, &bytes, &host_offset, &type);
90
qemu_co_mutex_unlock(&s->lock);
91
if (ret < 0) {
92
return ret;
93
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
94
95
*pnum = bytes;
96
97
- if ((ret == QCOW2_CLUSTER_NORMAL || ret == QCOW2_CLUSTER_ZERO_ALLOC) &&
98
+ if ((type == QCOW2_CLUSTER_NORMAL || type == QCOW2_CLUSTER_ZERO_ALLOC) &&
99
!s->crypto) {
100
*map = host_offset;
101
*file = s->data_file->bs;
102
status |= BDRV_BLOCK_OFFSET_VALID;
103
}
104
- if (ret == QCOW2_CLUSTER_ZERO_PLAIN || ret == QCOW2_CLUSTER_ZERO_ALLOC) {
105
+ if (type == QCOW2_CLUSTER_ZERO_PLAIN || type == QCOW2_CLUSTER_ZERO_ALLOC) {
106
status |= BDRV_BLOCK_ZERO;
107
- } else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
108
+ } else if (type != QCOW2_CLUSTER_UNALLOCATED) {
109
status |= BDRV_BLOCK_DATA;
110
}
111
if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
112
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
113
int ret = 0;
114
unsigned int cur_bytes; /* number of bytes in current iteration */
115
uint64_t host_offset = 0;
116
+ QCow2ClusterType type;
117
AioTaskPool *aio = NULL;
118
119
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
120
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
121
}
122
123
qemu_co_mutex_lock(&s->lock);
124
- ret = qcow2_get_host_offset(bs, offset, &cur_bytes, &host_offset);
125
+ ret = qcow2_get_host_offset(bs, offset, &cur_bytes,
126
+ &host_offset, &type);
127
qemu_co_mutex_unlock(&s->lock);
128
if (ret < 0) {
129
goto out;
130
}
131
132
- if (ret == QCOW2_CLUSTER_ZERO_PLAIN ||
133
- ret == QCOW2_CLUSTER_ZERO_ALLOC ||
134
- (ret == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
135
+ if (type == QCOW2_CLUSTER_ZERO_PLAIN ||
136
+ type == QCOW2_CLUSTER_ZERO_ALLOC ||
137
+ (type == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
138
{
139
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
140
} else {
141
if (!aio && cur_bytes != bytes) {
142
aio = aio_task_pool_new(QCOW2_MAX_WORKERS);
143
}
144
- ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, ret,
145
+ ret = qcow2_add_task(bs, aio, qcow2_co_preadv_task_entry, type,
146
host_offset, offset, cur_bytes,
147
qiov, qiov_offset, NULL);
148
if (ret < 0) {
149
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
150
if (head || tail) {
151
uint64_t off;
152
unsigned int nr;
153
+ QCow2ClusterType type;
154
155
assert(head + bytes <= s->cluster_size);
156
157
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
158
offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
159
bytes = s->cluster_size;
160
nr = s->cluster_size;
161
- ret = qcow2_get_host_offset(bs, offset, &nr, &off);
162
- if (ret != QCOW2_CLUSTER_UNALLOCATED &&
163
- ret != QCOW2_CLUSTER_ZERO_PLAIN &&
164
- ret != QCOW2_CLUSTER_ZERO_ALLOC) {
165
+ ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type);
166
+ if (ret < 0 ||
167
+ (type != QCOW2_CLUSTER_UNALLOCATED &&
168
+ type != QCOW2_CLUSTER_ZERO_PLAIN &&
169
+ type != QCOW2_CLUSTER_ZERO_ALLOC)) {
170
qemu_co_mutex_unlock(&s->lock);
171
return -ENOTSUP;
172
}
173
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
174
175
while (bytes != 0) {
176
uint64_t copy_offset = 0;
177
+ QCow2ClusterType type;
178
/* prepare next request */
179
cur_bytes = MIN(bytes, INT_MAX);
180
cur_write_flags = write_flags;
181
182
- ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes, &copy_offset);
183
+ ret = qcow2_get_host_offset(bs, src_offset, &cur_bytes,
184
+ &copy_offset, &type);
185
if (ret < 0) {
186
goto out;
187
}
188
189
- switch (ret) {
190
+ switch (type) {
191
case QCOW2_CLUSTER_UNALLOCATED:
192
if (bs->backing && bs->backing->bs) {
193
int64_t backing_length = bdrv_getlength(bs->backing->bs);
194
--
195
2.26.2
196
197
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
In order to support extended L2 entries some functions of the qcow2
4
driver need to start dealing with subclusters instead of clusters.
5
6
qcow2_get_host_offset() is modified to return the subcluster type
7
instead of the cluster type, and all callers are updated to replace
8
all values of QCow2ClusterType with their QCow2SubclusterType
9
equivalents.
10
11
This patch only changes the data types, there are no semantic changes.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-Id: <f6c29737c295f32cbee74c903c30b01820363b34.1594396418.git.berto@igalia.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2.h | 2 +-
20
block/qcow2-cluster.c | 10 +++----
21
block/qcow2.c | 70 ++++++++++++++++++++++---------------------
22
3 files changed, 42 insertions(+), 40 deletions(-)
23
24
diff --git a/block/qcow2.h b/block/qcow2.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/qcow2.h
27
+++ b/block/qcow2.h
28
@@ -XXX,XX +XXX,XX @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
29
30
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
31
unsigned int *bytes, uint64_t *host_offset,
32
- QCow2ClusterType *cluster_type);
33
+ QCow2SubclusterType *subcluster_type);
34
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
35
unsigned int *bytes, uint64_t *host_offset,
36
QCowL2Meta **m);
37
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/block/qcow2-cluster.c
40
+++ b/block/qcow2-cluster.c
41
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn do_perform_cow_write(BlockDriverState *bs,
42
* offset that we are interested in.
43
*
44
* On exit, *bytes is the number of bytes starting at offset that have the same
45
- * cluster type and (if applicable) are stored contiguously in the image file.
46
- * The cluster type is stored in *cluster_type.
47
- * Compressed clusters are always returned one by one.
48
+ * subcluster type and (if applicable) are stored contiguously in the image
49
+ * file. The subcluster type is stored in *subcluster_type.
50
+ * Compressed clusters are always processed one by one.
51
*
52
* Returns 0 on success, -errno in error cases.
53
*/
54
int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
55
unsigned int *bytes, uint64_t *host_offset,
56
- QCow2ClusterType *cluster_type)
57
+ QCow2SubclusterType *subcluster_type)
58
{
59
BDRVQcow2State *s = bs->opaque;
60
unsigned int l2_index;
61
@@ -XXX,XX +XXX,XX @@ out:
62
assert(bytes_available - offset_in_cluster <= UINT_MAX);
63
*bytes = bytes_available - offset_in_cluster;
64
65
- *cluster_type = type;
66
+ *subcluster_type = qcow2_cluster_to_subcluster_type(type);
67
68
return 0;
69
70
diff --git a/block/qcow2.c b/block/qcow2.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/qcow2.c
73
+++ b/block/qcow2.c
74
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
75
BDRVQcow2State *s = bs->opaque;
76
uint64_t host_offset;
77
unsigned int bytes;
78
- QCow2ClusterType type;
79
+ QCow2SubclusterType type;
80
int ret, status = 0;
81
82
qemu_co_mutex_lock(&s->lock);
83
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
84
85
*pnum = bytes;
86
87
- if ((type == QCOW2_CLUSTER_NORMAL || type == QCOW2_CLUSTER_ZERO_ALLOC) &&
88
- !s->crypto) {
89
+ if ((type == QCOW2_SUBCLUSTER_NORMAL ||
90
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC) && !s->crypto) {
91
*map = host_offset;
92
*file = s->data_file->bs;
93
status |= BDRV_BLOCK_OFFSET_VALID;
94
}
95
- if (type == QCOW2_CLUSTER_ZERO_PLAIN || type == QCOW2_CLUSTER_ZERO_ALLOC) {
96
+ if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
97
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC) {
98
status |= BDRV_BLOCK_ZERO;
99
- } else if (type != QCOW2_CLUSTER_UNALLOCATED) {
100
+ } else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN) {
101
status |= BDRV_BLOCK_DATA;
102
}
103
if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
104
@@ -XXX,XX +XXX,XX @@ typedef struct Qcow2AioTask {
105
AioTask task;
106
107
BlockDriverState *bs;
108
- QCow2ClusterType cluster_type; /* only for read */
109
+ QCow2SubclusterType subcluster_type; /* only for read */
110
uint64_t host_offset; /* or full descriptor in compressed clusters */
111
uint64_t offset;
112
uint64_t bytes;
113
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task);
114
static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
115
AioTaskPool *pool,
116
AioTaskFunc func,
117
- QCow2ClusterType cluster_type,
118
+ QCow2SubclusterType subcluster_type,
119
uint64_t host_offset,
120
uint64_t offset,
121
uint64_t bytes,
122
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
123
*task = (Qcow2AioTask) {
124
.task.func = func,
125
.bs = bs,
126
- .cluster_type = cluster_type,
127
+ .subcluster_type = subcluster_type,
128
.qiov = qiov,
129
.host_offset = host_offset,
130
.offset = offset,
131
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
132
133
trace_qcow2_add_task(qemu_coroutine_self(), bs, pool,
134
func == qcow2_co_preadv_task_entry ? "read" : "write",
135
- cluster_type, host_offset, offset, bytes,
136
+ subcluster_type, host_offset, offset, bytes,
137
qiov, qiov_offset);
138
139
if (!pool) {
140
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_add_task(BlockDriverState *bs,
141
}
142
143
static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
144
- QCow2ClusterType cluster_type,
145
+ QCow2SubclusterType subc_type,
146
uint64_t host_offset,
147
uint64_t offset, uint64_t bytes,
148
QEMUIOVector *qiov,
149
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
150
{
151
BDRVQcow2State *s = bs->opaque;
152
153
- switch (cluster_type) {
154
- case QCOW2_CLUSTER_ZERO_PLAIN:
155
- case QCOW2_CLUSTER_ZERO_ALLOC:
156
+ switch (subc_type) {
157
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
158
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
159
/* Both zero types are handled in qcow2_co_preadv_part */
160
g_assert_not_reached();
161
162
- case QCOW2_CLUSTER_UNALLOCATED:
163
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
164
assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
165
166
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
167
return bdrv_co_preadv_part(bs->backing, offset, bytes,
168
qiov, qiov_offset, 0);
169
170
- case QCOW2_CLUSTER_COMPRESSED:
171
+ case QCOW2_SUBCLUSTER_COMPRESSED:
172
return qcow2_co_preadv_compressed(bs, host_offset,
173
offset, bytes, qiov, qiov_offset);
174
175
- case QCOW2_CLUSTER_NORMAL:
176
+ case QCOW2_SUBCLUSTER_NORMAL:
177
if (bs->encrypted) {
178
return qcow2_co_preadv_encrypted(bs, host_offset,
179
offset, bytes, qiov, qiov_offset);
180
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task_entry(AioTask *task)
181
182
assert(!t->l2meta);
183
184
- return qcow2_co_preadv_task(t->bs, t->cluster_type, t->host_offset,
185
- t->offset, t->bytes, t->qiov, t->qiov_offset);
186
+ return qcow2_co_preadv_task(t->bs, t->subcluster_type,
187
+ t->host_offset, t->offset, t->bytes,
188
+ t->qiov, t->qiov_offset);
189
}
190
191
static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
192
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
193
int ret = 0;
194
unsigned int cur_bytes; /* number of bytes in current iteration */
195
uint64_t host_offset = 0;
196
- QCow2ClusterType type;
197
+ QCow2SubclusterType type;
198
AioTaskPool *aio = NULL;
199
200
while (bytes != 0 && aio_task_pool_status(aio) == 0) {
201
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
202
goto out;
203
}
204
205
- if (type == QCOW2_CLUSTER_ZERO_PLAIN ||
206
- type == QCOW2_CLUSTER_ZERO_ALLOC ||
207
- (type == QCOW2_CLUSTER_UNALLOCATED && !bs->backing))
208
+ if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
209
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
210
+ (type == QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && !bs->backing))
211
{
212
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
213
} else {
214
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_task_entry(AioTask *task)
215
{
216
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
217
218
- assert(!t->cluster_type);
219
+ assert(!t->subcluster_type);
220
221
return qcow2_co_pwritev_task(t->bs, t->host_offset,
222
t->offset, t->bytes, t->qiov, t->qiov_offset,
223
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
224
if (head || tail) {
225
uint64_t off;
226
unsigned int nr;
227
- QCow2ClusterType type;
228
+ QCow2SubclusterType type;
229
230
assert(head + bytes <= s->cluster_size);
231
232
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
233
nr = s->cluster_size;
234
ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type);
235
if (ret < 0 ||
236
- (type != QCOW2_CLUSTER_UNALLOCATED &&
237
- type != QCOW2_CLUSTER_ZERO_PLAIN &&
238
- type != QCOW2_CLUSTER_ZERO_ALLOC)) {
239
+ (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
240
+ type != QCOW2_SUBCLUSTER_ZERO_PLAIN &&
241
+ type != QCOW2_SUBCLUSTER_ZERO_ALLOC)) {
242
qemu_co_mutex_unlock(&s->lock);
243
return -ENOTSUP;
244
}
245
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
246
247
while (bytes != 0) {
248
uint64_t copy_offset = 0;
249
- QCow2ClusterType type;
250
+ QCow2SubclusterType type;
251
/* prepare next request */
252
cur_bytes = MIN(bytes, INT_MAX);
253
cur_write_flags = write_flags;
254
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
255
}
256
257
switch (type) {
258
- case QCOW2_CLUSTER_UNALLOCATED:
259
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
260
if (bs->backing && bs->backing->bs) {
261
int64_t backing_length = bdrv_getlength(bs->backing->bs);
262
if (src_offset >= backing_length) {
263
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
264
}
265
break;
266
267
- case QCOW2_CLUSTER_ZERO_PLAIN:
268
- case QCOW2_CLUSTER_ZERO_ALLOC:
269
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
270
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
271
cur_write_flags |= BDRV_REQ_ZERO_WRITE;
272
break;
273
274
- case QCOW2_CLUSTER_COMPRESSED:
275
+ case QCOW2_SUBCLUSTER_COMPRESSED:
276
ret = -ENOTSUP;
277
goto out;
278
279
- case QCOW2_CLUSTER_NORMAL:
280
+ case QCOW2_SUBCLUSTER_NORMAL:
281
child = s->data_file;
282
break;
283
284
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev_compressed_task_entry(AioTask *task)
285
{
286
Qcow2AioTask *t = container_of(task, Qcow2AioTask, task);
287
288
- assert(!t->cluster_type && !t->l2meta);
289
+ assert(!t->subcluster_type && !t->l2meta);
290
291
return qcow2_co_pwritev_compressed_task(t->bs, t->offset, t->bytes, t->qiov,
292
t->qiov_offset);
293
--
294
2.26.2
295
296
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
When dealing with subcluster types there is a new value called
4
QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC that has no equivalent in
5
QCow2ClusterType.
6
7
This patch handles that value in all places where subcluster types
8
are processed.
9
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
13
Message-Id: <bf09e2e2439a468a901bb96ace411eed9ee50295.1594396418.git.berto@igalia.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2.c | 12 +++++++++---
17
1 file changed, 9 insertions(+), 3 deletions(-)
18
19
diff --git a/block/qcow2.c b/block/qcow2.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block/qcow2.c
22
+++ b/block/qcow2.c
23
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
24
*pnum = bytes;
25
26
if ((type == QCOW2_SUBCLUSTER_NORMAL ||
27
- type == QCOW2_SUBCLUSTER_ZERO_ALLOC) && !s->crypto) {
28
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
29
+ type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) && !s->crypto) {
30
*map = host_offset;
31
*file = s->data_file->bs;
32
status |= BDRV_BLOCK_OFFSET_VALID;
33
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
34
if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
35
type == QCOW2_SUBCLUSTER_ZERO_ALLOC) {
36
status |= BDRV_BLOCK_ZERO;
37
- } else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN) {
38
+ } else if (type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
39
+ type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC) {
40
status |= BDRV_BLOCK_DATA;
41
}
42
if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
43
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_task(BlockDriverState *bs,
44
g_assert_not_reached();
45
46
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
47
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
48
assert(bs->backing); /* otherwise handled in qcow2_co_preadv_part */
49
50
BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO);
51
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv_part(BlockDriverState *bs,
52
53
if (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
54
type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
55
- (type == QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && !bs->backing))
56
+ (type == QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN && !bs->backing) ||
57
+ (type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC && !bs->backing))
58
{
59
qemu_iovec_memset(qiov, qiov_offset, 0, cur_bytes);
60
} else {
61
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
62
ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type);
63
if (ret < 0 ||
64
(type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
65
+ type != QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC &&
66
type != QCOW2_SUBCLUSTER_ZERO_PLAIN &&
67
type != QCOW2_SUBCLUSTER_ZERO_ALLOC)) {
68
qemu_co_mutex_unlock(&s->lock);
69
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
70
71
switch (type) {
72
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
73
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
74
if (bs->backing && bs->backing->bs) {
75
int64_t backing_length = bdrv_getlength(bs->backing->bs);
76
if (src_offset >= backing_length) {
77
--
78
2.26.2
79
80
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
If an image has subclusters then there are more copy-on-write
4
scenarios that we need to consider. Let's say we have a write request
5
from the middle of subcluster #3 until the end of the cluster:
6
7
1) If we are writing to a newly allocated cluster then we need
8
copy-on-write. The previous contents of subclusters #0 to #3 must
9
be copied to the new cluster. We can optimize this process by
10
skipping all leading unallocated or zero subclusters (the status of
11
those skipped subclusters will be reflected in the new L2 bitmap).
12
13
2) If we are overwriting an existing cluster:
14
15
2.1) If subcluster #3 is unallocated or has the all-zeroes bit set
16
then we need copy-on-write (on subcluster #3 only).
17
18
2.2) If subcluster #3 was already allocated then there is no need
19
for any copy-on-write. However we still need to update the L2
20
bitmap to reflect possible changes in the allocation status of
21
subclusters #4 to #31. Because of this, this function checks
22
if all the overwritten subclusters are already allocated and
23
in this case it returns without creating a new QCowL2Meta
24
structure.
25
26
After all these changes l2meta_cow_start() and l2meta_cow_end()
27
are not necessarily cluster-aligned anymore. We need to update the
28
calculation of old_start and old_end in handle_dependencies() to
29
guarantee that no two requests try to write on the same cluster.
30
31
Signed-off-by: Alberto Garcia <berto@igalia.com>
32
Reviewed-by: Eric Blake <eblake@redhat.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
34
Message-Id: <4292dd56e4446d386a2fe307311737a711c00708.1594396418.git.berto@igalia.com>
35
Signed-off-by: Max Reitz <mreitz@redhat.com>
36
---
37
block/qcow2-cluster.c | 167 +++++++++++++++++++++++++++++++++---------
38
1 file changed, 133 insertions(+), 34 deletions(-)
39
40
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/block/qcow2-cluster.c
43
+++ b/block/qcow2-cluster.c
44
@@ -XXX,XX +XXX,XX @@ fail:
45
* If the L2 entry is invalid return -errno and set @type to
46
* QCOW2_SUBCLUSTER_INVALID.
47
*/
48
-G_GNUC_UNUSED
49
static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
50
uint64_t l2_entry,
51
uint64_t l2_bitmap,
52
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m)
53
* If @keep_old is true it means that the clusters were already
54
* allocated and will be overwritten. If false then the clusters are
55
* new and we have to decrease the reference count of the old ones.
56
+ *
57
+ * Returns 0 on success, -errno on failure.
58
*/
59
-static void calculate_l2_meta(BlockDriverState *bs,
60
- uint64_t host_cluster_offset,
61
- uint64_t guest_offset, unsigned bytes,
62
- uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
63
+static int calculate_l2_meta(BlockDriverState *bs, uint64_t host_cluster_offset,
64
+ uint64_t guest_offset, unsigned bytes,
65
+ uint64_t *l2_slice, QCowL2Meta **m, bool keep_old)
66
{
67
BDRVQcow2State *s = bs->opaque;
68
- int l2_index = offset_to_l2_slice_index(s, guest_offset);
69
- uint64_t l2_entry;
70
+ int sc_index, l2_index = offset_to_l2_slice_index(s, guest_offset);
71
+ uint64_t l2_entry, l2_bitmap;
72
unsigned cow_start_from, cow_end_to;
73
unsigned cow_start_to = offset_into_cluster(s, guest_offset);
74
unsigned cow_end_from = cow_start_to + bytes;
75
unsigned nb_clusters = size_to_clusters(s, cow_end_from);
76
QCowL2Meta *old_m = *m;
77
- QCow2ClusterType type;
78
+ QCow2SubclusterType type;
79
+ int i;
80
+ bool skip_cow = keep_old;
81
82
assert(nb_clusters <= s->l2_slice_size - l2_index);
83
84
- /* Return if there's no COW (all clusters are normal and we keep them) */
85
- if (keep_old) {
86
- int i;
87
- for (i = 0; i < nb_clusters; i++) {
88
- l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
89
- if (qcow2_get_cluster_type(bs, l2_entry) != QCOW2_CLUSTER_NORMAL) {
90
- break;
91
+ /* Check the type of all affected subclusters */
92
+ for (i = 0; i < nb_clusters; i++) {
93
+ l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
94
+ l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
95
+ if (skip_cow) {
96
+ unsigned write_from = MAX(cow_start_to, i << s->cluster_bits);
97
+ unsigned write_to = MIN(cow_end_from, (i + 1) << s->cluster_bits);
98
+ int first_sc = offset_to_sc_index(s, write_from);
99
+ int last_sc = offset_to_sc_index(s, write_to - 1);
100
+ int cnt = qcow2_get_subcluster_range_type(bs, l2_entry, l2_bitmap,
101
+ first_sc, &type);
102
+ /* Is any of the subclusters of type != QCOW2_SUBCLUSTER_NORMAL ? */
103
+ if (type != QCOW2_SUBCLUSTER_NORMAL || first_sc + cnt <= last_sc) {
104
+ skip_cow = false;
105
}
106
+ } else {
107
+ /* If we can't skip the cow we can still look for invalid entries */
108
+ type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, 0);
109
}
110
- if (i == nb_clusters) {
111
- return;
112
+ if (type == QCOW2_SUBCLUSTER_INVALID) {
113
+ int l1_index = offset_to_l1_index(s, guest_offset);
114
+ uint64_t l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
115
+ qcow2_signal_corruption(bs, true, -1, -1, "Invalid cluster "
116
+ "entry found (L2 offset: %#" PRIx64
117
+ ", L2 index: %#x)",
118
+ l2_offset, l2_index + i);
119
+ return -EIO;
120
}
121
}
122
123
+ if (skip_cow) {
124
+ return 0;
125
+ }
126
+
127
/* Get the L2 entry of the first cluster */
128
l2_entry = get_l2_entry(s, l2_slice, l2_index);
129
- type = qcow2_get_cluster_type(bs, l2_entry);
130
-
131
- if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
132
- cow_start_from = cow_start_to;
133
+ l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
134
+ sc_index = offset_to_sc_index(s, guest_offset);
135
+ type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index);
136
+
137
+ if (!keep_old) {
138
+ switch (type) {
139
+ case QCOW2_SUBCLUSTER_COMPRESSED:
140
+ cow_start_from = 0;
141
+ break;
142
+ case QCOW2_SUBCLUSTER_NORMAL:
143
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
144
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
145
+ if (has_subclusters(s)) {
146
+ /* Skip all leading zero and unallocated subclusters */
147
+ uint32_t alloc_bitmap = l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC;
148
+ cow_start_from =
149
+ MIN(sc_index, ctz32(alloc_bitmap)) << s->subcluster_bits;
150
+ } else {
151
+ cow_start_from = 0;
152
+ }
153
+ break;
154
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
155
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
156
+ cow_start_from = sc_index << s->subcluster_bits;
157
+ break;
158
+ default:
159
+ g_assert_not_reached();
160
+ }
161
} else {
162
- cow_start_from = 0;
163
+ switch (type) {
164
+ case QCOW2_SUBCLUSTER_NORMAL:
165
+ cow_start_from = cow_start_to;
166
+ break;
167
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
168
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
169
+ cow_start_from = sc_index << s->subcluster_bits;
170
+ break;
171
+ default:
172
+ g_assert_not_reached();
173
+ }
174
}
175
176
/* Get the L2 entry of the last cluster */
177
- l2_entry = get_l2_entry(s, l2_slice, l2_index + nb_clusters - 1);
178
- type = qcow2_get_cluster_type(bs, l2_entry);
179
-
180
- if (type == QCOW2_CLUSTER_NORMAL && keep_old) {
181
- cow_end_to = cow_end_from;
182
+ l2_index += nb_clusters - 1;
183
+ l2_entry = get_l2_entry(s, l2_slice, l2_index);
184
+ l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
185
+ sc_index = offset_to_sc_index(s, guest_offset + bytes - 1);
186
+ type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index);
187
+
188
+ if (!keep_old) {
189
+ switch (type) {
190
+ case QCOW2_SUBCLUSTER_COMPRESSED:
191
+ cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
192
+ break;
193
+ case QCOW2_SUBCLUSTER_NORMAL:
194
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
195
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
196
+ cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
197
+ if (has_subclusters(s)) {
198
+ /* Skip all trailing zero and unallocated subclusters */
199
+ uint32_t alloc_bitmap = l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC;
200
+ cow_end_to -=
201
+ MIN(s->subclusters_per_cluster - sc_index - 1,
202
+ clz32(alloc_bitmap)) << s->subcluster_bits;
203
+ }
204
+ break;
205
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
206
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
207
+ cow_end_to = ROUND_UP(cow_end_from, s->subcluster_size);
208
+ break;
209
+ default:
210
+ g_assert_not_reached();
211
+ }
212
} else {
213
- cow_end_to = ROUND_UP(cow_end_from, s->cluster_size);
214
+ switch (type) {
215
+ case QCOW2_SUBCLUSTER_NORMAL:
216
+ cow_end_to = cow_end_from;
217
+ break;
218
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
219
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
220
+ cow_end_to = ROUND_UP(cow_end_from, s->subcluster_size);
221
+ break;
222
+ default:
223
+ g_assert_not_reached();
224
+ }
225
}
226
227
*m = g_malloc0(sizeof(**m));
228
@@ -XXX,XX +XXX,XX @@ static void calculate_l2_meta(BlockDriverState *bs,
229
230
qemu_co_queue_init(&(*m)->dependent_requests);
231
QLIST_INSERT_HEAD(&s->cluster_allocs, *m, next_in_flight);
232
+
233
+ return 0;
234
}
235
236
/*
237
@@ -XXX,XX +XXX,XX @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
238
239
uint64_t start = guest_offset;
240
uint64_t end = start + bytes;
241
- uint64_t old_start = l2meta_cow_start(old_alloc);
242
- uint64_t old_end = l2meta_cow_end(old_alloc);
243
+ uint64_t old_start = start_of_cluster(s, l2meta_cow_start(old_alloc));
244
+ uint64_t old_end = ROUND_UP(l2meta_cow_end(old_alloc), s->cluster_size);
245
246
if (end <= old_start || start >= old_end) {
247
/* No intersection */
248
@@ -XXX,XX +XXX,XX @@ static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
249
- offset_into_cluster(s, guest_offset));
250
assert(*bytes != 0);
251
252
- calculate_l2_meta(bs, cluster_offset, guest_offset,
253
- *bytes, l2_slice, m, true);
254
+ ret = calculate_l2_meta(bs, cluster_offset, guest_offset,
255
+ *bytes, l2_slice, m, true);
256
+ if (ret < 0) {
257
+ goto out;
258
+ }
259
260
ret = 1;
261
} else {
262
@@ -XXX,XX +XXX,XX @@ static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
263
*bytes = MIN(*bytes, nb_bytes - offset_into_cluster(s, guest_offset));
264
assert(*bytes != 0);
265
266
- calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes, l2_slice,
267
- m, false);
268
+ ret = calculate_l2_meta(bs, alloc_cluster_offset, guest_offset, *bytes,
269
+ l2_slice, m, false);
270
+ if (ret < 0) {
271
+ goto out;
272
+ }
273
274
ret = 1;
275
276
--
277
2.26.2
278
279
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
SheepdogAIOCB is internal to sheepdog.c, hence it is never canceled.
3
The logic of this function remains pretty much the same, except that
4
4
it uses count_contiguous_subclusters(), which combines the logic of
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
count_contiguous_clusters() / count_contiguous_clusters_unallocated()
6
Message-id: 20161129113245.32724-2-pbonzini@redhat.com
6
and checks individual subclusters.
7
Signed-off-by: Jeff Cody <jcody@redhat.com>
7
8
qcow2_cluster_to_subcluster_type() is not necessary as a separate
9
function anymore so it's inlined into its caller.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <d2193fd48653a350d80f0eca1c67b1d9053fb2f3.1594396418.git.berto@igalia.com>
14
[mreitz: Initialize expected_type to anything]
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
---
16
---
9
block/sheepdog.c | 52 ----------------------------------------------------
17
block/qcow2.h | 38 ++++-------
10
1 file changed, 52 deletions(-)
18
block/qcow2-cluster.c | 150 ++++++++++++++++++++++--------------------
11
19
2 files changed, 92 insertions(+), 96 deletions(-)
12
diff --git a/block/sheepdog.c b/block/sheepdog.c
20
21
diff --git a/block/qcow2.h b/block/qcow2.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/block/sheepdog.c
23
--- a/block/qcow2.h
15
+++ b/block/sheepdog.c
24
+++ b/block/qcow2.h
16
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
25
@@ -XXX,XX +XXX,XX @@ static inline QCow2ClusterType qcow2_get_cluster_type(BlockDriverState *bs,
17
Coroutine *coroutine;
26
}
18
void (*aio_done_func)(SheepdogAIOCB *);
19
20
- bool cancelable;
21
int nr_pending;
22
23
uint32_t min_affect_data_idx;
24
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
25
{
26
SheepdogAIOCB *acb = aio_req->aiocb;
27
28
- acb->cancelable = false;
29
QLIST_REMOVE(aio_req, aio_siblings);
30
g_free(aio_req);
31
32
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb)
33
qemu_aio_unref(acb);
34
}
27
}
35
28
36
-/*
29
-/*
37
- * Check whether the specified acb can be canceled
30
- * For an image without extended L2 entries, return the
38
- *
31
- * QCow2SubclusterType equivalent of a given QCow2ClusterType.
39
- * We can cancel aio when any request belonging to the acb is:
40
- * - Not processed by the sheepdog server.
41
- * - Not linked to the inflight queue.
42
- */
32
- */
43
-static bool sd_acb_cancelable(const SheepdogAIOCB *acb)
33
-static inline
34
-QCow2SubclusterType qcow2_cluster_to_subcluster_type(QCow2ClusterType type)
44
-{
35
-{
45
- BDRVSheepdogState *s = acb->common.bs->opaque;
36
- switch (type) {
46
- AIOReq *aioreq;
37
- case QCOW2_CLUSTER_COMPRESSED:
47
-
38
- return QCOW2_SUBCLUSTER_COMPRESSED;
48
- if (!acb->cancelable) {
39
- case QCOW2_CLUSTER_ZERO_PLAIN:
49
- return false;
40
- return QCOW2_SUBCLUSTER_ZERO_PLAIN;
50
- }
41
- case QCOW2_CLUSTER_ZERO_ALLOC:
51
-
42
- return QCOW2_SUBCLUSTER_ZERO_ALLOC;
52
- QLIST_FOREACH(aioreq, &s->inflight_aio_head, aio_siblings) {
43
- case QCOW2_CLUSTER_NORMAL:
53
- if (aioreq->aiocb == acb) {
44
- return QCOW2_SUBCLUSTER_NORMAL;
54
- return false;
45
- case QCOW2_CLUSTER_UNALLOCATED:
55
- }
46
- return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
56
- }
47
- default:
57
-
48
- g_assert_not_reached();
58
- return true;
59
-}
60
-
61
-static void sd_aio_cancel(BlockAIOCB *blockacb)
62
-{
63
- SheepdogAIOCB *acb = (SheepdogAIOCB *)blockacb;
64
- BDRVSheepdogState *s = acb->common.bs->opaque;
65
- AIOReq *aioreq, *next;
66
-
67
- if (sd_acb_cancelable(acb)) {
68
- /* Remove outstanding requests from failed queue. */
69
- QLIST_FOREACH_SAFE(aioreq, &s->failed_aio_head, aio_siblings,
70
- next) {
71
- if (aioreq->aiocb == acb) {
72
- free_aio_req(s, aioreq);
73
- }
74
- }
75
-
76
- assert(acb->nr_pending == 0);
77
- if (acb->common.cb) {
78
- acb->common.cb(acb->common.opaque, -ECANCELED);
79
- }
80
- sd_finish_aiocb(acb);
81
- }
49
- }
82
-}
50
-}
83
-
51
-
84
static const AIOCBInfo sd_aiocb_info = {
52
/*
85
.aiocb_size = sizeof(SheepdogAIOCB),
53
* In an image without subsclusters @l2_bitmap is ignored and
86
- .cancel_async = sd_aio_cancel,
54
* @sc_index must be 0.
87
};
55
@@ -XXX,XX +XXX,XX @@ QCow2SubclusterType qcow2_get_subcluster_type(BlockDriverState *bs,
88
56
g_assert_not_reached();
89
static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
57
}
90
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
58
} else {
91
acb->nb_sectors = nb_sectors;
59
- return qcow2_cluster_to_subcluster_type(type);
92
60
+ switch (type) {
93
acb->aio_done_func = NULL;
61
+ case QCOW2_CLUSTER_COMPRESSED:
94
- acb->cancelable = true;
62
+ return QCOW2_SUBCLUSTER_COMPRESSED;
95
acb->coroutine = qemu_coroutine_self();
63
+ case QCOW2_CLUSTER_ZERO_PLAIN:
96
acb->ret = 0;
64
+ return QCOW2_SUBCLUSTER_ZERO_PLAIN;
97
acb->nr_pending = 0;
65
+ case QCOW2_CLUSTER_ZERO_ALLOC:
66
+ return QCOW2_SUBCLUSTER_ZERO_ALLOC;
67
+ case QCOW2_CLUSTER_NORMAL:
68
+ return QCOW2_SUBCLUSTER_NORMAL;
69
+ case QCOW2_CLUSTER_UNALLOCATED:
70
+ return QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
71
+ default:
72
+ g_assert_not_reached();
73
+ }
74
}
75
}
76
77
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/block/qcow2-cluster.c
80
+++ b/block/qcow2-cluster.c
81
@@ -XXX,XX +XXX,XX @@ static int qcow2_get_subcluster_range_type(BlockDriverState *bs,
82
}
83
84
/*
85
- * Checks how many clusters in a given L2 slice are contiguous in the image
86
- * file. As soon as one of the flags in the bitmask stop_flags changes compared
87
- * to the first cluster, the search is stopped and the cluster is not counted
88
- * as contiguous. (This allows it, for example, to stop at the first compressed
89
- * cluster which may require a different handling)
90
+ * Return the number of contiguous subclusters of the exact same type
91
+ * in a given L2 slice, starting from cluster @l2_index, subcluster
92
+ * @sc_index. Allocated subclusters are required to be contiguous in
93
+ * the image file.
94
+ * At most @nb_clusters are checked (note that this means clusters,
95
+ * not subclusters).
96
+ * Compressed clusters are always processed one by one but for the
97
+ * purpose of this count they are treated as if they were divided into
98
+ * subclusters of size s->subcluster_size.
99
+ * On failure return -errno and update @l2_index to point to the
100
+ * invalid entry.
101
*/
102
-static int count_contiguous_clusters(BlockDriverState *bs, int nb_clusters,
103
- int cluster_size, uint64_t *l2_slice, int l2_index, uint64_t stop_flags)
104
+static int count_contiguous_subclusters(BlockDriverState *bs, int nb_clusters,
105
+ unsigned sc_index, uint64_t *l2_slice,
106
+ unsigned *l2_index)
107
{
108
BDRVQcow2State *s = bs->opaque;
109
- int i;
110
- QCow2ClusterType first_cluster_type;
111
- uint64_t mask = stop_flags | L2E_OFFSET_MASK | QCOW_OFLAG_COMPRESSED;
112
- uint64_t first_entry = get_l2_entry(s, l2_slice, l2_index);
113
- uint64_t offset = first_entry & mask;
114
+ int i, count = 0;
115
+ bool check_offset = false;
116
+ uint64_t expected_offset = 0;
117
+ QCow2SubclusterType expected_type = QCOW2_SUBCLUSTER_NORMAL, type;
118
119
- first_cluster_type = qcow2_get_cluster_type(bs, first_entry);
120
- if (first_cluster_type == QCOW2_CLUSTER_UNALLOCATED) {
121
- return 0;
122
- }
123
-
124
- /* must be allocated */
125
- assert(first_cluster_type == QCOW2_CLUSTER_NORMAL ||
126
- first_cluster_type == QCOW2_CLUSTER_ZERO_ALLOC);
127
+ assert(*l2_index + nb_clusters <= s->l2_slice_size);
128
129
for (i = 0; i < nb_clusters; i++) {
130
- uint64_t l2_entry = get_l2_entry(s, l2_slice, l2_index + i) & mask;
131
- if (offset + (uint64_t) i * cluster_size != l2_entry) {
132
+ unsigned first_sc = (i == 0) ? sc_index : 0;
133
+ uint64_t l2_entry = get_l2_entry(s, l2_slice, *l2_index + i);
134
+ uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, *l2_index + i);
135
+ int ret = qcow2_get_subcluster_range_type(bs, l2_entry, l2_bitmap,
136
+ first_sc, &type);
137
+ if (ret < 0) {
138
+ *l2_index += i; /* Point to the invalid entry */
139
+ return -EIO;
140
+ }
141
+ if (i == 0) {
142
+ if (type == QCOW2_SUBCLUSTER_COMPRESSED) {
143
+ /* Compressed clusters are always processed one by one */
144
+ return ret;
145
+ }
146
+ expected_type = type;
147
+ expected_offset = l2_entry & L2E_OFFSET_MASK;
148
+ check_offset = (type == QCOW2_SUBCLUSTER_NORMAL ||
149
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC ||
150
+ type == QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC);
151
+ } else if (type != expected_type) {
152
break;
153
+ } else if (check_offset) {
154
+ expected_offset += s->cluster_size;
155
+ if (expected_offset != (l2_entry & L2E_OFFSET_MASK)) {
156
+ break;
157
+ }
158
}
159
- }
160
-
161
- return i;
162
-}
163
-
164
-/*
165
- * Checks how many consecutive unallocated clusters in a given L2
166
- * slice have the same cluster type.
167
- */
168
-static int count_contiguous_clusters_unallocated(BlockDriverState *bs,
169
- int nb_clusters,
170
- uint64_t *l2_slice,
171
- int l2_index,
172
- QCow2ClusterType wanted_type)
173
-{
174
- BDRVQcow2State *s = bs->opaque;
175
- int i;
176
-
177
- assert(wanted_type == QCOW2_CLUSTER_ZERO_PLAIN ||
178
- wanted_type == QCOW2_CLUSTER_UNALLOCATED);
179
- for (i = 0; i < nb_clusters; i++) {
180
- uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
181
- QCow2ClusterType type = qcow2_get_cluster_type(bs, entry);
182
-
183
- if (type != wanted_type) {
184
+ count += ret;
185
+ /* Stop if there are type changes before the end of the cluster */
186
+ if (first_sc + ret < s->subclusters_per_cluster) {
187
break;
188
}
189
}
190
191
- return i;
192
+ return count;
193
}
194
195
static int coroutine_fn do_perform_cow_read(BlockDriverState *bs,
196
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
197
QCow2SubclusterType *subcluster_type)
198
{
199
BDRVQcow2State *s = bs->opaque;
200
- unsigned int l2_index;
201
- uint64_t l1_index, l2_offset, *l2_slice, l2_entry;
202
- int c;
203
+ unsigned int l2_index, sc_index;
204
+ uint64_t l1_index, l2_offset, *l2_slice, l2_entry, l2_bitmap;
205
+ int sc;
206
unsigned int offset_in_cluster;
207
uint64_t bytes_available, bytes_needed, nb_clusters;
208
- QCow2ClusterType type;
209
+ QCow2SubclusterType type;
210
int ret;
211
212
offset_in_cluster = offset_into_cluster(s, offset);
213
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
214
215
l1_index = offset_to_l1_index(s, offset);
216
if (l1_index >= s->l1_size) {
217
- type = QCOW2_CLUSTER_UNALLOCATED;
218
+ type = QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
219
goto out;
220
}
221
222
l2_offset = s->l1_table[l1_index] & L1E_OFFSET_MASK;
223
if (!l2_offset) {
224
- type = QCOW2_CLUSTER_UNALLOCATED;
225
+ type = QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN;
226
goto out;
227
}
228
229
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
230
/* find the cluster offset for the given disk offset */
231
232
l2_index = offset_to_l2_slice_index(s, offset);
233
+ sc_index = offset_to_sc_index(s, offset);
234
l2_entry = get_l2_entry(s, l2_slice, l2_index);
235
+ l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
236
237
nb_clusters = size_to_clusters(s, bytes_needed);
238
/* bytes_needed <= *bytes + offset_in_cluster, both of which are unsigned
239
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
240
* true */
241
assert(nb_clusters <= INT_MAX);
242
243
- type = qcow2_get_cluster_type(bs, l2_entry);
244
- if (s->qcow_version < 3 && (type == QCOW2_CLUSTER_ZERO_PLAIN ||
245
- type == QCOW2_CLUSTER_ZERO_ALLOC)) {
246
+ type = qcow2_get_subcluster_type(bs, l2_entry, l2_bitmap, sc_index);
247
+ if (s->qcow_version < 3 && (type == QCOW2_SUBCLUSTER_ZERO_PLAIN ||
248
+ type == QCOW2_SUBCLUSTER_ZERO_ALLOC)) {
249
qcow2_signal_corruption(bs, true, -1, -1, "Zero cluster entry found"
250
" in pre-v3 image (L2 offset: %#" PRIx64
251
", L2 index: %#x)", l2_offset, l2_index);
252
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
253
goto fail;
254
}
255
switch (type) {
256
- case QCOW2_CLUSTER_COMPRESSED:
257
+ case QCOW2_SUBCLUSTER_INVALID:
258
+ break; /* This is handled by count_contiguous_subclusters() below */
259
+ case QCOW2_SUBCLUSTER_COMPRESSED:
260
if (has_data_file(bs)) {
261
qcow2_signal_corruption(bs, true, -1, -1, "Compressed cluster "
262
"entry found in image with external data "
263
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
264
ret = -EIO;
265
goto fail;
266
}
267
- /* Compressed clusters can only be processed one by one */
268
- c = 1;
269
*host_offset = l2_entry & L2E_COMPRESSED_OFFSET_SIZE_MASK;
270
break;
271
- case QCOW2_CLUSTER_ZERO_PLAIN:
272
- case QCOW2_CLUSTER_UNALLOCATED:
273
- /* how many empty clusters ? */
274
- c = count_contiguous_clusters_unallocated(bs, nb_clusters,
275
- l2_slice, l2_index, type);
276
+ case QCOW2_SUBCLUSTER_ZERO_PLAIN:
277
+ case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
278
break;
279
- case QCOW2_CLUSTER_ZERO_ALLOC:
280
- case QCOW2_CLUSTER_NORMAL: {
281
+ case QCOW2_SUBCLUSTER_ZERO_ALLOC:
282
+ case QCOW2_SUBCLUSTER_NORMAL:
283
+ case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC: {
284
uint64_t host_cluster_offset = l2_entry & L2E_OFFSET_MASK;
285
*host_offset = host_cluster_offset + offset_in_cluster;
286
- /* how many allocated clusters ? */
287
- c = count_contiguous_clusters(bs, nb_clusters, s->cluster_size,
288
- l2_slice, l2_index, QCOW_OFLAG_ZERO);
289
if (offset_into_cluster(s, host_cluster_offset)) {
290
qcow2_signal_corruption(bs, true, -1, -1,
291
"Cluster allocation offset %#"
292
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
293
abort();
294
}
295
296
+ sc = count_contiguous_subclusters(bs, nb_clusters, sc_index,
297
+ l2_slice, &l2_index);
298
+ if (sc < 0) {
299
+ qcow2_signal_corruption(bs, true, -1, -1, "Invalid cluster entry found "
300
+ " (L2 offset: %#" PRIx64 ", L2 index: %#x)",
301
+ l2_offset, l2_index);
302
+ ret = -EIO;
303
+ goto fail;
304
+ }
305
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
306
307
- bytes_available = (int64_t)c * s->cluster_size;
308
+ bytes_available = ((int64_t)sc + sc_index) << s->subcluster_bits;
309
310
out:
311
if (bytes_available > bytes_needed) {
312
@@ -XXX,XX +XXX,XX @@ out:
313
assert(bytes_available - offset_in_cluster <= UINT_MAX);
314
*bytes = bytes_available - offset_in_cluster;
315
316
- *subcluster_type = qcow2_cluster_to_subcluster_type(type);
317
+ *subcluster_type = type;
318
319
return 0;
320
98
--
321
--
99
2.9.3
322
2.26.2
100
323
101
324
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Delimit co_recv's lifetime clearly in aio_read_response.
3
The QCOW_OFLAG_ZERO bit that indicates that a cluster reads as
4
zeroes is only used in standard L2 entries. Extended L2 entries use
5
individual 'all zeroes' bits for each subcluster.
4
6
5
Do a simple qemu_coroutine_enter in aio_read_response, letting
7
This must be taken into account when updating the L2 entry and also
6
sd_co_writev call sd_write_done.
8
when deciding that an existing entry does not need to be updated.
7
9
8
Handle nr_pending in the same way in sd_co_rw_vector,
10
Signed-off-by: Alberto Garcia <berto@igalia.com>
9
sd_write_done and sd_co_flush_to_disk.
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Message-Id: <b61d61606d8c9b367bd641ab37351ddb9172799a.1594396418.git.berto@igalia.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 38 ++++++++++++++++++++------------------
17
1 file changed, 20 insertions(+), 18 deletions(-)
10
18
11
Remove sd_co_rw_vector's return value; just leave with no
19
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
12
pending requests.
13
14
[Jeff: added missing 'return' back, spotted by Paolo after
15
series was applied.]
16
17
Signed-off-by: Jeff Cody <jcody@redhat.com>
18
---
19
block/sheepdog.c | 115 ++++++++++++++++++++-----------------------------------
20
1 file changed, 42 insertions(+), 73 deletions(-)
21
22
diff --git a/block/sheepdog.c b/block/sheepdog.c
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/block/sheepdog.c
21
--- a/block/qcow2-cluster.c
25
+++ b/block/sheepdog.c
22
+++ b/block/qcow2-cluster.c
26
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
23
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
27
enum AIOCBState aiocb_type;
24
int l2_index;
28
25
int ret;
29
Coroutine *coroutine;
26
int i;
30
- void (*aio_done_func)(SheepdogAIOCB *);
27
- bool unmap = !!(flags & BDRV_REQ_MAY_UNMAP);
28
29
ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
30
if (ret < 0) {
31
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
32
assert(nb_clusters <= INT_MAX);
33
34
for (i = 0; i < nb_clusters; i++) {
35
- uint64_t old_offset;
36
- QCow2ClusterType cluster_type;
31
-
37
-
32
int nr_pending;
38
- old_offset = get_l2_entry(s, l2_slice, l2_index + i);
33
39
+ uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
34
uint32_t min_affect_data_idx;
40
+ uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
35
@@ -XXX,XX +XXX,XX @@ static const char * sd_strerror(int err)
41
+ QCow2ClusterType type = qcow2_get_cluster_type(bs, old_l2_entry);
36
*
42
+ bool unmap = (type == QCOW2_CLUSTER_COMPRESSED) ||
37
* 1. In sd_co_rw_vector, we send the I/O requests to the server and
43
+ ((flags & BDRV_REQ_MAY_UNMAP) && qcow2_cluster_is_allocated(type));
38
* link the requests to the inflight_list in the
44
+ uint64_t new_l2_entry = unmap ? 0 : old_l2_entry;
39
- * BDRVSheepdogState. The function exits without waiting for
45
+ uint64_t new_l2_bitmap = old_l2_bitmap;
40
+ * BDRVSheepdogState. The function yields while waiting for
46
+
41
* receiving the response.
47
+ if (has_subclusters(s)) {
42
*
48
+ new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
43
* 2. We receive the response in aio_read_response, the fd handler to
49
+ } else {
44
- * the sheepdog connection. If metadata update is needed, we send
50
+ new_l2_entry |= QCOW_OFLAG_ZERO;
45
- * the write request to the vdi object in sd_write_done, the write
51
+ }
46
- * completion function. We switch back to sd_co_readv/writev after
52
47
- * all the requests belonging to the AIOCB are finished.
53
- /*
48
+ * the sheepdog connection. We switch back to sd_co_readv/sd_writev
54
- * Minimize L2 changes if the cluster already reads back as
49
+ * after all the requests belonging to the AIOCB are finished. If
55
- * zeroes with correct allocation.
50
+ * needed, sd_co_writev will send another requests for the vdi object.
56
- */
51
*/
57
- cluster_type = qcow2_get_cluster_type(bs, old_offset);
52
58
- if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN ||
53
static inline AIOReq *alloc_aio_req(BDRVSheepdogState *s, SheepdogAIOCB *acb,
59
- (cluster_type == QCOW2_CLUSTER_ZERO_ALLOC && !unmap)) {
54
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
60
+ if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) {
55
acb->nr_pending--;
61
continue;
56
}
57
58
-static void coroutine_fn sd_finish_aiocb(SheepdogAIOCB *acb)
59
-{
60
- qemu_coroutine_enter(acb->coroutine);
61
- qemu_aio_unref(acb);
62
-}
63
-
64
static const AIOCBInfo sd_aiocb_info = {
65
.aiocb_size = sizeof(SheepdogAIOCB),
66
};
67
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
68
acb->sector_num = sector_num;
69
acb->nb_sectors = nb_sectors;
70
71
- acb->aio_done_func = NULL;
72
acb->coroutine = qemu_coroutine_self();
73
acb->ret = 0;
74
acb->nr_pending = 0;
75
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
76
77
switch (acb->aiocb_type) {
78
case AIOCB_WRITE_UDATA:
79
- /* this coroutine context is no longer suitable for co_recv
80
- * because we may send data to update vdi objects */
81
- s->co_recv = NULL;
82
if (!is_data_obj(aio_req->oid)) {
83
break;
84
}
62
}
85
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
63
64
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
65
- if (cluster_type == QCOW2_CLUSTER_COMPRESSED || unmap) {
66
- set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
67
- qcow2_free_any_clusters(bs, old_offset, 1, QCOW2_DISCARD_REQUEST);
68
- } else {
69
- uint64_t entry = get_l2_entry(s, l2_slice, l2_index + i);
70
- set_l2_entry(s, l2_slice, l2_index + i, entry | QCOW_OFLAG_ZERO);
71
+ if (unmap) {
72
+ qcow2_free_any_clusters(bs, old_l2_entry, 1, QCOW2_DISCARD_REQUEST);
73
+ }
74
+ set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry);
75
+ if (has_subclusters(s)) {
76
+ set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
86
}
77
}
87
}
78
}
88
79
89
+ /* No more data for this aio_req (reload_inode below uses its own file
90
+ * descriptor handler which doesn't use co_recv).
91
+ */
92
+ s->co_recv = NULL;
93
+
94
switch (rsp.result) {
95
case SD_RES_SUCCESS:
96
break;
97
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
98
aio_req->oid = vid_to_vdi_oid(s->inode.vdi_id);
99
}
100
resend_aioreq(s, aio_req);
101
- goto out;
102
+ return;
103
default:
104
acb->ret = -EIO;
105
error_report("%s", sd_strerror(rsp.result));
106
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
107
* We've finished all requests which belong to the AIOCB, so
108
* we can switch back to sd_co_readv/writev now.
109
*/
110
- acb->aio_done_func(acb);
111
+ qemu_coroutine_enter(acb->coroutine);
112
}
113
-out:
114
- s->co_recv = NULL;
115
+
116
return;
117
+
118
err:
119
- s->co_recv = NULL;
120
reconnect_to_sdog(opaque);
121
}
122
123
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
124
/*
125
* This function is called after writing data objects. If we need to
126
* update metadata, this sends a write request to the vdi object.
127
- * Otherwise, this switches back to sd_co_readv/writev.
128
*/
129
static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
130
{
131
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
132
mx = acb->max_dirty_data_idx;
133
if (mn <= mx) {
134
/* we need to update the vdi object. */
135
+ ++acb->nr_pending;
136
offset = sizeof(s->inode) - sizeof(s->inode.data_vdi_id) +
137
mn * sizeof(s->inode.data_vdi_id[0]);
138
data_len = (mx - mn + 1) * sizeof(s->inode.data_vdi_id[0]);
139
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
140
data_len, offset, 0, false, 0, offset);
141
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
142
add_aio_request(s, aio_req, &iov, 1, AIOCB_WRITE_UDATA);
143
-
144
- acb->aio_done_func = sd_finish_aiocb;
145
- acb->aiocb_type = AIOCB_WRITE_UDATA;
146
- return;
147
+ if (--acb->nr_pending) {
148
+ qemu_coroutine_yield();
149
+ }
150
}
151
-
152
- sd_finish_aiocb(acb);
153
}
154
155
/* Delete current working VDI on the snapshot chain */
156
@@ -XXX,XX +XXX,XX @@ out:
157
* Returns 1 when we need to wait a response, 0 when there is no sent
158
* request and -errno in error cases.
159
*/
160
-static int coroutine_fn sd_co_rw_vector(void *p)
161
+static void coroutine_fn sd_co_rw_vector(void *p)
162
{
163
SheepdogAIOCB *acb = p;
164
int ret = 0;
165
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_rw_vector(void *p)
166
ret = sd_create_branch(s);
167
if (ret) {
168
acb->ret = -EIO;
169
- goto out;
170
+ return;
171
}
172
}
173
174
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_rw_vector(void *p)
175
idx++;
176
done += len;
177
}
178
-out:
179
- if (!--acb->nr_pending) {
180
- return acb->ret;
181
+ if (--acb->nr_pending) {
182
+ qemu_coroutine_yield();
183
}
184
- return 1;
185
}
186
187
static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
188
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
189
}
190
191
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
192
- acb->aio_done_func = sd_write_done;
193
acb->aiocb_type = AIOCB_WRITE_UDATA;
194
195
retry:
196
@@ -XXX,XX +XXX,XX @@ retry:
197
goto retry;
198
}
199
200
- ret = sd_co_rw_vector(acb);
201
- if (ret <= 0) {
202
- QLIST_REMOVE(acb, aiocb_siblings);
203
- qemu_co_queue_restart_all(&s->overlapping_queue);
204
- qemu_aio_unref(acb);
205
- return ret;
206
- }
207
-
208
- qemu_coroutine_yield();
209
+ sd_co_rw_vector(acb);
210
+ sd_write_done(acb);
211
212
QLIST_REMOVE(acb, aiocb_siblings);
213
qemu_co_queue_restart_all(&s->overlapping_queue);
214
-
215
- return acb->ret;
216
+ ret = acb->ret;
217
+ qemu_aio_unref(acb);
218
+ return ret;
219
}
220
221
static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
222
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
223
224
acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
225
acb->aiocb_type = AIOCB_READ_UDATA;
226
- acb->aio_done_func = sd_finish_aiocb;
227
228
retry:
229
if (check_overlapping_aiocb(s, acb)) {
230
@@ -XXX,XX +XXX,XX @@ retry:
231
goto retry;
232
}
233
234
- ret = sd_co_rw_vector(acb);
235
- if (ret <= 0) {
236
- QLIST_REMOVE(acb, aiocb_siblings);
237
- qemu_co_queue_restart_all(&s->overlapping_queue);
238
- qemu_aio_unref(acb);
239
- return ret;
240
- }
241
-
242
- qemu_coroutine_yield();
243
+ sd_co_rw_vector(acb);
244
245
QLIST_REMOVE(acb, aiocb_siblings);
246
qemu_co_queue_restart_all(&s->overlapping_queue);
247
- return acb->ret;
248
+ ret = acb->ret;
249
+ qemu_aio_unref(acb);
250
+ return ret;
251
}
252
253
static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
254
{
255
BDRVSheepdogState *s = bs->opaque;
256
SheepdogAIOCB *acb;
257
+ int ret;
258
AIOReq *aio_req;
259
260
if (s->cache_flags != SD_FLAG_CMD_CACHE) {
261
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
262
263
acb = sd_aio_setup(bs, NULL, 0, 0);
264
acb->aiocb_type = AIOCB_FLUSH_CACHE;
265
- acb->aio_done_func = sd_finish_aiocb;
266
267
+ acb->nr_pending++;
268
aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
269
0, 0, 0, false, 0, 0);
270
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
271
add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
272
273
- qemu_coroutine_yield();
274
- return acb->ret;
275
+ if (--acb->nr_pending) {
276
+ qemu_coroutine_yield();
277
+ }
278
+ ret = acb->ret;
279
+ qemu_aio_unref(acb);
280
+ return ret;
281
}
282
283
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
284
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
285
acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
286
count >> BDRV_SECTOR_BITS);
287
acb->aiocb_type = AIOCB_DISCARD_OBJ;
288
- acb->aio_done_func = sd_finish_aiocb;
289
290
retry:
291
if (check_overlapping_aiocb(s, acb)) {
292
@@ -XXX,XX +XXX,XX @@ retry:
293
goto retry;
294
}
295
296
- ret = sd_co_rw_vector(acb);
297
- if (ret <= 0) {
298
- QLIST_REMOVE(acb, aiocb_siblings);
299
- qemu_co_queue_restart_all(&s->overlapping_queue);
300
- qemu_aio_unref(acb);
301
- return ret;
302
- }
303
-
304
- qemu_coroutine_yield();
305
+ sd_co_rw_vector(acb);
306
307
QLIST_REMOVE(acb, aiocb_siblings);
308
qemu_co_queue_restart_all(&s->overlapping_queue);
309
-
310
- return acb->ret;
311
+ ret = acb->ret;
312
+ qemu_aio_unref(acb);
313
+ return ret;
314
}
315
316
static coroutine_fn int64_t
317
--
80
--
318
2.9.3
81
2.26.2
319
82
320
83
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Two things need to be taken into account here:
4
5
1) With full_discard == true the L2 entry must be cleared completely.
6
This also includes the L2 bitmap if the image has extended L2
7
entries.
8
9
2) With full_discard == false we have to make the discarded cluster
10
read back as zeroes. With normal L2 entries this is done with the
11
QCOW_OFLAG_ZERO bit, whereas with extended L2 entries this is done
12
with the individual 'all zeroes' bits for each subcluster.
13
14
Note however that QCOW_OFLAG_ZERO is not supported in v2 qcow2
15
images so, if there is a backing file, discard cannot guarantee
16
that the image will read back as zeroes. If this is important for
17
the caller it should forbid it as qcow2_co_pdiscard() does (see
18
80f5c01183 for more details).
19
20
Signed-off-by: Alberto Garcia <berto@igalia.com>
21
Reviewed-by: Eric Blake <eblake@redhat.com>
22
Reviewed-by: Max Reitz <mreitz@redhat.com>
23
Message-Id: <5ef8274e628aa3ab559bfac467abf488534f2b76.1594396418.git.berto@igalia.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
26
block/qcow2-cluster.c | 52 +++++++++++++++++++------------------------
27
1 file changed, 23 insertions(+), 29 deletions(-)
28
29
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/qcow2-cluster.c
32
+++ b/block/qcow2-cluster.c
33
@@ -XXX,XX +XXX,XX @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
34
assert(nb_clusters <= INT_MAX);
35
36
for (i = 0; i < nb_clusters; i++) {
37
- uint64_t old_l2_entry;
38
-
39
- old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
40
+ uint64_t old_l2_entry = get_l2_entry(s, l2_slice, l2_index + i);
41
+ uint64_t old_l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
42
+ uint64_t new_l2_entry = old_l2_entry;
43
+ uint64_t new_l2_bitmap = old_l2_bitmap;
44
+ QCow2ClusterType cluster_type =
45
+ qcow2_get_cluster_type(bs, old_l2_entry);
46
47
/*
48
+ * If full_discard is true, the cluster should not read back as zeroes,
49
+ * but rather fall through to the backing file.
50
+ *
51
* If full_discard is false, make sure that a discarded area reads back
52
* as zeroes for v3 images (we cannot do it for v2 without actually
53
* writing a zero-filled buffer). We can skip the operation if the
54
@@ -XXX,XX +XXX,XX @@ static int discard_in_l2_slice(BlockDriverState *bs, uint64_t offset,
55
*
56
* TODO We might want to use bdrv_block_status(bs) here, but we're
57
* holding s->lock, so that doesn't work today.
58
- *
59
- * If full_discard is true, the sector should not read back as zeroes,
60
- * but rather fall through to the backing file.
61
*/
62
- switch (qcow2_get_cluster_type(bs, old_l2_entry)) {
63
- case QCOW2_CLUSTER_UNALLOCATED:
64
- if (full_discard || !bs->backing) {
65
- continue;
66
- }
67
- break;
68
-
69
- case QCOW2_CLUSTER_ZERO_PLAIN:
70
- if (!full_discard) {
71
- continue;
72
+ if (full_discard) {
73
+ new_l2_entry = new_l2_bitmap = 0;
74
+ } else if (bs->backing || qcow2_cluster_is_allocated(cluster_type)) {
75
+ if (has_subclusters(s)) {
76
+ new_l2_entry = 0;
77
+ new_l2_bitmap = QCOW_L2_BITMAP_ALL_ZEROES;
78
+ } else {
79
+ new_l2_entry = s->qcow_version >= 3 ? QCOW_OFLAG_ZERO : 0;
80
}
81
- break;
82
-
83
- case QCOW2_CLUSTER_ZERO_ALLOC:
84
- case QCOW2_CLUSTER_NORMAL:
85
- case QCOW2_CLUSTER_COMPRESSED:
86
- break;
87
+ }
88
89
- default:
90
- abort();
91
+ if (old_l2_entry == new_l2_entry && old_l2_bitmap == new_l2_bitmap) {
92
+ continue;
93
}
94
95
/* First remove L2 entries */
96
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
97
- if (!full_discard && s->qcow_version >= 3) {
98
- set_l2_entry(s, l2_slice, l2_index + i, QCOW_OFLAG_ZERO);
99
- } else {
100
- set_l2_entry(s, l2_slice, l2_index + i, 0);
101
+ set_l2_entry(s, l2_slice, l2_index + i, new_l2_entry);
102
+ if (has_subclusters(s)) {
103
+ set_l2_bitmap(s, l2_slice, l2_index + i, new_l2_bitmap);
104
}
105
-
106
/* Then decrease the refcount */
107
qcow2_free_any_clusters(bs, old_l2_entry, 1, type);
108
}
109
--
110
2.26.2
111
112
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
The offset field of an uncompressed cluster's L2 entry must be aligned
4
to the cluster size, otherwise it is invalid. If the cluster has no
5
data then it means that the offset points to a preallocation, so we
6
can clear the offset field without affecting the guest-visible data.
7
This is what 'qemu-img check' does when run in repair mode.
8
9
On traditional qcow2 images this can only happen when QCOW_OFLAG_ZERO
10
is set, and repairing such entries turns the clusters from ZERO_ALLOC
11
into ZERO_PLAIN.
12
13
Extended L2 entries have no ZERO_ALLOC clusters and no QCOW_OFLAG_ZERO
14
but the idea is the same: if none of the subclusters are allocated
15
then we can clear the offset field and leave the bitmap untouched.
16
17
Signed-off-by: Alberto Garcia <berto@igalia.com>
18
Reviewed-by: Max Reitz <mreitz@redhat.com>
19
Message-Id: <9f4ed1d0a34b0a545b032c31ecd8c14734065342.1594396418.git.berto@igalia.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
22
block/qcow2-refcount.c | 16 +++++++++++-----
23
tests/qemu-iotests/060.out | 2 +-
24
2 files changed, 12 insertions(+), 6 deletions(-)
25
26
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/qcow2-refcount.c
29
+++ b/block/qcow2-refcount.c
30
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
31
32
/* Correct offsets are cluster aligned */
33
if (offset_into_cluster(s, offset)) {
34
+ bool contains_data;
35
res->corruptions++;
36
37
- if (qcow2_get_cluster_type(bs, l2_entry) ==
38
- QCOW2_CLUSTER_ZERO_ALLOC)
39
- {
40
- fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated zero "
41
+ if (has_subclusters(s)) {
42
+ uint64_t l2_bitmap = get_l2_bitmap(s, l2_table, i);
43
+ contains_data = (l2_bitmap & QCOW_L2_BITMAP_ALL_ALLOC);
44
+ } else {
45
+ contains_data = !(l2_entry & QCOW_OFLAG_ZERO);
46
+ }
47
+
48
+ if (!contains_data) {
49
+ fprintf(stderr, "%s offset=%" PRIx64 ": Preallocated "
50
"cluster is not properly aligned; L2 entry "
51
"corrupted.\n",
52
fix & BDRV_FIX_ERRORS ? "Repairing" : "ERROR",
53
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
54
int ign = active ? QCOW2_OL_ACTIVE_L2 :
55
QCOW2_OL_INACTIVE_L2;
56
57
- l2_entry = QCOW_OFLAG_ZERO;
58
+ l2_entry = has_subclusters(s) ? 0 : QCOW_OFLAG_ZERO;
59
set_l2_entry(s, l2_table, i, l2_entry);
60
ret = qcow2_pre_write_overlap_check(bs, ign,
61
l2e_offset, l2_entry_size(s), false);
62
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tests/qemu-iotests/060.out
65
+++ b/tests/qemu-iotests/060.out
66
@@ -XXX,XX +XXX,XX @@ discard 65536/65536 bytes at offset 0
67
qcow2: Marking image as corrupt: Preallocated zero cluster offset 0x2a00 unaligned (guest offset: 0); further corruption events will be suppressed
68
write failed: Input/output error
69
--- Repairing ---
70
-Repairing offset=2a00: Preallocated zero cluster is not properly aligned; L2 entry corrupted.
71
+Repairing offset=2a00: Preallocated cluster is not properly aligned; L2 entry corrupted.
72
The following inconsistencies were found and repaired:
73
74
0 leaked clusters
75
--
76
2.26.2
77
78
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
The L2 bitmap needs to be updated after each write to indicate what
4
new subclusters are now allocated. This needs to happen even if the
5
cluster was already allocated and the L2 entry was otherwise valid.
6
7
In some cases however a write operation doesn't need change the L2
8
bitmap (because all affected subclusters were already allocated). This
9
is detected in calculate_l2_meta(), and qcow2_alloc_cluster_link_l2()
10
is never called in those cases.
11
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Message-Id: <0875620d49f44320334b6a91c73b3f301f975f38.1594396418.git.berto@igalia.com>
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
---
18
block/qcow2-cluster.c | 18 ++++++++++++++++++
19
1 file changed, 18 insertions(+)
20
21
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-cluster.c
24
+++ b/block/qcow2-cluster.c
25
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
26
assert((offset & L2E_OFFSET_MASK) == offset);
27
28
set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED);
29
+
30
+ /* Update bitmap with the subclusters that were just written */
31
+ if (has_subclusters(s)) {
32
+ uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
33
+ unsigned written_from = m->cow_start.offset;
34
+ unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes ?:
35
+ m->nb_clusters << s->cluster_bits;
36
+ int first_sc, last_sc;
37
+ /* Narrow written_from and written_to down to the current cluster */
38
+ written_from = MAX(written_from, i << s->cluster_bits);
39
+ written_to = MIN(written_to, (i + 1) << s->cluster_bits);
40
+ assert(written_from < written_to);
41
+ first_sc = offset_to_sc_index(s, written_from);
42
+ last_sc = offset_to_sc_index(s, written_to - 1);
43
+ l2_bitmap |= QCOW_OFLAG_SUB_ALLOC_RANGE(first_sc, last_sc + 1);
44
+ l2_bitmap &= ~QCOW_OFLAG_SUB_ZERO_RANGE(first_sc, last_sc + 1);
45
+ set_l2_bitmap(s, l2_slice, l2_index + i, l2_bitmap);
46
+ }
47
}
48
49
50
--
51
2.26.2
52
53
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Compressed clusters always have the bitmap part of the extended L2
4
entry set to 0.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <04455b3de5dfeb9d1cfe1fc7b02d7060a6e09710.1594396418.git.berto@igalia.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qcow2-cluster.c | 3 +++
12
1 file changed, 3 insertions(+)
13
14
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2-cluster.c
17
+++ b/block/qcow2-cluster.c
18
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
19
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE_COMPRESSED);
20
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
21
set_l2_entry(s, l2_slice, l2_index, cluster_offset);
22
+ if (has_subclusters(s)) {
23
+ set_l2_bitmap(s, l2_slice, l2_index, 0);
24
+ }
25
qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
26
27
*host_offset = cluster_offset & s->cluster_offset_mask;
28
--
29
2.26.2
30
31
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
The bdrv_co_pwrite_zeroes() call here fills complete clusters with
4
zeroes, but it can happen that some subclusters are not part of the
5
write request or the copy-on-write. This patch makes sure that only
6
the affected subclusters are overwritten.
7
8
A potential improvement would be to also fill with zeroes the other
9
subclusters if we can guarantee that we are not overwriting existing
10
data. However this would waste more disk space, so we should first
11
evaluate if it's really worth doing.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
16
Message-Id: <b3dc97e8e2240ddb5191a4f930e8fc9653f94621.1594396418.git.berto@igalia.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
block/qcow2.c | 9 +++++----
20
1 file changed, 5 insertions(+), 4 deletions(-)
21
22
diff --git a/block/qcow2.c b/block/qcow2.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/qcow2.c
25
+++ b/block/qcow2.c
26
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
27
28
for (m = l2meta; m != NULL; m = m->next) {
29
int ret;
30
+ uint64_t start_offset = m->alloc_offset + m->cow_start.offset;
31
+ unsigned nb_bytes = m->cow_end.offset + m->cow_end.nb_bytes -
32
+ m->cow_start.offset;
33
34
if (!m->cow_start.nb_bytes && !m->cow_end.nb_bytes) {
35
continue;
36
@@ -XXX,XX +XXX,XX @@ static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta)
37
* efficiently zero out the whole clusters
38
*/
39
40
- ret = qcow2_pre_write_overlap_check(bs, 0, m->alloc_offset,
41
- m->nb_clusters * s->cluster_size,
42
+ ret = qcow2_pre_write_overlap_check(bs, 0, start_offset, nb_bytes,
43
true);
44
if (ret < 0) {
45
return ret;
46
}
47
48
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC_SPACE);
49
- ret = bdrv_co_pwrite_zeroes(s->data_file, m->alloc_offset,
50
- m->nb_clusters * s->cluster_size,
51
+ ret = bdrv_co_pwrite_zeroes(s->data_file, start_offset, nb_bytes,
52
BDRV_REQ_NO_FALLBACK);
53
if (ret < 0) {
54
if (ret != -ENOTSUP && ret != -EAGAIN) {
55
--
56
2.26.2
57
58
diff view generated by jsdifflib
New patch
1
1
From: Alberto Garcia <berto@igalia.com>
2
3
This works now at the subcluster level and pwrite_zeroes_alignment is
4
updated accordingly.
5
6
qcow2_cluster_zeroize() is turned into qcow2_subcluster_zeroize() with
7
the following changes:
8
9
- The request can now be subcluster-aligned.
10
11
- The cluster-aligned body of the request is still zeroized using
12
zero_in_l2_slice() as before.
13
14
- The subcluster-aligned head and tail of the request are zeroized
15
with the new zero_l2_subclusters() function.
16
17
There is just one thing to take into account for a possible future
18
improvement: compressed clusters cannot be partially zeroized so
19
zero_l2_subclusters() on the head or the tail can return -ENOTSUP.
20
This makes the caller repeat the *complete* request and write actual
21
zeroes to disk. This is sub-optimal because
22
23
1) if the head area was compressed we would still be able to use
24
the fast path for the body and possibly the tail.
25
26
2) if the tail area was compressed we are writing zeroes to the
27
head and the body areas, which are already zeroized.
28
29
Signed-off-by: Alberto Garcia <berto@igalia.com>
30
Reviewed-by: Max Reitz <mreitz@redhat.com>
31
Message-Id: <17e05e2ee7e12f10dcf012da81e83ebe27eb3bef.1594396418.git.berto@igalia.com>
32
Signed-off-by: Max Reitz <mreitz@redhat.com>
33
---
34
block/qcow2.h | 4 +--
35
block/qcow2-cluster.c | 81 +++++++++++++++++++++++++++++++++++++++----
36
block/qcow2.c | 33 +++++++++---------
37
3 files changed, 94 insertions(+), 24 deletions(-)
38
39
diff --git a/block/qcow2.h b/block/qcow2.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/qcow2.h
42
+++ b/block/qcow2.h
43
@@ -XXX,XX +XXX,XX @@ void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m);
44
int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset,
45
uint64_t bytes, enum qcow2_discard_type type,
46
bool full_discard);
47
-int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
48
- uint64_t bytes, int flags);
49
+int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
50
+ uint64_t bytes, int flags);
51
52
int qcow2_expand_zero_clusters(BlockDriverState *bs,
53
BlockDriverAmendStatusCB *status_cb,
54
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/qcow2-cluster.c
57
+++ b/block/qcow2-cluster.c
58
@@ -XXX,XX +XXX,XX @@ static int zero_in_l2_slice(BlockDriverState *bs, uint64_t offset,
59
return nb_clusters;
60
}
61
62
-int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
63
- uint64_t bytes, int flags)
64
+static int zero_l2_subclusters(BlockDriverState *bs, uint64_t offset,
65
+ unsigned nb_subclusters)
66
+{
67
+ BDRVQcow2State *s = bs->opaque;
68
+ uint64_t *l2_slice;
69
+ uint64_t old_l2_bitmap, l2_bitmap;
70
+ int l2_index, ret, sc = offset_to_sc_index(s, offset);
71
+
72
+ /* For full clusters use zero_in_l2_slice() instead */
73
+ assert(nb_subclusters > 0 && nb_subclusters < s->subclusters_per_cluster);
74
+ assert(sc + nb_subclusters <= s->subclusters_per_cluster);
75
+ assert(offset_into_subcluster(s, offset) == 0);
76
+
77
+ ret = get_cluster_table(bs, offset, &l2_slice, &l2_index);
78
+ if (ret < 0) {
79
+ return ret;
80
+ }
81
+
82
+ switch (qcow2_get_cluster_type(bs, get_l2_entry(s, l2_slice, l2_index))) {
83
+ case QCOW2_CLUSTER_COMPRESSED:
84
+ ret = -ENOTSUP; /* We cannot partially zeroize compressed clusters */
85
+ goto out;
86
+ case QCOW2_CLUSTER_NORMAL:
87
+ case QCOW2_CLUSTER_UNALLOCATED:
88
+ break;
89
+ default:
90
+ g_assert_not_reached();
91
+ }
92
+
93
+ old_l2_bitmap = l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index);
94
+
95
+ l2_bitmap |= QCOW_OFLAG_SUB_ZERO_RANGE(sc, sc + nb_subclusters);
96
+ l2_bitmap &= ~QCOW_OFLAG_SUB_ALLOC_RANGE(sc, sc + nb_subclusters);
97
+
98
+ if (old_l2_bitmap != l2_bitmap) {
99
+ set_l2_bitmap(s, l2_slice, l2_index, l2_bitmap);
100
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_slice);
101
+ }
102
+
103
+ ret = 0;
104
+out:
105
+ qcow2_cache_put(s->l2_table_cache, (void **) &l2_slice);
106
+
107
+ return ret;
108
+}
109
+
110
+int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset,
111
+ uint64_t bytes, int flags)
112
{
113
BDRVQcow2State *s = bs->opaque;
114
uint64_t end_offset = offset + bytes;
115
uint64_t nb_clusters;
116
+ unsigned head, tail;
117
int64_t cleared;
118
int ret;
119
120
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
121
}
122
123
/* Caller must pass aligned values, except at image end */
124
- assert(QEMU_IS_ALIGNED(offset, s->cluster_size));
125
- assert(QEMU_IS_ALIGNED(end_offset, s->cluster_size) ||
126
+ assert(offset_into_subcluster(s, offset) == 0);
127
+ assert(offset_into_subcluster(s, end_offset) == 0 ||
128
end_offset >= bs->total_sectors << BDRV_SECTOR_BITS);
129
130
/*
131
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
132
return -ENOTSUP;
133
}
134
135
- /* Each L2 slice is handled by its own loop iteration */
136
- nb_clusters = size_to_clusters(s, bytes);
137
+ head = MIN(end_offset, ROUND_UP(offset, s->cluster_size)) - offset;
138
+ offset += head;
139
+
140
+ tail = (end_offset >= bs->total_sectors << BDRV_SECTOR_BITS) ? 0 :
141
+ end_offset - MAX(offset, start_of_cluster(s, end_offset));
142
+ end_offset -= tail;
143
144
s->cache_discards = true;
145
146
+ if (head) {
147
+ ret = zero_l2_subclusters(bs, offset - head,
148
+ size_to_subclusters(s, head));
149
+ if (ret < 0) {
150
+ goto fail;
151
+ }
152
+ }
153
+
154
+ /* Each L2 slice is handled by its own loop iteration */
155
+ nb_clusters = size_to_clusters(s, end_offset - offset);
156
+
157
while (nb_clusters > 0) {
158
cleared = zero_in_l2_slice(bs, offset, nb_clusters, flags);
159
if (cleared < 0) {
160
@@ -XXX,XX +XXX,XX @@ int qcow2_cluster_zeroize(BlockDriverState *bs, uint64_t offset,
161
offset += (cleared * s->cluster_size);
162
}
163
164
+ if (tail) {
165
+ ret = zero_l2_subclusters(bs, end_offset, size_to_subclusters(s, tail));
166
+ if (ret < 0) {
167
+ goto fail;
168
+ }
169
+ }
170
+
171
ret = 0;
172
fail:
173
s->cache_discards = false;
174
diff --git a/block/qcow2.c b/block/qcow2.c
175
index XXXXXXX..XXXXXXX 100644
176
--- a/block/qcow2.c
177
+++ b/block/qcow2.c
178
@@ -XXX,XX +XXX,XX @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
179
/* Encryption works on a sector granularity */
180
bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
181
}
182
- bs->bl.pwrite_zeroes_alignment = s->cluster_size;
183
+ bs->bl.pwrite_zeroes_alignment = s->subcluster_size;
184
bs->bl.pdiscard_alignment = s->cluster_size;
185
}
186
187
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
188
int ret;
189
BDRVQcow2State *s = bs->opaque;
190
191
- uint32_t head = offset % s->cluster_size;
192
- uint32_t tail = (offset + bytes) % s->cluster_size;
193
+ uint32_t head = offset_into_subcluster(s, offset);
194
+ uint32_t tail = ROUND_UP(offset + bytes, s->subcluster_size) -
195
+ (offset + bytes);
196
197
trace_qcow2_pwrite_zeroes_start_req(qemu_coroutine_self(), offset, bytes);
198
if (offset + bytes == bs->total_sectors * BDRV_SECTOR_SIZE) {
199
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
200
unsigned int nr;
201
QCow2SubclusterType type;
202
203
- assert(head + bytes <= s->cluster_size);
204
+ assert(head + bytes + tail <= s->subcluster_size);
205
206
/* check whether remainder of cluster already reads as zero */
207
if (!(is_zero(bs, offset - head, head) &&
208
- is_zero(bs, offset + bytes,
209
- tail ? s->cluster_size - tail : 0))) {
210
+ is_zero(bs, offset + bytes, tail))) {
211
return -ENOTSUP;
212
}
213
214
qemu_co_mutex_lock(&s->lock);
215
/* We can have new write after previous check */
216
- offset = QEMU_ALIGN_DOWN(offset, s->cluster_size);
217
- bytes = s->cluster_size;
218
- nr = s->cluster_size;
219
+ offset -= head;
220
+ bytes = s->subcluster_size;
221
+ nr = s->subcluster_size;
222
ret = qcow2_get_host_offset(bs, offset, &nr, &off, &type);
223
if (ret < 0 ||
224
(type != QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN &&
225
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
226
227
trace_qcow2_pwrite_zeroes(qemu_coroutine_self(), offset, bytes);
228
229
- /* Whatever is left can use real zero clusters */
230
- ret = qcow2_cluster_zeroize(bs, offset, bytes, flags);
231
+ /* Whatever is left can use real zero subclusters */
232
+ ret = qcow2_subcluster_zeroize(bs, offset, bytes, flags);
233
qemu_co_mutex_unlock(&s->lock);
234
235
return ret;
236
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
237
}
238
239
if ((flags & BDRV_REQ_ZERO_WRITE) && offset > old_length) {
240
- uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->cluster_size);
241
+ uint64_t zero_start = QEMU_ALIGN_UP(old_length, s->subcluster_size);
242
243
/*
244
- * Use zero clusters as much as we can. qcow2_cluster_zeroize()
245
- * requires a cluster-aligned start. The end may be unaligned if it is
246
- * at the end of the image (which it is here).
247
+ * Use zero clusters as much as we can. qcow2_subcluster_zeroize()
248
+ * requires a subcluster-aligned start. The end may be unaligned if
249
+ * it is at the end of the image (which it is here).
250
*/
251
if (offset > zero_start) {
252
- ret = qcow2_cluster_zeroize(bs, zero_start, offset - zero_start, 0);
253
+ ret = qcow2_subcluster_zeroize(bs, zero_start, offset - zero_start,
254
+ 0);
255
if (ret < 0) {
256
error_setg_errno(errp, -ret, "Failed to zero out new clusters");
257
goto fail;
258
--
259
2.26.2
260
261
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Extended L2 entries are bigger than normal L2 entries so this has an
4
impact on the amount of metadata needed for a qcow2 file.
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Message-Id: <7efae2efd5e36b42d2570743a12576d68ce53685.1594396418.git.berto@igalia.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
block/qcow2.c | 20 +++++++++++++-------
12
1 file changed, 13 insertions(+), 7 deletions(-)
13
14
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.c
17
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_metadata_size(int64_t clusters, size_t cluster_size,
19
* @total_size: virtual disk size in bytes
20
* @cluster_size: cluster size in bytes
21
* @refcount_order: refcount bits power-of-2 exponent
22
+ * @extended_l2: true if the image has extended L2 entries
23
*
24
* Returns: Total number of bytes required for the fully allocated image
25
* (including metadata).
26
*/
27
static int64_t qcow2_calc_prealloc_size(int64_t total_size,
28
size_t cluster_size,
29
- int refcount_order)
30
+ int refcount_order,
31
+ bool extended_l2)
32
{
33
int64_t meta_size = 0;
34
uint64_t nl1e, nl2e;
35
int64_t aligned_total_size = ROUND_UP(total_size, cluster_size);
36
+ size_t l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
37
38
/* header: 1 cluster */
39
meta_size += cluster_size;
40
41
/* total size of L2 tables */
42
nl2e = aligned_total_size / cluster_size;
43
- nl2e = ROUND_UP(nl2e, cluster_size / sizeof(uint64_t));
44
- meta_size += nl2e * sizeof(uint64_t);
45
+ nl2e = ROUND_UP(nl2e, cluster_size / l2e_size);
46
+ meta_size += nl2e * l2e_size;
47
48
/* total size of L1 tables */
49
- nl1e = nl2e * sizeof(uint64_t) / cluster_size;
50
+ nl1e = nl2e * l2e_size / cluster_size;
51
nl1e = ROUND_UP(nl1e, cluster_size / sizeof(uint64_t));
52
meta_size += nl1e * sizeof(uint64_t);
53
54
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
55
PreallocMode prealloc;
56
bool has_backing_file;
57
bool has_luks;
58
+ bool extended_l2 = false; /* Set to false until the option is added */
59
+ size_t l2e_size;
60
61
/* Parse image creation options */
62
cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
63
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
64
virtual_size = ROUND_UP(virtual_size, cluster_size);
65
66
/* Check that virtual disk size is valid */
67
+ l2e_size = extended_l2 ? L2E_SIZE_EXTENDED : L2E_SIZE_NORMAL;
68
l2_tables = DIV_ROUND_UP(virtual_size / cluster_size,
69
- cluster_size / sizeof(uint64_t));
70
+ cluster_size / l2e_size);
71
if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) {
72
error_setg(&local_err, "The image size is too large "
73
"(try using a larger cluster size)");
74
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
75
}
76
77
info = g_new0(BlockMeasureInfo, 1);
78
- info->fully_allocated =
79
+ info->fully_allocated = luks_payload_size +
80
qcow2_calc_prealloc_size(virtual_size, cluster_size,
81
- ctz32(refcount_bits)) + luks_payload_size;
82
+ ctz32(refcount_bits), extended_l2);
83
84
/*
85
* Remove data clusters that are not required. This overestimates the
86
--
87
2.26.2
88
89
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This field allows us to indicate that the L2 metadata update does not
4
come from a write request with actual data but from a preallocation
5
request.
6
7
For traditional images this does not make any difference, but for
8
images with extended L2 entries this means that the clusters are
9
allocated normally in the L2 table but individual subclusters are
10
marked as unallocated.
11
12
This will allow preallocating images that have a backing file.
13
14
There is one special case: when we resize an existing image we can
15
also request that the new clusters are preallocated. If the image
16
already had a backing file then we have to hide any possible stale
17
data and zero out the new clusters (see commit 955c7d6687 for more
18
details).
19
20
In this case the subclusters cannot be left as unallocated so the L2
21
bitmap must be updated.
22
23
Signed-off-by: Alberto Garcia <berto@igalia.com>
24
Reviewed-by: Eric Blake <eblake@redhat.com>
25
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Message-Id: <960d4c444a4f5a870e2b47e5da322a73cd9a2f5a.1594396418.git.berto@igalia.com>
27
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
---
29
block/qcow2.h | 8 ++++++++
30
block/qcow2-cluster.c | 2 +-
31
block/qcow2.c | 6 ++++++
32
3 files changed, 15 insertions(+), 1 deletion(-)
33
34
diff --git a/block/qcow2.h b/block/qcow2.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/qcow2.h
37
+++ b/block/qcow2.h
38
@@ -XXX,XX +XXX,XX @@ typedef struct QCowL2Meta
39
*/
40
bool skip_cow;
41
42
+ /**
43
+ * Indicates that this is not a normal write request but a preallocation.
44
+ * If the image has extended L2 entries this means that no new individual
45
+ * subclusters will be marked as allocated in the L2 bitmap (but any
46
+ * existing contents of that bitmap will be kept).
47
+ */
48
+ bool prealloc;
49
+
50
/**
51
* The I/O vector with the data from the actual guest write request.
52
* If non-NULL, this is meant to be merged together with the data
53
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/qcow2-cluster.c
56
+++ b/block/qcow2-cluster.c
57
@@ -XXX,XX +XXX,XX @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
58
set_l2_entry(s, l2_slice, l2_index + i, offset | QCOW_OFLAG_COPIED);
59
60
/* Update bitmap with the subclusters that were just written */
61
- if (has_subclusters(s)) {
62
+ if (has_subclusters(s) && !m->prealloc) {
63
uint64_t l2_bitmap = get_l2_bitmap(s, l2_slice, l2_index + i);
64
unsigned written_from = m->cow_start.offset;
65
unsigned written_to = m->cow_end.offset + m->cow_end.nb_bytes ?:
66
diff --git a/block/qcow2.c b/block/qcow2.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/qcow2.c
69
+++ b/block/qcow2.c
70
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_handle_l2meta(BlockDriverState *bs,
71
QCowL2Meta *next;
72
73
if (link_l2) {
74
+ assert(!l2meta->prealloc);
75
ret = qcow2_alloc_cluster_link_l2(bs, l2meta);
76
if (ret) {
77
goto out;
78
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn preallocate_co(BlockDriverState *bs, uint64_t offset,
79
80
while (meta) {
81
QCowL2Meta *next = meta->next;
82
+ meta->prealloc = true;
83
84
ret = qcow2_alloc_cluster_link_l2(bs, meta);
85
if (ret < 0) {
86
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
87
int64_t clusters_allocated;
88
int64_t old_file_size, last_cluster, new_file_size;
89
uint64_t nb_new_data_clusters, nb_new_l2_tables;
90
+ bool subclusters_need_allocation = false;
91
92
/* With a data file, preallocation means just allocating the metadata
93
* and forwarding the truncate request to the data file */
94
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
95
BDRV_REQ_ZERO_WRITE, NULL);
96
if (ret >= 0) {
97
flags &= ~BDRV_REQ_ZERO_WRITE;
98
+ /* Ensure that we read zeroes and not backing file data */
99
+ subclusters_need_allocation = true;
100
}
101
} else {
102
ret = -1;
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
104
.offset = nb_clusters << s->cluster_bits,
105
.nb_bytes = 0,
106
},
107
+ .prealloc = !subclusters_need_allocation,
108
};
109
qemu_co_queue_init(&allocation.dependent_requests);
110
111
--
112
2.26.2
113
114
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Sheepdog's AIOCB are completely internal entities for a group of
3
Now that the implementation of subclusters is complete we can finally
4
requests and do not need dynamic allocation.
4
add the necessary options to create and read images with this feature,
5
which we call "extended L2 entries".
5
6
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Message-id: 20161129113245.32724-4-pbonzini@redhat.com
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Jeff Cody <jcody@redhat.com>
9
Reviewed-by: Max Reitz <mreitz@redhat.com>
10
Message-Id: <6476caaa73216bd05b7bb2d504a20415e1665176.1594396418.git.berto@igalia.com>
11
[mreitz: %s/5\.1/5.2/; fixed 302's and 303's reference output]
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
13
---
10
block/sheepdog.c | 99 ++++++++++++++++++++++----------------------------------
14
qapi/block-core.json | 7 +++
11
1 file changed, 39 insertions(+), 60 deletions(-)
15
block/qcow2.h | 8 ++-
16
include/block/block_int.h | 1 +
17
block/qcow2.c | 66 ++++++++++++++++++--
18
tests/qemu-iotests/031.out | 8 +--
19
tests/qemu-iotests/036.out | 4 +-
20
tests/qemu-iotests/049.out | 102 +++++++++++++++----------------
21
tests/qemu-iotests/060.out | 1 +
22
tests/qemu-iotests/061.out | 20 +++---
23
tests/qemu-iotests/065 | 12 ++--
24
tests/qemu-iotests/082.out | 39 +++++++++---
25
tests/qemu-iotests/085.out | 38 ++++++------
26
tests/qemu-iotests/144.out | 4 +-
27
tests/qemu-iotests/182.out | 2 +-
28
tests/qemu-iotests/185.out | 8 +--
29
tests/qemu-iotests/198 | 2 +
30
tests/qemu-iotests/206.out | 4 ++
31
tests/qemu-iotests/242.out | 5 ++
32
tests/qemu-iotests/255.out | 8 +--
33
tests/qemu-iotests/274.out | 49 ++++++++-------
34
tests/qemu-iotests/280.out | 2 +-
35
tests/qemu-iotests/291.out | 2 +
36
tests/qemu-iotests/302.out | 1 +
37
tests/qemu-iotests/303.out | 4 +-
38
tests/qemu-iotests/common.filter | 1 +
39
25 files changed, 256 insertions(+), 142 deletions(-)
12
40
13
diff --git a/block/sheepdog.c b/block/sheepdog.c
41
diff --git a/qapi/block-core.json b/qapi/block-core.json
14
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
15
--- a/block/sheepdog.c
43
--- a/qapi/block-core.json
16
+++ b/block/sheepdog.c
44
+++ b/qapi/block-core.json
17
@@ -XXX,XX +XXX,XX @@ static inline size_t count_data_objs(const struct SheepdogInode *inode)
45
@@ -XXX,XX +XXX,XX @@
18
} while (0)
46
# standalone (read-only) raw image without looking at qcow2
19
47
# metadata (since: 4.0)
20
typedef struct SheepdogAIOCB SheepdogAIOCB;
48
#
21
+typedef struct BDRVSheepdogState BDRVSheepdogState;
49
+# @extended-l2: true if the image has extended L2 entries; only valid for
22
50
+# compat >= 1.1 (since 5.2)
23
typedef struct AIOReq {
51
+#
24
SheepdogAIOCB *aiocb;
52
# @lazy-refcounts: on or off; only valid for compat >= 1.1
25
@@ -XXX,XX +XXX,XX @@ enum AIOCBState {
53
#
26
|| y->max_affect_data_idx < x->min_affect_data_idx))
54
# @corrupt: true if the image has been marked corrupt; only valid for
27
55
@@ -XXX,XX +XXX,XX @@
28
struct SheepdogAIOCB {
56
'compat': 'str',
29
- BlockAIOCB common;
57
'*data-file': 'str',
30
+ BDRVSheepdogState *s;
58
'*data-file-raw': 'bool',
31
59
+ '*extended-l2': 'bool',
32
QEMUIOVector *qiov;
60
'*lazy-refcounts': 'bool',
33
61
'*corrupt': 'bool',
34
@@ -XXX,XX +XXX,XX @@ struct SheepdogAIOCB {
62
'refcount-bits': 'int',
35
QLIST_ENTRY(SheepdogAIOCB) aiocb_siblings;
63
@@ -XXX,XX +XXX,XX @@
64
# @data-file-raw: True if the external data file must stay valid as a
65
# standalone (read-only) raw image without looking at qcow2
66
# metadata (default: false; since: 4.0)
67
+# @extended-l2 True to make the image have extended L2 entries
68
+# (default: false; since 5.2)
69
# @size: Size of the virtual disk in bytes
70
# @version: Compatibility level (default: v3)
71
# @backing-file: File name of the backing file if a backing file
72
@@ -XXX,XX +XXX,XX @@
73
'data': { 'file': 'BlockdevRef',
74
'*data-file': 'BlockdevRef',
75
'*data-file-raw': 'bool',
76
+ '*extended-l2': 'bool',
77
'size': 'size',
78
'*version': 'BlockdevQcow2Version',
79
'*backing-file': 'str',
80
diff --git a/block/qcow2.h b/block/qcow2.h
81
index XXXXXXX..XXXXXXX 100644
82
--- a/block/qcow2.h
83
+++ b/block/qcow2.h
84
@@ -XXX,XX +XXX,XX @@ enum {
85
QCOW2_INCOMPAT_CORRUPT_BITNR = 1,
86
QCOW2_INCOMPAT_DATA_FILE_BITNR = 2,
87
QCOW2_INCOMPAT_COMPRESSION_BITNR = 3,
88
+ QCOW2_INCOMPAT_EXTL2_BITNR = 4,
89
QCOW2_INCOMPAT_DIRTY = 1 << QCOW2_INCOMPAT_DIRTY_BITNR,
90
QCOW2_INCOMPAT_CORRUPT = 1 << QCOW2_INCOMPAT_CORRUPT_BITNR,
91
QCOW2_INCOMPAT_DATA_FILE = 1 << QCOW2_INCOMPAT_DATA_FILE_BITNR,
92
QCOW2_INCOMPAT_COMPRESSION = 1 << QCOW2_INCOMPAT_COMPRESSION_BITNR,
93
+ QCOW2_INCOMPAT_EXTL2 = 1 << QCOW2_INCOMPAT_EXTL2_BITNR,
94
95
QCOW2_INCOMPAT_MASK = QCOW2_INCOMPAT_DIRTY
96
| QCOW2_INCOMPAT_CORRUPT
97
| QCOW2_INCOMPAT_DATA_FILE
98
- | QCOW2_INCOMPAT_COMPRESSION,
99
+ | QCOW2_INCOMPAT_COMPRESSION
100
+ | QCOW2_INCOMPAT_EXTL2,
36
};
101
};
37
102
38
-typedef struct BDRVSheepdogState {
103
/* Compatible feature bits */
39
+struct BDRVSheepdogState {
104
@@ -XXX,XX +XXX,XX @@ typedef enum QCow2MetadataOverlap {
40
BlockDriverState *bs;
105
41
AioContext *aio_context;
106
static inline bool has_subclusters(BDRVQcow2State *s)
42
107
{
43
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVSheepdogState {
108
- /* FIXME: Return false until this feature is complete */
44
109
- return false;
45
CoQueue overlapping_queue;
110
+ return s->incompatible_features & QCOW2_INCOMPAT_EXTL2;
46
QLIST_HEAD(inflight_aiocb_head, SheepdogAIOCB) inflight_aiocb_head;
47
-} BDRVSheepdogState;
48
+};
49
50
typedef struct BDRVSheepdogReopenState {
51
int fd;
52
@@ -XXX,XX +XXX,XX @@ static inline void free_aio_req(BDRVSheepdogState *s, AIOReq *aio_req)
53
acb->nr_pending--;
54
}
111
}
55
112
56
-static const AIOCBInfo sd_aiocb_info = {
113
static inline size_t l2_entry_size(BDRVQcow2State *s)
57
- .aiocb_size = sizeof(SheepdogAIOCB),
114
diff --git a/include/block/block_int.h b/include/block/block_int.h
58
-};
115
index XXXXXXX..XXXXXXX 100644
59
-
116
--- a/include/block/block_int.h
60
-static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
117
+++ b/include/block/block_int.h
61
- int64_t sector_num, int nb_sectors)
118
@@ -XXX,XX +XXX,XX @@
62
+static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
119
#define BLOCK_OPT_DATA_FILE "data_file"
63
+ QEMUIOVector *qiov, int64_t sector_num, int nb_sectors,
120
#define BLOCK_OPT_DATA_FILE_RAW "data_file_raw"
64
+ int type)
121
#define BLOCK_OPT_COMPRESSION_TYPE "compression_type"
122
+#define BLOCK_OPT_EXTL2 "extended_l2"
123
124
#define BLOCK_PROBE_BUF_SIZE 512
125
126
diff --git a/block/qcow2.c b/block/qcow2.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/block/qcow2.c
129
+++ b/block/qcow2.c
130
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
131
s->subcluster_size = s->cluster_size / s->subclusters_per_cluster;
132
s->subcluster_bits = ctz32(s->subcluster_size);
133
134
+ if (s->subcluster_size < (1 << MIN_CLUSTER_BITS)) {
135
+ error_setg(errp, "Unsupported subcluster size: %d", s->subcluster_size);
136
+ ret = -EINVAL;
137
+ goto fail;
138
+ }
139
+
140
/* Check support for various header values */
141
if (header.refcount_order > 6) {
142
error_setg(errp, "Reference count entry width too large; may not "
143
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
144
.bit = QCOW2_INCOMPAT_COMPRESSION_BITNR,
145
.name = "compression type",
146
},
147
+ {
148
+ .type = QCOW2_FEAT_TYPE_INCOMPATIBLE,
149
+ .bit = QCOW2_INCOMPAT_EXTL2_BITNR,
150
+ .name = "extended L2 entries",
151
+ },
152
{
153
.type = QCOW2_FEAT_TYPE_COMPATIBLE,
154
.bit = QCOW2_COMPAT_LAZY_REFCOUNTS_BITNR,
155
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_calc_prealloc_size(int64_t total_size,
156
return meta_size + aligned_total_size;
157
}
158
159
-static bool validate_cluster_size(size_t cluster_size, Error **errp)
160
+static bool validate_cluster_size(size_t cluster_size, bool extended_l2,
161
+ Error **errp)
65
{
162
{
66
- SheepdogAIOCB *acb;
163
int cluster_bits = ctz32(cluster_size);
67
uint32_t object_size;
164
if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS ||
68
- BDRVSheepdogState *s = bs->opaque;
165
@@ -XXX,XX +XXX,XX @@ static bool validate_cluster_size(size_t cluster_size, Error **errp)
69
166
"%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
70
object_size = (UINT32_C(1) << s->inode.block_size_shift);
167
return false;
71
168
}
72
- acb = qemu_aio_get(&sd_aiocb_info, bs, NULL, NULL);
169
+
73
+ acb->s = s;
170
+ if (extended_l2) {
74
171
+ unsigned min_cluster_size =
75
acb->qiov = qiov;
172
+ (1 << MIN_CLUSTER_BITS) * QCOW_EXTL2_SUBCLUSTERS_PER_CLUSTER;
76
173
+ if (cluster_size < min_cluster_size) {
77
@@ -XXX,XX +XXX,XX @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
174
+ error_setg(errp, "Extended L2 entries are only supported with "
78
175
+ "cluster sizes of at least %u bytes", min_cluster_size);
79
acb->min_dirty_data_idx = UINT32_MAX;
176
+ return false;
80
acb->max_dirty_data_idx = 0;
177
+ }
81
-
178
+ }
82
- return acb;
179
+
83
+ acb->aiocb_type = type;
180
return true;
84
}
181
}
85
182
86
/* Return -EIO in case of error, file descriptor on success */
183
-static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp)
87
@@ -XXX,XX +XXX,XX @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
184
+static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, bool extended_l2,
88
*/
185
+ Error **errp)
89
static void coroutine_fn sd_write_done(SheepdogAIOCB *acb)
90
{
186
{
91
- BDRVSheepdogState *s = acb->common.bs->opaque;
187
size_t cluster_size;
92
+ BDRVSheepdogState *s = acb->s;
188
93
struct iovec iov;
189
cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE,
94
AIOReq *aio_req;
190
DEFAULT_CLUSTER_SIZE);
95
uint32_t offset, data_len, mn, mx;
191
- if (!validate_cluster_size(cluster_size, errp)) {
96
@@ -XXX,XX +XXX,XX @@ out:
192
+ if (!validate_cluster_size(cluster_size, extended_l2, errp)) {
97
* Returns 1 when we need to wait a response, 0 when there is no sent
98
* request and -errno in error cases.
99
*/
100
-static void coroutine_fn sd_co_rw_vector(void *p)
101
+static void coroutine_fn sd_co_rw_vector(SheepdogAIOCB *acb)
102
{
103
- SheepdogAIOCB *acb = p;
104
int ret = 0;
105
unsigned long len, done = 0, total = acb->nb_sectors * BDRV_SECTOR_SIZE;
106
unsigned long idx;
107
uint32_t object_size;
108
uint64_t oid;
109
uint64_t offset;
110
- BDRVSheepdogState *s = acb->common.bs->opaque;
111
+ BDRVSheepdogState *s = acb->s;
112
SheepdogInode *inode = &s->inode;
113
AIOReq *aio_req;
114
115
@@ -XXX,XX +XXX,XX @@ static bool check_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *aiocb)
116
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
117
int nb_sectors, QEMUIOVector *qiov)
118
{
119
- SheepdogAIOCB *acb;
120
+ SheepdogAIOCB acb;
121
int ret;
122
int64_t offset = (sector_num + nb_sectors) * BDRV_SECTOR_SIZE;
123
BDRVSheepdogState *s = bs->opaque;
124
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
125
}
126
}
127
128
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
129
- acb->aiocb_type = AIOCB_WRITE_UDATA;
130
+ sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_WRITE_UDATA);
131
132
retry:
133
- if (check_overlapping_aiocb(s, acb)) {
134
+ if (check_overlapping_aiocb(s, &acb)) {
135
qemu_co_queue_wait(&s->overlapping_queue);
136
goto retry;
137
}
138
139
- sd_co_rw_vector(acb);
140
- sd_write_done(acb);
141
+ sd_co_rw_vector(&acb);
142
+ sd_write_done(&acb);
143
144
- QLIST_REMOVE(acb, aiocb_siblings);
145
+ QLIST_REMOVE(&acb, aiocb_siblings);
146
qemu_co_queue_restart_all(&s->overlapping_queue);
147
- ret = acb->ret;
148
- qemu_aio_unref(acb);
149
- return ret;
150
+ return acb.ret;
151
}
152
153
static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
154
int nb_sectors, QEMUIOVector *qiov)
155
{
156
- SheepdogAIOCB *acb;
157
- int ret;
158
+ SheepdogAIOCB acb;
159
BDRVSheepdogState *s = bs->opaque;
160
161
- acb = sd_aio_setup(bs, qiov, sector_num, nb_sectors);
162
- acb->aiocb_type = AIOCB_READ_UDATA;
163
+ sd_aio_setup(&acb, s, qiov, sector_num, nb_sectors, AIOCB_READ_UDATA);
164
165
retry:
166
- if (check_overlapping_aiocb(s, acb)) {
167
+ if (check_overlapping_aiocb(s, &acb)) {
168
qemu_co_queue_wait(&s->overlapping_queue);
169
goto retry;
170
}
171
172
- sd_co_rw_vector(acb);
173
+ sd_co_rw_vector(&acb);
174
175
- QLIST_REMOVE(acb, aiocb_siblings);
176
+ QLIST_REMOVE(&acb, aiocb_siblings);
177
qemu_co_queue_restart_all(&s->overlapping_queue);
178
- ret = acb->ret;
179
- qemu_aio_unref(acb);
180
- return ret;
181
+ return acb.ret;
182
}
183
184
static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
185
{
186
BDRVSheepdogState *s = bs->opaque;
187
- SheepdogAIOCB *acb;
188
- int ret;
189
+ SheepdogAIOCB acb;
190
AIOReq *aio_req;
191
192
if (s->cache_flags != SD_FLAG_CMD_CACHE) {
193
return 0;
193
return 0;
194
}
194
}
195
195
return cluster_size;
196
- acb = sd_aio_setup(bs, NULL, 0, 0);
196
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
197
- acb->aiocb_type = AIOCB_FLUSH_CACHE;
197
cluster_size = DEFAULT_CLUSTER_SIZE;
198
+ sd_aio_setup(&acb, s, NULL, 0, 0, AIOCB_FLUSH_CACHE);
199
200
- acb->nr_pending++;
201
- aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
202
+ acb.nr_pending++;
203
+ aio_req = alloc_aio_req(s, &acb, vid_to_vdi_oid(s->inode.vdi_id),
204
0, 0, 0, false, 0, 0);
205
QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
206
- add_aio_request(s, aio_req, NULL, 0, acb->aiocb_type);
207
+ add_aio_request(s, aio_req, NULL, 0, acb.aiocb_type);
208
209
- if (--acb->nr_pending) {
210
+ if (--acb.nr_pending) {
211
qemu_coroutine_yield();
212
}
198
}
213
- ret = acb->ret;
199
214
- qemu_aio_unref(acb);
200
- if (!validate_cluster_size(cluster_size, errp)) {
215
- return ret;
201
+ if (!qcow2_opts->has_extended_l2) {
216
+ return acb.ret;
202
+ qcow2_opts->extended_l2 = false;
217
}
203
+ }
218
204
+ if (qcow2_opts->extended_l2) {
219
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
205
+ if (version < 3) {
220
@@ -XXX,XX +XXX,XX @@ static int sd_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
206
+ error_setg(errp, "Extended L2 entries are only supported with "
221
static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
207
+ "compatibility level 1.1 and above (use version=v3 or "
222
int count)
208
+ "greater)");
223
{
209
+ ret = -EINVAL;
224
- SheepdogAIOCB *acb;
210
+ goto out;
225
+ SheepdogAIOCB acb;
211
+ }
226
BDRVSheepdogState *s = bs->opaque;
212
+ }
227
- int ret;
213
+
228
QEMUIOVector discard_iov;
214
+ if (!validate_cluster_size(cluster_size, qcow2_opts->extended_l2, errp)) {
229
struct iovec iov;
215
ret = -EINVAL;
230
uint32_t zero = 0;
216
goto out;
231
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int sd_co_pdiscard(BlockDriverState *bs, int64_t offset,
232
if (!QEMU_IS_ALIGNED(offset | count, BDRV_SECTOR_SIZE)) {
233
return -ENOTSUP;
234
}
217
}
235
- acb = sd_aio_setup(bs, &discard_iov, offset >> BDRV_SECTOR_BITS,
218
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
236
- count >> BDRV_SECTOR_BITS);
219
cpu_to_be64(QCOW2_INCOMPAT_COMPRESSION);
237
- acb->aiocb_type = AIOCB_DISCARD_OBJ;
238
+ sd_aio_setup(&acb, s, &discard_iov, offset >> BDRV_SECTOR_BITS,
239
+ count >> BDRV_SECTOR_BITS, AIOCB_DISCARD_OBJ);
240
241
retry:
242
- if (check_overlapping_aiocb(s, acb)) {
243
+ if (check_overlapping_aiocb(s, &acb)) {
244
qemu_co_queue_wait(&s->overlapping_queue);
245
goto retry;
246
}
220
}
247
221
248
- sd_co_rw_vector(acb);
222
+ if (qcow2_opts->extended_l2) {
249
+ sd_co_rw_vector(&acb);
223
+ header->incompatible_features |=
250
224
+ cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
251
- QLIST_REMOVE(acb, aiocb_siblings);
225
+ }
252
+ QLIST_REMOVE(&acb, aiocb_siblings);
226
+
253
qemu_co_queue_restart_all(&s->overlapping_queue);
227
ret = blk_pwrite(blk, 0, header, cluster_size, 0);
254
- ret = acb->ret;
228
g_free(header);
255
- qemu_aio_unref(acb);
229
if (ret < 0) {
256
- return ret;
230
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_create_opts(BlockDriver *drv,
257
+ return acb.ret;
231
{ BLOCK_OPT_BACKING_FMT, "backing-fmt" },
258
}
232
{ BLOCK_OPT_CLUSTER_SIZE, "cluster-size" },
259
233
{ BLOCK_OPT_LAZY_REFCOUNTS, "lazy-refcounts" },
260
static coroutine_fn int64_t
234
+ { BLOCK_OPT_EXTL2, "extended-l2" },
235
{ BLOCK_OPT_REFCOUNT_BITS, "refcount-bits" },
236
{ BLOCK_OPT_ENCRYPT, BLOCK_OPT_ENCRYPT_FORMAT },
237
{ BLOCK_OPT_COMPAT_LEVEL, "version" },
238
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
239
PreallocMode prealloc;
240
bool has_backing_file;
241
bool has_luks;
242
- bool extended_l2 = false; /* Set to false until the option is added */
243
+ bool extended_l2;
244
size_t l2e_size;
245
246
/* Parse image creation options */
247
- cluster_size = qcow2_opt_get_cluster_size_del(opts, &local_err);
248
+ extended_l2 = qemu_opt_get_bool_del(opts, BLOCK_OPT_EXTL2, false);
249
+
250
+ cluster_size = qcow2_opt_get_cluster_size_del(opts, extended_l2,
251
+ &local_err);
252
if (local_err) {
253
goto err;
254
}
255
@@ -XXX,XX +XXX,XX @@ static ImageInfoSpecific *qcow2_get_specific_info(BlockDriverState *bs,
256
.corrupt = s->incompatible_features &
257
QCOW2_INCOMPAT_CORRUPT,
258
.has_corrupt = true,
259
+ .has_extended_l2 = true,
260
+ .extended_l2 = has_subclusters(s),
261
.refcount_bits = s->refcount_bits,
262
.has_bitmaps = !!bitmaps,
263
.bitmaps = bitmaps,
264
@@ -XXX,XX +XXX,XX @@ static QemuOptsList qcow2_create_opts = {
265
.help = "qcow2 cluster size", \
266
.def_value_str = stringify(DEFAULT_CLUSTER_SIZE) \
267
}, \
268
+ { \
269
+ .name = BLOCK_OPT_EXTL2, \
270
+ .type = QEMU_OPT_BOOL, \
271
+ .help = "Extended L2 tables", \
272
+ .def_value_str = "off" \
273
+ }, \
274
{ \
275
.name = BLOCK_OPT_PREALLOC, \
276
.type = QEMU_OPT_STRING, \
277
diff --git a/tests/qemu-iotests/031.out b/tests/qemu-iotests/031.out
278
index XXXXXXX..XXXXXXX 100644
279
--- a/tests/qemu-iotests/031.out
280
+++ b/tests/qemu-iotests/031.out
281
@@ -XXX,XX +XXX,XX @@ header_length 112
282
283
Header extension:
284
magic 0x6803f857 (Feature table)
285
-length 336
286
+length 384
287
data <binary>
288
289
Header extension:
290
@@ -XXX,XX +XXX,XX @@ header_length 112
291
292
Header extension:
293
magic 0x6803f857 (Feature table)
294
-length 336
295
+length 384
296
data <binary>
297
298
Header extension:
299
@@ -XXX,XX +XXX,XX @@ No errors were found on the image.
300
301
magic 0x514649fb
302
version 3
303
-backing_file_offset 0x210
304
+backing_file_offset 0x240
305
backing_file_size 0x17
306
cluster_bits 16
307
size 67108864
308
@@ -XXX,XX +XXX,XX @@ data 'host_device'
309
310
Header extension:
311
magic 0x6803f857 (Feature table)
312
-length 336
313
+length 384
314
data <binary>
315
316
Header extension:
317
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
318
index XXXXXXX..XXXXXXX 100644
319
--- a/tests/qemu-iotests/036.out
320
+++ b/tests/qemu-iotests/036.out
321
@@ -XXX,XX +XXX,XX @@ compatible_features []
322
autoclear_features [63]
323
Header extension:
324
magic 0x6803f857 (Feature table)
325
-length 336
326
+length 384
327
data <binary>
328
329
330
@@ -XXX,XX +XXX,XX @@ compatible_features []
331
autoclear_features []
332
Header extension:
333
magic 0x6803f857 (Feature table)
334
-length 336
335
+length 384
336
data <binary>
337
338
*** done
339
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
340
index XXXXXXX..XXXXXXX 100644
341
--- a/tests/qemu-iotests/049.out
342
+++ b/tests/qemu-iotests/049.out
343
@@ -XXX,XX +XXX,XX @@ QA output created by 049
344
== 1. Traditional size parameter ==
345
346
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024
347
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
348
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
349
350
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024b
351
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
352
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
353
354
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1k
355
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
356
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
357
358
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1K
359
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
360
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
361
362
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1M
363
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
364
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
365
366
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1G
367
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
368
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
369
370
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1T
371
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
372
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
373
374
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0
375
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
376
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
377
378
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1024.0b
379
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
380
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
381
382
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5k
383
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
384
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
385
386
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5K
387
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
388
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
389
390
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5M
391
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
392
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
393
394
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5G
395
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
396
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
397
398
qemu-img create -f qcow2 TEST_DIR/t.qcow2 1.5T
399
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
400
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
401
402
== 2. Specifying size via -o ==
403
404
qemu-img create -f qcow2 -o size=1024 TEST_DIR/t.qcow2
405
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
406
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
407
408
qemu-img create -f qcow2 -o size=1024b TEST_DIR/t.qcow2
409
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
410
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
411
412
qemu-img create -f qcow2 -o size=1k TEST_DIR/t.qcow2
413
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
414
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
415
416
qemu-img create -f qcow2 -o size=1K TEST_DIR/t.qcow2
417
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
418
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
419
420
qemu-img create -f qcow2 -o size=1M TEST_DIR/t.qcow2
421
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
422
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 lazy_refcounts=off refcount_bits=16
423
424
qemu-img create -f qcow2 -o size=1G TEST_DIR/t.qcow2
425
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
426
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 lazy_refcounts=off refcount_bits=16
427
428
qemu-img create -f qcow2 -o size=1T TEST_DIR/t.qcow2
429
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
430
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1099511627776 lazy_refcounts=off refcount_bits=16
431
432
qemu-img create -f qcow2 -o size=1024.0 TEST_DIR/t.qcow2
433
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
434
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
435
436
qemu-img create -f qcow2 -o size=1024.0b TEST_DIR/t.qcow2
437
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
438
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1024 lazy_refcounts=off refcount_bits=16
439
440
qemu-img create -f qcow2 -o size=1.5k TEST_DIR/t.qcow2
441
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
442
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
443
444
qemu-img create -f qcow2 -o size=1.5K TEST_DIR/t.qcow2
445
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
446
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1536 lazy_refcounts=off refcount_bits=16
447
448
qemu-img create -f qcow2 -o size=1.5M TEST_DIR/t.qcow2
449
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
450
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1572864 lazy_refcounts=off refcount_bits=16
451
452
qemu-img create -f qcow2 -o size=1.5G TEST_DIR/t.qcow2
453
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
454
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1610612736 lazy_refcounts=off refcount_bits=16
455
456
qemu-img create -f qcow2 -o size=1.5T TEST_DIR/t.qcow2
457
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
458
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1649267441664 lazy_refcounts=off refcount_bits=16
459
460
== 3. Invalid sizes ==
461
462
@@ -XXX,XX +XXX,XX @@ qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once
463
== Check correct interpretation of suffixes for cluster size ==
464
465
qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
466
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
467
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
468
469
qemu-img create -f qcow2 -o cluster_size=1024b TEST_DIR/t.qcow2 64M
470
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
471
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
472
473
qemu-img create -f qcow2 -o cluster_size=1k TEST_DIR/t.qcow2 64M
474
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
475
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
476
477
qemu-img create -f qcow2 -o cluster_size=1K TEST_DIR/t.qcow2 64M
478
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
479
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
480
481
qemu-img create -f qcow2 -o cluster_size=1M TEST_DIR/t.qcow2 64M
482
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
483
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1048576 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
484
485
qemu-img create -f qcow2 -o cluster_size=1024.0 TEST_DIR/t.qcow2 64M
486
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
487
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
488
489
qemu-img create -f qcow2 -o cluster_size=1024.0b TEST_DIR/t.qcow2 64M
490
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
491
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=1024 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
492
493
qemu-img create -f qcow2 -o cluster_size=0.5k TEST_DIR/t.qcow2 64M
494
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
495
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
496
497
qemu-img create -f qcow2 -o cluster_size=0.5K TEST_DIR/t.qcow2 64M
498
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
499
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=512 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
500
501
qemu-img create -f qcow2 -o cluster_size=0.5M TEST_DIR/t.qcow2 64M
502
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
503
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=524288 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
504
505
== Check compat level option ==
506
507
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
508
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
509
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
510
511
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
512
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
513
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
514
515
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
516
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
517
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.42 lazy_refcounts=off refcount_bits=16
518
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '0.42'
519
520
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
521
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
522
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=foobar lazy_refcounts=off refcount_bits=16
523
qemu-img: TEST_DIR/t.qcow2: Invalid parameter 'foobar'
524
525
== Check preallocation option ==
526
527
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
528
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
529
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
530
531
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
532
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
533
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=metadata compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
534
535
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
536
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
537
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off preallocation=1234 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
538
qemu-img: TEST_DIR/t.qcow2: Invalid parameter '1234'
539
540
== Check encryption option ==
541
542
qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
543
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
544
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=off cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
545
546
qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o encryption=on,encrypt.key-secret=sec0 TEST_DIR/t.qcow2 64M
547
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
548
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 encryption=on encrypt.key-secret=sec0 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
549
550
== Check lazy_refcounts option (only with v3) ==
551
552
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
553
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
554
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=off refcount_bits=16
555
556
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
557
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16
558
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=1.1 lazy_refcounts=on refcount_bits=16
559
560
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
561
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
562
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=off refcount_bits=16
563
564
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
565
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
566
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 compat=0.10 lazy_refcounts=on refcount_bits=16
567
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
568
569
*** done
570
diff --git a/tests/qemu-iotests/060.out b/tests/qemu-iotests/060.out
571
index XXXXXXX..XXXXXXX 100644
572
--- a/tests/qemu-iotests/060.out
573
+++ b/tests/qemu-iotests/060.out
574
@@ -XXX,XX +XXX,XX @@ Format specific information:
575
lazy refcounts: false
576
refcount bits: 16
577
corrupt: true
578
+ extended l2: false
579
qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
580
no file open, try 'help open'
581
read 512/512 bytes at offset 0
582
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
583
index XXXXXXX..XXXXXXX 100644
584
--- a/tests/qemu-iotests/061.out
585
+++ b/tests/qemu-iotests/061.out
586
@@ -XXX,XX +XXX,XX @@ header_length 112
587
588
Header extension:
589
magic 0x6803f857 (Feature table)
590
-length 336
591
+length 384
592
data <binary>
593
594
magic 0x514649fb
595
@@ -XXX,XX +XXX,XX @@ header_length 112
596
597
Header extension:
598
magic 0x6803f857 (Feature table)
599
-length 336
600
+length 384
601
data <binary>
602
603
magic 0x514649fb
604
@@ -XXX,XX +XXX,XX @@ header_length 112
605
606
Header extension:
607
magic 0x6803f857 (Feature table)
608
-length 336
609
+length 384
610
data <binary>
611
612
ERROR cluster 5 refcount=0 reference=1
613
@@ -XXX,XX +XXX,XX @@ header_length 112
614
615
Header extension:
616
magic 0x6803f857 (Feature table)
617
-length 336
618
+length 384
619
data <binary>
620
621
magic 0x514649fb
622
@@ -XXX,XX +XXX,XX @@ header_length 112
623
624
Header extension:
625
magic 0x6803f857 (Feature table)
626
-length 336
627
+length 384
628
data <binary>
629
630
read 65536/65536 bytes at offset 44040192
631
@@ -XXX,XX +XXX,XX @@ header_length 112
632
633
Header extension:
634
magic 0x6803f857 (Feature table)
635
-length 336
636
+length 384
637
data <binary>
638
639
ERROR cluster 5 refcount=0 reference=1
640
@@ -XXX,XX +XXX,XX @@ header_length 112
641
642
Header extension:
643
magic 0x6803f857 (Feature table)
644
-length 336
645
+length 384
646
data <binary>
647
648
read 131072/131072 bytes at offset 0
649
@@ -XXX,XX +XXX,XX @@ Format specific information:
650
data file: TEST_DIR/t.IMGFMT.data
651
data file raw: false
652
corrupt: false
653
+ extended l2: false
654
No errors were found on the image.
655
656
=== Try changing the external data file ===
657
@@ -XXX,XX +XXX,XX @@ Format specific information:
658
data file: foo
659
data file raw: false
660
corrupt: false
661
+ extended l2: false
662
663
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
664
image: TEST_DIR/t.IMGFMT
665
@@ -XXX,XX +XXX,XX @@ Format specific information:
666
refcount bits: 16
667
data file raw: false
668
corrupt: false
669
+ extended l2: false
670
671
=== Clearing and setting data-file-raw ===
672
673
@@ -XXX,XX +XXX,XX @@ Format specific information:
674
data file: TEST_DIR/t.IMGFMT.data
675
data file raw: true
676
corrupt: false
677
+ extended l2: false
678
No errors were found on the image.
679
image: TEST_DIR/t.IMGFMT
680
file format: IMGFMT
681
@@ -XXX,XX +XXX,XX @@ Format specific information:
682
data file: TEST_DIR/t.IMGFMT.data
683
data file raw: false
684
corrupt: false
685
+ extended l2: false
686
No errors were found on the image.
687
qemu-img: data-file-raw cannot be set on existing images
688
image: TEST_DIR/t.IMGFMT
689
@@ -XXX,XX +XXX,XX @@ Format specific information:
690
data file: TEST_DIR/t.IMGFMT.data
691
data file raw: false
692
corrupt: false
693
+ extended l2: false
694
No errors were found on the image.
695
*** done
696
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
697
index XXXXXXX..XXXXXXX 100755
698
--- a/tests/qemu-iotests/065
699
+++ b/tests/qemu-iotests/065
700
@@ -XXX,XX +XXX,XX @@ class TestQCow3NotLazy(TestQemuImgInfo):
701
img_options = 'compat=1.1,lazy_refcounts=off'
702
json_compare = { 'compat': '1.1', 'lazy-refcounts': False,
703
'refcount-bits': 16, 'corrupt': False,
704
- 'compression-type': 'zlib' }
705
+ 'compression-type': 'zlib', 'extended-l2': False }
706
human_compare = [ 'compat: 1.1', 'compression type: zlib',
707
'lazy refcounts: false', 'refcount bits: 16',
708
- 'corrupt: false' ]
709
+ 'corrupt: false', 'extended l2: false' ]
710
711
class TestQCow3Lazy(TestQemuImgInfo):
712
'''Testing a qcow2 version 3 image with lazy refcounts enabled'''
713
img_options = 'compat=1.1,lazy_refcounts=on'
714
json_compare = { 'compat': '1.1', 'lazy-refcounts': True,
715
'refcount-bits': 16, 'corrupt': False,
716
- 'compression-type': 'zlib' }
717
+ 'compression-type': 'zlib', 'extended-l2': False }
718
human_compare = [ 'compat: 1.1', 'compression type: zlib',
719
'lazy refcounts: true', 'refcount bits: 16',
720
- 'corrupt: false' ]
721
+ 'corrupt: false', 'extended l2: false' ]
722
723
class TestQCow3NotLazyQMP(TestQMP):
724
'''Testing a qcow2 version 3 image with lazy refcounts disabled, opening
725
@@ -XXX,XX +XXX,XX @@ class TestQCow3NotLazyQMP(TestQMP):
726
qemu_options = 'lazy-refcounts=on'
727
compare = { 'compat': '1.1', 'lazy-refcounts': False,
728
'refcount-bits': 16, 'corrupt': False,
729
- 'compression-type': 'zlib' }
730
+ 'compression-type': 'zlib', 'extended-l2': False }
731
732
733
class TestQCow3LazyQMP(TestQMP):
734
@@ -XXX,XX +XXX,XX @@ class TestQCow3LazyQMP(TestQMP):
735
qemu_options = 'lazy-refcounts=off'
736
compare = { 'compat': '1.1', 'lazy-refcounts': True,
737
'refcount-bits': 16, 'corrupt': False,
738
- 'compression-type': 'zlib' }
739
+ 'compression-type': 'zlib', 'extended-l2': False }
740
741
TestImageInfoSpecific = None
742
TestQemuImgInfo = None
743
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
744
index XXXXXXX..XXXXXXX 100644
745
--- a/tests/qemu-iotests/082.out
746
+++ b/tests/qemu-iotests/082.out
747
@@ -XXX,XX +XXX,XX @@ QA output created by 082
748
=== create: Options specified more than once ===
749
750
Testing: create -f foo -f qcow2 TEST_DIR/t.qcow2 128M
751
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
752
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
753
image: TEST_DIR/t.IMGFMT
754
file format: IMGFMT
755
virtual size: 128 MiB (134217728 bytes)
756
cluster_size: 65536
757
758
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on TEST_DIR/t.qcow2 128M
759
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=4096 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
760
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=4096 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
761
image: TEST_DIR/t.IMGFMT
762
file format: IMGFMT
763
virtual size: 128 MiB (134217728 bytes)
764
@@ -XXX,XX +XXX,XX @@ Format specific information:
765
lazy refcounts: true
766
refcount bits: 16
767
corrupt: false
768
+ extended l2: false
769
770
Testing: create -f qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 128M
771
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
772
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=on refcount_bits=16
773
image: TEST_DIR/t.IMGFMT
774
file format: IMGFMT
775
virtual size: 128 MiB (134217728 bytes)
776
@@ -XXX,XX +XXX,XX @@ Format specific information:
777
lazy refcounts: true
778
refcount bits: 16
779
corrupt: false
780
+ extended l2: false
781
782
Testing: create -f qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 128M
783
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
784
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=8192 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
785
image: TEST_DIR/t.IMGFMT
786
file format: IMGFMT
787
virtual size: 128 MiB (134217728 bytes)
788
@@ -XXX,XX +XXX,XX @@ Supported options:
789
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
790
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
791
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
792
+ extended_l2=<bool (on/off)> - Extended L2 tables
793
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
794
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
795
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
796
@@ -XXX,XX +XXX,XX @@ Supported options:
797
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
798
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
799
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
800
+ extended_l2=<bool (on/off)> - Extended L2 tables
801
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
802
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
803
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
804
@@ -XXX,XX +XXX,XX @@ Supported options:
805
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
806
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
807
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
808
+ extended_l2=<bool (on/off)> - Extended L2 tables
809
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
810
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
811
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
812
@@ -XXX,XX +XXX,XX @@ Supported options:
813
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
814
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
815
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
816
+ extended_l2=<bool (on/off)> - Extended L2 tables
817
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
818
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
819
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
820
@@ -XXX,XX +XXX,XX @@ Supported options:
821
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
822
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
823
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
824
+ extended_l2=<bool (on/off)> - Extended L2 tables
825
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
826
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
827
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
828
@@ -XXX,XX +XXX,XX @@ Supported options:
829
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
830
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
831
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
832
+ extended_l2=<bool (on/off)> - Extended L2 tables
833
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
834
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
835
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
836
@@ -XXX,XX +XXX,XX @@ Supported options:
837
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
838
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
839
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
840
+ extended_l2=<bool (on/off)> - Extended L2 tables
841
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
842
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
843
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
844
@@ -XXX,XX +XXX,XX @@ Supported options:
845
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
846
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
847
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
848
+ extended_l2=<bool (on/off)> - Extended L2 tables
849
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
850
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
851
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
852
@@ -XXX,XX +XXX,XX @@ Supported options:
853
size=<size> - Virtual disk size
854
855
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,help -F qcow2 TEST_DIR/t.qcow2 128M
856
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
857
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,help backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
858
859
Testing: create -f qcow2 -u -o backing_file=TEST_DIR/t.qcow2,,? -F qcow2 TEST_DIR/t.qcow2 128M
860
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
861
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2,,? backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
862
863
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
864
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
865
@@ -XXX,XX +XXX,XX @@ Supported qcow2 options:
866
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
867
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
868
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
869
+ extended_l2=<bool (on/off)> - Extended L2 tables
870
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
871
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
872
refcount_bits=<num> - Width of a reference count entry in bits
873
@@ -XXX,XX +XXX,XX @@ qemu-img: Format driver 'bochs' does not support image creation
874
=== convert: Options specified more than once ===
875
876
Testing: create -f qcow2 TEST_DIR/t.qcow2 128M
877
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
878
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
879
880
Testing: convert -f foo -f qcow2 TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
881
image: TEST_DIR/t.IMGFMT.base
882
@@ -XXX,XX +XXX,XX @@ Format specific information:
883
lazy refcounts: true
884
refcount bits: 16
885
corrupt: false
886
+ extended l2: false
887
888
Testing: convert -O qcow2 -o cluster_size=4k -o lazy_refcounts=on -o cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
889
image: TEST_DIR/t.IMGFMT.base
890
@@ -XXX,XX +XXX,XX @@ Format specific information:
891
lazy refcounts: true
892
refcount bits: 16
893
corrupt: false
894
+ extended l2: false
895
896
Testing: convert -O qcow2 -o cluster_size=4k,cluster_size=8k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
897
image: TEST_DIR/t.IMGFMT.base
898
@@ -XXX,XX +XXX,XX @@ Supported options:
899
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
900
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
901
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
902
+ extended_l2=<bool (on/off)> - Extended L2 tables
903
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
904
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
905
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
906
@@ -XXX,XX +XXX,XX @@ Supported options:
907
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
908
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
909
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
910
+ extended_l2=<bool (on/off)> - Extended L2 tables
911
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
912
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
913
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
914
@@ -XXX,XX +XXX,XX @@ Supported options:
915
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
916
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
917
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
918
+ extended_l2=<bool (on/off)> - Extended L2 tables
919
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
920
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
921
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
922
@@ -XXX,XX +XXX,XX @@ Supported options:
923
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
924
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
925
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
926
+ extended_l2=<bool (on/off)> - Extended L2 tables
927
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
928
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
929
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
930
@@ -XXX,XX +XXX,XX @@ Supported options:
931
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
932
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
933
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
934
+ extended_l2=<bool (on/off)> - Extended L2 tables
935
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
936
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
937
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
938
@@ -XXX,XX +XXX,XX @@ Supported options:
939
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
940
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
941
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
942
+ extended_l2=<bool (on/off)> - Extended L2 tables
943
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
944
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
945
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
946
@@ -XXX,XX +XXX,XX @@ Supported options:
947
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
948
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
949
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
950
+ extended_l2=<bool (on/off)> - Extended L2 tables
951
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
952
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
953
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
954
@@ -XXX,XX +XXX,XX @@ Supported options:
955
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
956
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
957
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
958
+ extended_l2=<bool (on/off)> - Extended L2 tables
959
extent_size_hint=<size> - Extent size hint for the image file, 0 to disable
960
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
961
nocow=<bool (on/off)> - Turn off copy-on-write (valid only on btrfs)
962
@@ -XXX,XX +XXX,XX @@ Supported qcow2 options:
963
encrypt.ivgen-hash-alg=<str> - Name of IV generator hash algorithm
964
encrypt.key-secret=<str> - ID of secret providing qcow AES key or LUKS passphrase
965
encryption=<bool (on/off)> - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes)
966
+ extended_l2=<bool (on/off)> - Extended L2 tables
967
lazy_refcounts=<bool (on/off)> - Postpone refcount updates
968
preallocation=<str> - Preallocation mode (allowed values: off, metadata, falloc, full)
969
refcount_bits=<num> - Width of a reference count entry in bits
970
@@ -XXX,XX +XXX,XX @@ Format specific information:
971
lazy refcounts: true
972
refcount bits: 16
973
corrupt: false
974
+ extended l2: false
975
976
Testing: amend -f qcow2 -o size=130M -o lazy_refcounts=off TEST_DIR/t.qcow2
977
image: TEST_DIR/t.IMGFMT
978
@@ -XXX,XX +XXX,XX @@ Format specific information:
979
lazy refcounts: false
980
refcount bits: 16
981
corrupt: false
982
+ extended l2: false
983
984
Testing: amend -f qcow2 -o size=8M -o lazy_refcounts=on -o size=132M TEST_DIR/t.qcow2
985
image: TEST_DIR/t.IMGFMT
986
@@ -XXX,XX +XXX,XX @@ Format specific information:
987
lazy refcounts: true
988
refcount bits: 16
989
corrupt: false
990
+ extended l2: false
991
992
Testing: amend -f qcow2 -o size=4M,size=148M TEST_DIR/t.qcow2
993
image: TEST_DIR/t.IMGFMT
994
diff --git a/tests/qemu-iotests/085.out b/tests/qemu-iotests/085.out
995
index XXXXXXX..XXXXXXX 100644
996
--- a/tests/qemu-iotests/085.out
997
+++ b/tests/qemu-iotests/085.out
998
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=134217728
999
=== Create a single snapshot on virtio0 ===
1000
1001
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/1-snapshot-v0.IMGFMT', 'format': 'IMGFMT' } }
1002
-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1003
+Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1004
{"return": {}}
1005
1006
=== Invalid command - missing device and nodename ===
1007
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compress
1008
=== Create several transactional group snapshots ===
1009
1010
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/2-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/2-snapshot-v1.IMGFMT' } } ] } }
1011
-Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1012
-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1013
+Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1014
+Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1015
{"return": {}}
1016
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/3-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/3-snapshot-v1.IMGFMT' } } ] } }
1017
-Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1018
-Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1019
+Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1020
+Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1021
{"return": {}}
1022
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/4-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/4-snapshot-v1.IMGFMT' } } ] } }
1023
-Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1024
-Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1025
+Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1026
+Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1027
{"return": {}}
1028
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/5-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/5-snapshot-v1.IMGFMT' } } ] } }
1029
-Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1030
-Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1031
+Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1032
+Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1033
{"return": {}}
1034
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/6-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/6-snapshot-v1.IMGFMT' } } ] } }
1035
-Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1036
-Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1037
+Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1038
+Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1039
{"return": {}}
1040
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/7-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/7-snapshot-v1.IMGFMT' } } ] } }
1041
-Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1042
-Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1043
+Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1044
+Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1045
{"return": {}}
1046
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/8-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/8-snapshot-v1.IMGFMT' } } ] } }
1047
-Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1048
-Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1049
+Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1050
+Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1051
{"return": {}}
1052
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/9-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/9-snapshot-v1.IMGFMT' } } ] } }
1053
-Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1054
-Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1055
+Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1056
+Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1057
{"return": {}}
1058
{ 'execute': 'transaction', 'arguments': {'actions': [ { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio0', 'snapshot-file': 'TEST_DIR/10-snapshot-v0.IMGFMT' } }, { 'type': 'blockdev-snapshot-sync', 'data' : { 'device': 'virtio1', 'snapshot-file': 'TEST_DIR/10-snapshot-v1.IMGFMT' } } ] } }
1059
-Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1060
-Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1061
+Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1062
+Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1063
{"return": {}}
1064
1065
=== Create a couple of snapshots using blockdev-snapshot ===
1066
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
1067
index XXXXXXX..XXXXXXX 100644
1068
--- a/tests/qemu-iotests/144.out
1069
+++ b/tests/qemu-iotests/144.out
1070
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
1071
{ 'execute': 'qmp_capabilities' }
1072
{"return": {}}
1073
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp.IMGFMT', 'format': 'IMGFMT' } }
1074
-Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1075
+Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1076
{"return": {}}
1077
1078
=== Performing block-commit on active layer ===
1079
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 compression_type=z
1080
=== Performing Live Snapshot 2 ===
1081
1082
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'virtio0', 'snapshot-file':'TEST_DIR/tmp2.IMGFMT', 'format': 'IMGFMT' } }
1083
-Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1084
+Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1085
{"return": {}}
1086
*** done
1087
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
1088
index XXXXXXX..XXXXXXX 100644
1089
--- a/tests/qemu-iotests/182.out
1090
+++ b/tests/qemu-iotests/182.out
1091
@@ -XXX,XX +XXX,XX @@ Is another process using the image [TEST_DIR/t.qcow2]?
1092
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node0', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
1093
{"return": {}}
1094
{'execute': 'blockdev-snapshot-sync', 'arguments': { 'node-name': 'node0', 'snapshot-file': 'TEST_DIR/t.IMGFMT.overlay', 'snapshot-node-name': 'node1' } }
1095
-Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
1096
+Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file lazy_refcounts=off refcount_bits=16
1097
{"return": {}}
1098
{'execute': 'blockdev-add', 'arguments': { 'node-name': 'node1', 'driver': 'file', 'filename': 'TEST_DIR/t.IMGFMT', 'locking': 'on' } }
1099
{"return": {}}
1100
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
1101
index XXXXXXX..XXXXXXX 100644
1102
--- a/tests/qemu-iotests/185.out
1103
+++ b/tests/qemu-iotests/185.out
1104
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
1105
=== Creating backing chain ===
1106
1107
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT.mid', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
1108
-Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1109
+Formatting 'TEST_DIR/t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1110
{"return": {}}
1111
{ 'execute': 'human-monitor-command', 'arguments': { 'command-line': 'qemu-io disk "write 0 4M"' } }
1112
wrote 4194304/4194304 bytes at offset 0
1113
4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1114
{"return": ""}
1115
{ 'execute': 'blockdev-snapshot-sync', 'arguments': { 'device': 'disk', 'snapshot-file': 'TEST_DIR/t.IMGFMT', 'format': 'IMGFMT', 'mode': 'absolute-paths' } }
1116
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1117
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 backing_file=TEST_DIR/t.qcow2.mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1118
{"return": {}}
1119
1120
=== Start commit job and exit qemu ===
1121
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zli
1122
{ 'execute': 'qmp_capabilities' }
1123
{"return": {}}
1124
{ 'execute': 'drive-mirror', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
1125
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1126
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1127
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1128
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1129
{"return": {}}
1130
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_typ
1131
{ 'execute': 'qmp_capabilities' }
1132
{"return": {}}
1133
{ 'execute': 'drive-backup', 'arguments': { 'device': 'disk', 'target': 'TEST_DIR/t.IMGFMT.copy', 'format': 'IMGFMT', 'sync': 'full', 'speed': 65536 } }
1134
-Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1135
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1136
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
1137
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
1138
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
1139
diff --git a/tests/qemu-iotests/198 b/tests/qemu-iotests/198
1140
index XXXXXXX..XXXXXXX 100755
1141
--- a/tests/qemu-iotests/198
1142
+++ b/tests/qemu-iotests/198
1143
@@ -XXX,XX +XXX,XX @@ echo "== checking image base =="
1144
$QEMU_IMG info --image-opts $IMGSPECBASE | _filter_img_info --format-specific \
1145
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
1146
-e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
1147
+ -e '/extended l2:/ D' \
1148
| _filter_json_filename
1149
1150
echo
1151
@@ -XXX,XX +XXX,XX @@ echo "== checking image layer =="
1152
$QEMU_IMG info --image-opts $IMGSPECLAYER | _filter_img_info --format-specific \
1153
| sed -e "/^disk size:/ D" -e '/refcount bits:/ D' -e '/compat:/ D' \
1154
-e '/lazy refcounts:/ D' -e '/corrupt:/ D' -e '/^\s*data file/ D' \
1155
+ -e '/extended l2:/ D' \
1156
| _filter_json_filename
1157
1158
1159
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
1160
index XXXXXXX..XXXXXXX 100644
1161
--- a/tests/qemu-iotests/206.out
1162
+++ b/tests/qemu-iotests/206.out
1163
@@ -XXX,XX +XXX,XX @@ Format specific information:
1164
lazy refcounts: false
1165
refcount bits: 16
1166
corrupt: false
1167
+ extended l2: false
1168
1169
=== Successful image creation (inline blockdev-add, explicit defaults) ===
1170
1171
@@ -XXX,XX +XXX,XX @@ Format specific information:
1172
lazy refcounts: false
1173
refcount bits: 16
1174
corrupt: false
1175
+ extended l2: false
1176
1177
=== Successful image creation (v3 non-default options) ===
1178
1179
@@ -XXX,XX +XXX,XX @@ Format specific information:
1180
lazy refcounts: true
1181
refcount bits: 1
1182
corrupt: false
1183
+ extended l2: false
1184
1185
=== Successful image creation (v2 non-default options) ===
1186
1187
@@ -XXX,XX +XXX,XX @@ Format specific information:
1188
payload offset: 528384
1189
master key iters: XXX
1190
corrupt: false
1191
+ extended l2: false
1192
1193
=== Invalid BlockdevRef ===
1194
1195
diff --git a/tests/qemu-iotests/242.out b/tests/qemu-iotests/242.out
1196
index XXXXXXX..XXXXXXX 100644
1197
--- a/tests/qemu-iotests/242.out
1198
+++ b/tests/qemu-iotests/242.out
1199
@@ -XXX,XX +XXX,XX @@ Format specific information:
1200
lazy refcounts: false
1201
refcount bits: 16
1202
corrupt: false
1203
+ extended l2: false
1204
1205
No bitmap in JSON format output
1206
1207
@@ -XXX,XX +XXX,XX @@ Format specific information:
1208
granularity: 32768
1209
refcount bits: 16
1210
corrupt: false
1211
+ extended l2: false
1212
1213
The same bitmaps in JSON format:
1214
[
1215
@@ -XXX,XX +XXX,XX @@ Format specific information:
1216
granularity: 65536
1217
refcount bits: 16
1218
corrupt: false
1219
+ extended l2: false
1220
1221
The same bitmaps in JSON format:
1222
[
1223
@@ -XXX,XX +XXX,XX @@ Format specific information:
1224
granularity: 65536
1225
refcount bits: 16
1226
corrupt: false
1227
+ extended l2: false
1228
1229
The same bitmaps in JSON format:
1230
[
1231
@@ -XXX,XX +XXX,XX @@ Format specific information:
1232
granularity: 16384
1233
refcount bits: 16
1234
corrupt: false
1235
+ extended l2: false
1236
1237
Test complete
1238
diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out
1239
index XXXXXXX..XXXXXXX 100644
1240
--- a/tests/qemu-iotests/255.out
1241
+++ b/tests/qemu-iotests/255.out
1242
@@ -XXX,XX +XXX,XX @@ Finishing a commit job with background reads
1243
1244
=== Create backing chain and start VM ===
1245
1246
-Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1247
+Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1248
1249
-Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1250
+Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1251
1252
=== Start background read requests ===
1253
1254
@@ -XXX,XX +XXX,XX @@ Closing the VM while a job is being cancelled
1255
1256
=== Create images and start VM ===
1257
1258
-Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1259
+Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1260
1261
-Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 cluster_size=65536 compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1262
+Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=134217728 lazy_refcounts=off refcount_bits=16
1263
1264
wrote 1048576/1048576 bytes at offset 0
1265
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1266
diff --git a/tests/qemu-iotests/274.out b/tests/qemu-iotests/274.out
1267
index XXXXXXX..XXXXXXX 100644
1268
--- a/tests/qemu-iotests/274.out
1269
+++ b/tests/qemu-iotests/274.out
1270
@@ -XXX,XX +XXX,XX @@
1271
== Commit tests ==
1272
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1273
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1274
1275
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1276
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1277
1278
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1279
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1280
1281
wrote 2097152/2097152 bytes at offset 0
1282
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1283
@@ -XXX,XX +XXX,XX @@ Format specific information:
1284
lazy refcounts: false
1285
refcount bits: 16
1286
corrupt: false
1287
+ extended l2: false
1288
1289
read 1048576/1048576 bytes at offset 0
1290
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1291
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
1292
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1293
1294
=== Testing HMP commit (top -> mid) ===
1295
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1296
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1297
1298
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1299
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1300
1301
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1302
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1303
1304
wrote 2097152/2097152 bytes at offset 0
1305
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1306
@@ -XXX,XX +XXX,XX @@ Format specific information:
1307
lazy refcounts: false
1308
refcount bits: 16
1309
corrupt: false
1310
+ extended l2: false
1311
1312
read 1048576/1048576 bytes at offset 0
1313
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1314
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
1315
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1316
1317
=== Testing QMP active commit (top -> mid) ===
1318
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1319
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 lazy_refcounts=off refcount_bits=16
1320
1321
-Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1322
+Formatting 'TEST_DIR/PID-mid', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1048576 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1323
1324
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1325
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=2097152 backing_file=TEST_DIR/PID-mid backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1326
1327
wrote 2097152/2097152 bytes at offset 0
1328
2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1329
@@ -XXX,XX +XXX,XX @@ Format specific information:
1330
lazy refcounts: false
1331
refcount bits: 16
1332
corrupt: false
1333
+ extended l2: false
1334
1335
read 1048576/1048576 bytes at offset 0
1336
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1337
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 1048576
1338
1339
== Resize tests ==
1340
=== preallocation=off ===
1341
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16
1342
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=6442450944 lazy_refcounts=off refcount_bits=16
1343
1344
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1345
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=1073741824 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1346
1347
wrote 65536/65536 bytes at offset 5368709120
1348
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1349
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 5368709120
1350
{ "start": 1073741824, "length": 7516192768, "depth": 0, "zero": true, "data": false}]
1351
1352
=== preallocation=metadata ===
1353
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16
1354
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=34359738368 lazy_refcounts=off refcount_bits=16
1355
1356
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1357
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=32212254720 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1358
1359
wrote 65536/65536 bytes at offset 33285996544
1360
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1361
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 33285996544
1362
{ "start": 34896609280, "length": 536870912, "depth": 0, "zero": true, "data": false, "offset": 2685075456}]
1363
1364
=== preallocation=falloc ===
1365
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16
1366
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=10485760 lazy_refcounts=off refcount_bits=16
1367
1368
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1369
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=5242880 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1370
1371
wrote 65536/65536 bytes at offset 9437184
1372
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1373
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 9437184
1374
{ "start": 5242880, "length": 10485760, "depth": 0, "zero": false, "data": true, "offset": 327680}]
1375
1376
=== preallocation=full ===
1377
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16
1378
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=16777216 lazy_refcounts=off refcount_bits=16
1379
1380
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1381
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=8388608 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1382
1383
wrote 65536/65536 bytes at offset 11534336
1384
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1385
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 11534336
1386
{ "start": 8388608, "length": 4194304, "depth": 0, "zero": false, "data": true, "offset": 327680}]
1387
1388
=== preallocation=off ===
1389
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16
1390
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=393216 lazy_refcounts=off refcount_bits=16
1391
1392
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1393
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=259072 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1394
1395
wrote 65536/65536 bytes at offset 259072
1396
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1397
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 259072
1398
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
1399
1400
=== preallocation=off ===
1401
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16
1402
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=409600 lazy_refcounts=off refcount_bits=16
1403
1404
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1405
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1406
1407
wrote 65536/65536 bytes at offset 344064
1408
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1409
@@ -XXX,XX +XXX,XX @@ read 65536/65536 bytes at offset 344064
1410
{ "start": 262144, "length": 262144, "depth": 0, "zero": true, "data": false}]
1411
1412
=== preallocation=off ===
1413
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16
1414
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=524288 lazy_refcounts=off refcount_bits=16
1415
1416
-Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1417
+Formatting 'TEST_DIR/PID-top', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=262144 backing_file=TEST_DIR/PID-base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
1418
1419
wrote 65536/65536 bytes at offset 446464
1420
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1421
diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out
1422
index XXXXXXX..XXXXXXX 100644
1423
--- a/tests/qemu-iotests/280.out
1424
+++ b/tests/qemu-iotests/280.out
1425
@@ -XXX,XX +XXX,XX @@
1426
-Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1427
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=67108864 lazy_refcounts=off refcount_bits=16
1428
1429
=== Launch VM ===
1430
Enabling migration QMP events on VM...
1431
diff --git a/tests/qemu-iotests/291.out b/tests/qemu-iotests/291.out
1432
index XXXXXXX..XXXXXXX 100644
1433
--- a/tests/qemu-iotests/291.out
1434
+++ b/tests/qemu-iotests/291.out
1435
@@ -XXX,XX +XXX,XX @@ Format specific information:
1436
granularity: 65536
1437
refcount bits: 16
1438
corrupt: false
1439
+ extended l2: false
1440
image: TEST_DIR/t.IMGFMT
1441
file format: IMGFMT
1442
virtual size: 10 MiB (10485760 bytes)
1443
@@ -XXX,XX +XXX,XX @@ Format specific information:
1444
granularity: 65536
1445
refcount bits: 16
1446
corrupt: false
1447
+ extended l2: false
1448
1449
=== Check bitmap contents ===
1450
1451
diff --git a/tests/qemu-iotests/302.out b/tests/qemu-iotests/302.out
1452
index XXXXXXX..XXXXXXX 100644
1453
--- a/tests/qemu-iotests/302.out
1454
+++ b/tests/qemu-iotests/302.out
1455
@@ -XXX,XX +XXX,XX @@ Format specific information:
1456
lazy refcounts: false
1457
refcount bits: 16
1458
corrupt: false
1459
+ extended l2: false
1460
1461
=== Converted image check ===
1462
No errors were found on the image.
1463
diff --git a/tests/qemu-iotests/303.out b/tests/qemu-iotests/303.out
1464
index XXXXXXX..XXXXXXX 100644
1465
--- a/tests/qemu-iotests/303.out
1466
+++ b/tests/qemu-iotests/303.out
1467
@@ -XXX,XX +XXX,XX @@ header_length 112
1468
1469
Header extension:
1470
magic 0x6803f857 (Feature table)
1471
-length 336
1472
+length 384
1473
data <binary>
1474
1475
Header extension:
1476
@@ -XXX,XX +XXX,XX @@ Bitmap table type size offset
1477
{
1478
"name": "Feature table",
1479
"magic": 1745090647,
1480
- "length": 336,
1481
+ "length": 384,
1482
"data_str": "<binary>"
1483
},
1484
{
1485
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
1486
index XXXXXXX..XXXXXXX 100644
1487
--- a/tests/qemu-iotests/common.filter
1488
+++ b/tests/qemu-iotests/common.filter
1489
@@ -XXX,XX +XXX,XX @@ _filter_img_info()
1490
-e "/adapter_type: '[^']*'/d" \
1491
-e "/hwversion: '[^']*'/d" \
1492
-e "/lazy_refcounts: \\(on\\|off\\)/d" \
1493
+ -e "/extended_l2=\\(on\\|off\\)/d" \
1494
-e "/block_size: [0-9]\\+/d" \
1495
-e "/block_state_zero: \\(on\\|off\\)/d" \
1496
-e "/log_size: [0-9]\\+/d" \
261
--
1497
--
262
2.9.3
1498
2.26.2
263
1499
264
1500
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Traditional qcow2 images don't allow preallocation if a backing file
4
is set. This is because once a cluster is allocated there is no way to
5
tell that its data should be read from the backing file.
6
7
Extended L2 entries have individual allocation bits for each
8
subcluster, and therefore it is perfectly possible to have an
9
allocated cluster with all its subclusters unallocated.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Eric Blake <eblake@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
Message-Id: <6d5b0f38e7dc5f2f31d8cab1cb92044e9909aece.1594396418.git.berto@igalia.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
---
17
block/qcow2.c | 7 ++++---
18
tests/qemu-iotests/206.out | 2 +-
19
2 files changed, 5 insertions(+), 4 deletions(-)
20
21
diff --git a/block/qcow2.c b/block/qcow2.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2.c
24
+++ b/block/qcow2.c
25
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
26
qcow2_opts->preallocation = PREALLOC_MODE_OFF;
27
}
28
if (qcow2_opts->has_backing_file &&
29
- qcow2_opts->preallocation != PREALLOC_MODE_OFF)
30
+ qcow2_opts->preallocation != PREALLOC_MODE_OFF &&
31
+ !qcow2_opts->extended_l2)
32
{
33
- error_setg(errp, "Backing file and preallocation cannot be used at "
34
- "the same time");
35
+ error_setg(errp, "Backing file and preallocation can only be used at "
36
+ "the same time if extended_l2 is on");
37
ret = -EINVAL;
38
goto out;
39
}
40
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/206.out
43
+++ b/tests/qemu-iotests/206.out
44
@@ -XXX,XX +XXX,XX @@ Job failed: Different refcount widths than 16 bits require compatibility level 1
45
=== Invalid backing file options ===
46
{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}}
47
{"return": {}}
48
-Job failed: Backing file and preallocation cannot be used at the same time
49
+Job failed: Backing file and preallocation can only be used at the same time if extended_l2 is on
50
{"execute": "job-dismiss", "arguments": {"id": "job0"}}
51
{"return": {}}
52
53
--
54
2.26.2
55
56
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
This function is only used by qcow2_expand_zero_clusters() to
4
downgrade a qcow2 image to a previous version. This would require
5
transforming all extended L2 entries into normal L2 entries but this
6
is not a simple task and there are no plans to implement this at the
7
moment.
8
9
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Eric Blake <eblake@redhat.com>
11
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Message-Id: <15e65112b4144381b4d8c0bdf8fb76b0d813e3d1.1594396418.git.berto@igalia.com>
13
[mreitz: Fixed comment style]
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
block/qcow2-cluster.c | 14 ++++++++++++--
17
tests/qemu-iotests/061 | 6 ++++++
18
tests/qemu-iotests/061.out | 5 +++++
19
3 files changed, 23 insertions(+), 2 deletions(-)
20
21
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/block/qcow2-cluster.c
24
+++ b/block/qcow2-cluster.c
25
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
26
int ret;
27
int i, j;
28
29
+ /* qcow2_downgrade() is not allowed in images with subclusters */
30
+ assert(!has_subclusters(s));
31
+
32
slice_size2 = s->l2_slice_size * l2_entry_size(s);
33
n_slices = s->cluster_size / slice_size2;
34
35
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
36
37
if (cluster_type == QCOW2_CLUSTER_ZERO_PLAIN) {
38
if (!bs->backing) {
39
- /* not backed; therefore we can simply deallocate the
40
- * cluster */
41
+ /*
42
+ * not backed; therefore we can simply deallocate the
43
+ * cluster. No need to call set_l2_bitmap(), this
44
+ * function doesn't support images with subclusters.
45
+ */
46
set_l2_entry(s, l2_slice, j, 0);
47
l2_dirty = true;
48
continue;
49
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
50
} else {
51
set_l2_entry(s, l2_slice, j, offset);
52
}
53
+ /*
54
+ * No need to call set_l2_bitmap() after set_l2_entry() because
55
+ * this function doesn't support images with subclusters.
56
+ */
57
l2_dirty = true;
58
}
59
60
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
61
index XXXXXXX..XXXXXXX 100755
62
--- a/tests/qemu-iotests/061
63
+++ b/tests/qemu-iotests/061
64
@@ -XXX,XX +XXX,XX @@ $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
65
_img_info --format-specific
66
_check_test_img
67
68
+echo
69
+echo "=== Testing version downgrade with extended L2 entries ==="
70
+echo
71
+_make_test_img -o "compat=1.1,extended_l2=on" 64M
72
+$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
73
+
74
echo
75
echo "=== Try changing the external data file ==="
76
echo
77
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
78
index XXXXXXX..XXXXXXX 100644
79
--- a/tests/qemu-iotests/061.out
80
+++ b/tests/qemu-iotests/061.out
81
@@ -XXX,XX +XXX,XX @@ Format specific information:
82
extended l2: false
83
No errors were found on the image.
84
85
+=== Testing version downgrade with extended L2 entries ===
86
+
87
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
88
+qemu-img: Cannot downgrade an image with incompatible features 0x10 set
89
+
90
=== Try changing the external data file ===
91
92
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
93
--
94
2.26.2
95
96
diff view generated by jsdifflib
New patch
1
From: Alberto Garcia <berto@igalia.com>
1
2
3
Signed-off-by: Alberto Garcia <berto@igalia.com>
4
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
Message-Id: <e6dd0429cafe84ca603179c298a8703bddca2904.1594396418.git.berto@igalia.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/271 | 901 +++++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/271.out | 726 ++++++++++++++++++++++++++++++
10
tests/qemu-iotests/group | 1 +
11
3 files changed, 1628 insertions(+)
12
create mode 100755 tests/qemu-iotests/271
13
create mode 100644 tests/qemu-iotests/271.out
14
15
diff --git a/tests/qemu-iotests/271 b/tests/qemu-iotests/271
16
new file mode 100755
17
index XXXXXXX..XXXXXXX
18
--- /dev/null
19
+++ b/tests/qemu-iotests/271
20
@@ -XXX,XX +XXX,XX @@
21
+#!/bin/bash
22
+#
23
+# Test qcow2 images with extended L2 entries
24
+#
25
+# Copyright (C) 2019-2020 Igalia, S.L.
26
+# Author: Alberto Garcia <berto@igalia.com>
27
+#
28
+# This program is free software; you can redistribute it and/or modify
29
+# it under the terms of the GNU General Public License as published by
30
+# the Free Software Foundation; either version 2 of the License, or
31
+# (at your option) any later version.
32
+#
33
+# This program is distributed in the hope that it will be useful,
34
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
35
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36
+# GNU General Public License for more details.
37
+#
38
+# You should have received a copy of the GNU General Public License
39
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
40
+#
41
+
42
+# creator
43
+owner=berto@igalia.com
44
+
45
+seq="$(basename $0)"
46
+echo "QA output created by $seq"
47
+
48
+here="$PWD"
49
+status=1    # failure is the default!
50
+
51
+_cleanup()
52
+{
53
+ _cleanup_test_img
54
+ rm -f "$TEST_IMG.raw"
55
+}
56
+trap "_cleanup; exit \$status" 0 1 2 3 15
57
+
58
+# get standard environment, filters and checks
59
+. ./common.rc
60
+. ./common.filter
61
+
62
+_supported_fmt qcow2
63
+_supported_proto file nfs
64
+_supported_os Linux
65
+_unsupported_imgopts extended_l2 compat=0.10 cluster_size data_file refcount_bits=1[^0-9]
66
+
67
+l2_offset=$((0x40000))
68
+
69
+_verify_img()
70
+{
71
+ $QEMU_IMG compare "$TEST_IMG" "$TEST_IMG.raw" | grep -v 'Images are identical'
72
+ $QEMU_IMG check "$TEST_IMG" | _filter_qemu_img_check | \
73
+ grep -v 'No errors were found on the image'
74
+}
75
+
76
+# Compare the bitmap of an extended L2 entry against an expected value
77
+_verify_l2_bitmap()
78
+{
79
+ entry_no="$1" # L2 entry number, starting from 0
80
+ expected_alloc="$alloc" # Space-separated list of allocated subcluster indexes
81
+ expected_zero="$zero" # Space-separated list of zero subcluster indexes
82
+
83
+ offset=$(($l2_offset + $entry_no * 16))
84
+ entry=$(peek_file_be "$TEST_IMG" $offset 8)
85
+ offset=$(($offset + 8))
86
+ bitmap=$(peek_file_be "$TEST_IMG" $offset 8)
87
+
88
+ expected_bitmap=0
89
+ for bit in $expected_alloc; do
90
+ expected_bitmap=$(($expected_bitmap | (1 << $bit)))
91
+ done
92
+ for bit in $expected_zero; do
93
+ expected_bitmap=$(($expected_bitmap | (1 << (32 + $bit))))
94
+ done
95
+ printf -v expected_bitmap "%u" $expected_bitmap # Convert to unsigned
96
+
97
+ printf "L2 entry #%d: 0x%016x %016x\n" "$entry_no" "$entry" "$bitmap"
98
+ if [ "$bitmap" != "$expected_bitmap" ]; then
99
+ printf "ERROR: expecting bitmap 0x%016x\n" "$expected_bitmap"
100
+ fi
101
+}
102
+
103
+# This should be called as _run_test c=XXX sc=XXX off=XXX len=XXX cmd=XXX
104
+# c: cluster number (0 if unset)
105
+# sc: subcluster number inside cluster @c (0 if unset)
106
+# off: offset inside subcluster @sc, in kilobytes (0 if unset)
107
+# len: request length, passed directly to qemu-io (e.g: 256, 4k, 1M, ...)
108
+# cmd: the command to pass to qemu-io, must be one of
109
+# write -> write
110
+# zero -> write -z
111
+# unmap -> write -z -u
112
+# compress -> write -c
113
+# discard -> discard
114
+_run_test()
115
+{
116
+ unset c sc off len cmd
117
+ for var in "$@"; do eval "$var"; done
118
+ case "${cmd:-write}" in
119
+ zero)
120
+ cmd="write -q -z";;
121
+ unmap)
122
+ cmd="write -q -z -u";;
123
+ compress)
124
+ pat=$((${pat:-0} + 1))
125
+ cmd="write -q -c -P ${pat}";;
126
+ write)
127
+ pat=$((${pat:-0} + 1))
128
+ cmd="write -q -P ${pat}";;
129
+ discard)
130
+ cmd="discard -q";;
131
+ *)
132
+ echo "Unknown option $cmd"
133
+ exit 1;;
134
+ esac
135
+ c="${c:-0}"
136
+ sc="${sc:-0}"
137
+ off="${off:-0}"
138
+ offset="$(($c * 64 + $sc * 2 + $off))"
139
+ [ "$offset" != 0 ] && offset="${offset}k"
140
+ cmd="$cmd ${offset} ${len}"
141
+ raw_cmd=$(echo $cmd | sed s/-c//) # Raw images don't support -c
142
+ echo $cmd | sed 's/-P [0-9][0-9]\?/-P PATTERN/'
143
+ $QEMU_IO -c "$cmd" "$TEST_IMG" | _filter_qemu_io
144
+ $QEMU_IO -c "$raw_cmd" -f raw "$TEST_IMG.raw" | _filter_qemu_io
145
+ _verify_img
146
+ _verify_l2_bitmap "$c"
147
+}
148
+
149
+_reset_img()
150
+{
151
+ size="$1"
152
+ $QEMU_IMG create -f raw "$TEST_IMG.raw" "$size" | _filter_img_create
153
+ if [ "$use_backing_file" = "yes" ]; then
154
+ $QEMU_IMG create -f raw "$TEST_IMG.base" "$size" | _filter_img_create
155
+ $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.base" | _filter_qemu_io
156
+ $QEMU_IO -c "write -q -P 0xFF 0 $size" -f raw "$TEST_IMG.raw" | _filter_qemu_io
157
+ _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" "$size"
158
+ else
159
+ _make_test_img -o extended_l2=on "$size"
160
+ fi
161
+}
162
+
163
+############################################################
164
+############################################################
165
+############################################################
166
+
167
+# Test that writing to an image with subclusters produces the expected
168
+# results, in images with and without backing files
169
+for use_backing_file in yes no; do
170
+ echo
171
+ echo "### Standard write tests (backing file: $use_backing_file) ###"
172
+ echo
173
+ _reset_img 1M
174
+ ### Write subcluster #0 (beginning of subcluster) ###
175
+ alloc="0"; zero=""
176
+ _run_test sc=0 len=1k
177
+
178
+ ### Write subcluster #1 (middle of subcluster) ###
179
+ alloc="0 1"; zero=""
180
+ _run_test sc=1 off=1 len=512
181
+
182
+ ### Write subcluster #2 (end of subcluster) ###
183
+ alloc="0 1 2"; zero=""
184
+ _run_test sc=2 off=1 len=1k
185
+
186
+ ### Write subcluster #3 (full subcluster) ###
187
+ alloc="0 1 2 3"; zero=""
188
+ _run_test sc=3 len=2k
189
+
190
+ ### Write subclusters #4-6 (full subclusters) ###
191
+ alloc="$(seq 0 6)"; zero=""
192
+ _run_test sc=4 len=6k
193
+
194
+ ### Write subclusters #7-9 (partial subclusters) ###
195
+ alloc="$(seq 0 9)"; zero=""
196
+ _run_test sc=7 off=1 len=4k
197
+
198
+ ### Write subcluster #16 (partial subcluster) ###
199
+ alloc="$(seq 0 9) 16"; zero=""
200
+ _run_test sc=16 len=1k
201
+
202
+ ### Write subcluster #31-#33 (cluster overlap) ###
203
+ alloc="$(seq 0 9) 16 31"; zero=""
204
+ _run_test sc=31 off=1 len=4k
205
+ alloc="0 1" ; zero=""
206
+ _verify_l2_bitmap 1
207
+
208
+ ### Zero subcluster #1
209
+ alloc="0 $(seq 2 9) 16 31"; zero="1"
210
+ _run_test sc=1 len=2k cmd=zero
211
+
212
+ ### Zero cluster #0
213
+ alloc=""; zero="$(seq 0 31)"
214
+ _run_test sc=0 len=64k cmd=zero
215
+
216
+ ### Fill cluster #0 with data
217
+ alloc="$(seq 0 31)"; zero=""
218
+ _run_test sc=0 len=64k
219
+
220
+ ### Zero and unmap half of cluster #0 (this won't unmap it)
221
+ alloc="$(seq 16 31)"; zero="$(seq 0 15)"
222
+ _run_test sc=0 len=32k cmd=unmap
223
+
224
+ ### Zero and unmap cluster #0
225
+ alloc=""; zero="$(seq 0 31)"
226
+ _run_test sc=0 len=64k cmd=unmap
227
+
228
+ ### Write subcluster #1 (middle of subcluster)
229
+ alloc="1"; zero="0 $(seq 2 31)"
230
+ _run_test sc=1 off=1 len=512
231
+
232
+ ### Fill cluster #0 with data
233
+ alloc="$(seq 0 31)"; zero=""
234
+ _run_test sc=0 len=64k
235
+
236
+ ### Discard cluster #0
237
+ alloc=""; zero="$(seq 0 31)"
238
+ _run_test sc=0 len=64k cmd=discard
239
+
240
+ ### Write compressed data to cluster #0
241
+ alloc=""; zero=""
242
+ _run_test sc=0 len=64k cmd=compress
243
+
244
+ ### Write subcluster #1 (middle of subcluster)
245
+ alloc="$(seq 0 31)"; zero=""
246
+ _run_test sc=1 off=1 len=512
247
+done
248
+
249
+############################################################
250
+############################################################
251
+############################################################
252
+
253
+# calculate_l2_meta() checks if none of the clusters affected by a
254
+# write operation need COW or changes to their L2 metadata and simply
255
+# returns when they don't. This is a test for that optimization.
256
+# Here clusters #0-#3 are overwritten but only #1 and #2 need changes.
257
+echo
258
+echo '### Overwriting several clusters without COW ###'
259
+echo
260
+use_backing_file="no" _reset_img 1M
261
+# Write cluster #0, subclusters #12-#31
262
+alloc="$(seq 12 31)"; zero=""
263
+_run_test sc=12 len=40k
264
+
265
+# Write cluster #1, subcluster #13
266
+alloc="13"; zero=""
267
+_run_test c=1 sc=13 len=2k
268
+
269
+# Zeroize cluster #2, subcluster #14
270
+alloc="14"; zero=""
271
+_run_test c=2 sc=14 len=2k
272
+alloc=""; zero="14"
273
+_run_test c=2 sc=14 len=2k cmd=zero
274
+
275
+# Write cluster #3, subclusters #0-#16
276
+alloc="$(seq 0 16)"; zero=""
277
+_run_test c=3 sc=0 len=34k
278
+
279
+# Write from cluster #0, subcluster #12 to cluster #3, subcluster #11
280
+alloc="$(seq 12 31)"; zero=""
281
+_run_test sc=12 len=192k
282
+alloc="$(seq 0 31)"; zero=""
283
+_verify_l2_bitmap 1
284
+_verify_l2_bitmap 2
285
+
286
+alloc="$(seq 0 16)"; zero=""
287
+_verify_l2_bitmap 3
288
+
289
+############################################################
290
+############################################################
291
+############################################################
292
+
293
+# Test different patterns of writing zeroes
294
+for use_backing_file in yes no; do
295
+ echo
296
+ echo "### Writing zeroes 1: unallocated clusters (backing file: $use_backing_file) ###"
297
+ echo
298
+ # Note that the image size is not a multiple of the cluster size
299
+ _reset_img 2083k
300
+
301
+ # Cluster-aligned request from clusters #0 to #2
302
+ alloc=""; zero="$(seq 0 31)"
303
+ _run_test c=0 sc=0 len=192k cmd=zero
304
+ _verify_l2_bitmap 1
305
+ _verify_l2_bitmap 2
306
+
307
+ # Subcluster-aligned request from clusters #3 to #5
308
+ alloc=""; zero="$(seq 16 31)"
309
+ _run_test c=3 sc=16 len=128k cmd=zero
310
+ alloc=""; zero="$(seq 0 31)"
311
+ _verify_l2_bitmap 4
312
+ alloc=""; zero="$(seq 0 15)"
313
+ _verify_l2_bitmap 5
314
+
315
+ # Unaligned request from clusters #6 to #8
316
+ if [ "$use_backing_file" = "yes" ]; then
317
+ alloc="15"; zero="$(seq 16 31)" # copy-on-write happening here
318
+ else
319
+ alloc=""; zero="$(seq 15 31)"
320
+ fi
321
+ _run_test c=6 sc=15 off=1 len=128k cmd=zero
322
+ alloc=""; zero="$(seq 0 31)"
323
+ _verify_l2_bitmap 7
324
+ if [ "$use_backing_file" = "yes" ]; then
325
+ alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
326
+ else
327
+ alloc=""; zero="$(seq 0 15)"
328
+ fi
329
+ _verify_l2_bitmap 8
330
+
331
+ echo
332
+ echo "### Writing zeroes 2: allocated clusters (backing file: $use_backing_file) ###"
333
+ echo
334
+ alloc="$(seq 0 31)"; zero=""
335
+ _run_test c=9 sc=0 len=576k
336
+ _verify_l2_bitmap 10
337
+ _verify_l2_bitmap 11
338
+ _verify_l2_bitmap 12
339
+ _verify_l2_bitmap 13
340
+ _verify_l2_bitmap 14
341
+ _verify_l2_bitmap 15
342
+ _verify_l2_bitmap 16
343
+ _verify_l2_bitmap 17
344
+
345
+ # Cluster-aligned request from clusters #9 to #11
346
+ alloc=""; zero="$(seq 0 31)"
347
+ _run_test c=9 sc=0 len=192k cmd=zero
348
+ _verify_l2_bitmap 10
349
+ _verify_l2_bitmap 11
350
+
351
+ # Subcluster-aligned request from clusters #12 to #14
352
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
353
+ _run_test c=12 sc=16 len=128k cmd=zero
354
+ alloc=""; zero="$(seq 0 31)"
355
+ _verify_l2_bitmap 13
356
+ alloc="$(seq 16 31)"; zero="$(seq 0 15)"
357
+ _verify_l2_bitmap 14
358
+
359
+ # Unaligned request from clusters #15 to #17
360
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
361
+ _run_test c=15 sc=15 off=1 len=128k cmd=zero
362
+ alloc=""; zero="$(seq 0 31)"
363
+ _verify_l2_bitmap 16
364
+ alloc="$(seq 15 31)"; zero="$(seq 0 14)"
365
+ _verify_l2_bitmap 17
366
+
367
+ echo
368
+ echo "### Writing zeroes 3: compressed clusters (backing file: $use_backing_file) ###"
369
+ echo
370
+ alloc=""; zero=""
371
+ for c in $(seq 18 28); do
372
+ _run_test c=$c sc=0 len=64k cmd=compress
373
+ done
374
+
375
+ # Cluster-aligned request from clusters #18 to #20
376
+ alloc=""; zero="$(seq 0 31)"
377
+ _run_test c=18 sc=0 len=192k cmd=zero
378
+ _verify_l2_bitmap 19
379
+ _verify_l2_bitmap 20
380
+
381
+ # Subcluster-aligned request from clusters #21 to #23.
382
+ # We cannot partially zero a compressed cluster so the code
383
+ # returns -ENOTSUP, which means copy-on-write of the compressed
384
+ # data and fill the rest with actual zeroes on disk.
385
+ # TODO: cluster #22 should use the 'all zeroes' bits.
386
+ alloc="$(seq 0 31)"; zero=""
387
+ _run_test c=21 sc=16 len=128k cmd=zero
388
+ _verify_l2_bitmap 22
389
+ _verify_l2_bitmap 23
390
+
391
+ # Unaligned request from clusters #24 to #26
392
+ # In this case QEMU internally sends a 1k request followed by a
393
+ # subcluster-aligned 128k request. The first request decompresses
394
+ # cluster #24, but that's not enough to perform the second request
395
+ # efficiently because it partially writes to cluster #26 (which is
396
+ # compressed) so we hit the same problem as before.
397
+ alloc="$(seq 0 31)"; zero=""
398
+ _run_test c=24 sc=15 off=1 len=129k cmd=zero
399
+ _verify_l2_bitmap 25
400
+ _verify_l2_bitmap 26
401
+
402
+ # Unaligned request from clusters #27 to #29
403
+ # Similar to the previous case, but this time the tail of the
404
+ # request does not correspond to a compressed cluster, so it can
405
+ # be zeroed efficiently.
406
+ # Note that the very last subcluster is partially written, so if
407
+ # there's a backing file we need to perform cow.
408
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
409
+ _run_test c=27 sc=15 off=1 len=128k cmd=zero
410
+ alloc=""; zero="$(seq 0 31)"
411
+ _verify_l2_bitmap 28
412
+ if [ "$use_backing_file" = "yes" ]; then
413
+ alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
414
+ else
415
+ alloc=""; zero="$(seq 0 15)"
416
+ fi
417
+ _verify_l2_bitmap 29
418
+
419
+ echo
420
+ echo "### Writing zeroes 4: other tests (backing file: $use_backing_file) ###"
421
+ echo
422
+ # Unaligned request in the middle of cluster #30.
423
+ # If there's a backing file we need to allocate and do
424
+ # copy-on-write on the partially zeroed subclusters.
425
+ # If not we can set the 'all zeroes' bit on them.
426
+ if [ "$use_backing_file" = "yes" ]; then
427
+ alloc="15 19"; zero="$(seq 16 18)" # copy-on-write happening here
428
+ else
429
+ alloc=""; zero="$(seq 15 19)"
430
+ fi
431
+ _run_test c=30 sc=15 off=1 len=8k cmd=zero
432
+
433
+ # Fill the last cluster with zeroes, up to the end of the image
434
+ # (the image size is not a multiple of the cluster or subcluster size).
435
+ alloc=""; zero="$(seq 0 17)"
436
+ _run_test c=32 sc=0 len=35k cmd=zero
437
+done
438
+
439
+############################################################
440
+############################################################
441
+############################################################
442
+
443
+# Zero + unmap
444
+for use_backing_file in yes no; do
445
+ echo
446
+ echo "### Zero + unmap 1: allocated clusters (backing file: $use_backing_file) ###"
447
+ echo
448
+ # Note that the image size is not a multiple of the cluster size
449
+ _reset_img 2083k
450
+ alloc="$(seq 0 31)"; zero=""
451
+ _run_test c=9 sc=0 len=576k
452
+ _verify_l2_bitmap 10
453
+ _verify_l2_bitmap 11
454
+ _verify_l2_bitmap 12
455
+ _verify_l2_bitmap 13
456
+ _verify_l2_bitmap 14
457
+ _verify_l2_bitmap 15
458
+ _verify_l2_bitmap 16
459
+ _verify_l2_bitmap 17
460
+
461
+ # Cluster-aligned request from clusters #9 to #11
462
+ alloc=""; zero="$(seq 0 31)"
463
+ _run_test c=9 sc=0 len=192k cmd=unmap
464
+ _verify_l2_bitmap 10
465
+ _verify_l2_bitmap 11
466
+
467
+ # Subcluster-aligned request from clusters #12 to #14
468
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
469
+ _run_test c=12 sc=16 len=128k cmd=unmap
470
+ alloc=""; zero="$(seq 0 31)"
471
+ _verify_l2_bitmap 13
472
+ alloc="$(seq 16 31)"; zero="$(seq 0 15)"
473
+ _verify_l2_bitmap 14
474
+
475
+ # Unaligned request from clusters #15 to #17
476
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
477
+ _run_test c=15 sc=15 off=1 len=128k cmd=unmap
478
+ alloc=""; zero="$(seq 0 31)"
479
+ _verify_l2_bitmap 16
480
+ alloc="$(seq 15 31)"; zero="$(seq 0 14)"
481
+ _verify_l2_bitmap 17
482
+
483
+ echo
484
+ echo "### Zero + unmap 2: compressed clusters (backing file: $use_backing_file) ###"
485
+ echo
486
+ alloc=""; zero=""
487
+ for c in $(seq 18 28); do
488
+ _run_test c=$c sc=0 len=64k cmd=compress
489
+ done
490
+
491
+ # Cluster-aligned request from clusters #18 to #20
492
+ alloc=""; zero="$(seq 0 31)"
493
+ _run_test c=18 sc=0 len=192k cmd=unmap
494
+ _verify_l2_bitmap 19
495
+ _verify_l2_bitmap 20
496
+
497
+ # Subcluster-aligned request from clusters #21 to #23.
498
+ # We cannot partially zero a compressed cluster so the code
499
+ # returns -ENOTSUP, which means copy-on-write of the compressed
500
+ # data and fill the rest with actual zeroes on disk.
501
+ # TODO: cluster #22 should use the 'all zeroes' bits.
502
+ alloc="$(seq 0 31)"; zero=""
503
+ _run_test c=21 sc=16 len=128k cmd=unmap
504
+ _verify_l2_bitmap 22
505
+ _verify_l2_bitmap 23
506
+
507
+ # Unaligned request from clusters #24 to #26
508
+ # In this case QEMU internally sends a 1k request followed by a
509
+ # subcluster-aligned 128k request. The first request decompresses
510
+ # cluster #24, but that's not enough to perform the second request
511
+ # efficiently because it partially writes to cluster #26 (which is
512
+ # compressed) so we hit the same problem as before.
513
+ alloc="$(seq 0 31)"; zero=""
514
+ _run_test c=24 sc=15 off=1 len=129k cmd=unmap
515
+ _verify_l2_bitmap 25
516
+ _verify_l2_bitmap 26
517
+
518
+ # Unaligned request from clusters #27 to #29
519
+ # Similar to the previous case, but this time the tail of the
520
+ # request does not correspond to a compressed cluster, so it can
521
+ # be zeroed efficiently.
522
+ # Note that the very last subcluster is partially written, so if
523
+ # there's a backing file we need to perform cow.
524
+ alloc="$(seq 0 15)"; zero="$(seq 16 31)"
525
+ _run_test c=27 sc=15 off=1 len=128k cmd=unmap
526
+ alloc=""; zero="$(seq 0 31)"
527
+ _verify_l2_bitmap 28
528
+ if [ "$use_backing_file" = "yes" ]; then
529
+ alloc="15"; zero="$(seq 0 14)" # copy-on-write happening here
530
+ else
531
+ alloc=""; zero="$(seq 0 15)"
532
+ fi
533
+ _verify_l2_bitmap 29
534
+done
535
+
536
+############################################################
537
+############################################################
538
+############################################################
539
+
540
+# Test qcow2_cluster_discard() with full and normal discards
541
+for use_backing_file in yes no; do
542
+ echo
543
+ echo "### Discarding clusters with non-zero bitmaps (backing file: $use_backing_file) ###"
544
+ echo
545
+ if [ "$use_backing_file" = "yes" ]; then
546
+ _make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 1M
547
+ else
548
+ _make_test_img -o extended_l2=on 1M
549
+ fi
550
+ # Write clusters #0-#2 and then discard them
551
+ $QEMU_IO -c 'write -q 0 128k' "$TEST_IMG"
552
+ $QEMU_IO -c 'discard -q 0 128k' "$TEST_IMG"
553
+ # 'qemu-io discard' doesn't do a full discard, it zeroizes the
554
+ # cluster, so both clusters have all zero bits set now
555
+ alloc=""; zero="$(seq 0 31)"
556
+ _verify_l2_bitmap 0
557
+ _verify_l2_bitmap 1
558
+ # Now mark the 2nd half of the subclusters from cluster #0 as unallocated
559
+ poke_file "$TEST_IMG" $(($l2_offset+8)) "\x00\x00"
560
+ # Discard cluster #0 again to see how the zero bits have changed
561
+ $QEMU_IO -c 'discard -q 0 64k' "$TEST_IMG"
562
+ # And do a full discard of cluster #1 by shrinking and growing the image
563
+ $QEMU_IMG resize --shrink "$TEST_IMG" 64k
564
+ $QEMU_IMG resize "$TEST_IMG" 1M
565
+ # A normal discard sets all 'zero' bits only if the image has a
566
+ # backing file, otherwise it won't touch them.
567
+ if [ "$use_backing_file" = "yes" ]; then
568
+ alloc=""; zero="$(seq 0 31)"
569
+ else
570
+ alloc=""; zero="$(seq 0 15)"
571
+ fi
572
+ _verify_l2_bitmap 0
573
+ # A full discard should clear the L2 entry completely. However
574
+ # when growing an image with a backing file the new clusters are
575
+ # zeroized to hide the stale data from the backing file
576
+ if [ "$use_backing_file" = "yes" ]; then
577
+ alloc=""; zero="$(seq 0 31)"
578
+ else
579
+ alloc=""; zero=""
580
+ fi
581
+ _verify_l2_bitmap 1
582
+done
583
+
584
+############################################################
585
+############################################################
586
+############################################################
587
+
588
+# Test that corrupted L2 entries are detected in both read and write
589
+# operations
590
+for corruption_test_cmd in read write; do
591
+ echo
592
+ echo "### Corrupted L2 entries - $corruption_test_cmd test (allocated) ###"
593
+ echo
594
+ echo "# 'cluster is zero' bit set on the standard cluster descriptor"
595
+ echo
596
+ # We actually don't consider this a corrupted image.
597
+ # The 'cluster is zero' bit is unused in extended L2 entries so
598
+ # QEMU ignores it.
599
+ # TODO: maybe treat the image as corrupted and make qemu-img check fix it?
600
+ _make_test_img -o extended_l2=on 1M
601
+ $QEMU_IO -c 'write -q -P 0x11 0 2k' "$TEST_IMG"
602
+ poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01"
603
+ alloc="0"; zero=""
604
+ _verify_l2_bitmap 0
605
+ $QEMU_IO -c "$corruption_test_cmd -q -P 0x11 0 1k" "$TEST_IMG"
606
+ if [ "$corruption_test_cmd" = "write" ]; then
607
+ alloc="0"; zero=""
608
+ fi
609
+ _verify_l2_bitmap 0
610
+
611
+ echo
612
+ echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set"
613
+ echo
614
+ _make_test_img -o extended_l2=on 1M
615
+ # Write from the middle of cluster #0 to the middle of cluster #2
616
+ $QEMU_IO -c 'write -q 32k 128k' "$TEST_IMG"
617
+ # Corrupt the L2 entry from cluster #1
618
+ poke_file_be "$TEST_IMG" $(($l2_offset+24)) 4 1
619
+ alloc="$(seq 0 31)"; zero="0"
620
+ _verify_l2_bitmap 1
621
+ $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG"
622
+
623
+ echo
624
+ echo "### Corrupted L2 entries - $corruption_test_cmd test (unallocated) ###"
625
+ echo
626
+ echo "# 'cluster is zero' bit set on the standard cluster descriptor"
627
+ echo
628
+ # We actually don't consider this a corrupted image.
629
+ # The 'cluster is zero' bit is unused in extended L2 entries so
630
+ # QEMU ignores it.
631
+ # TODO: maybe treat the image as corrupted and make qemu-img check fix it?
632
+ _make_test_img -o extended_l2=on 1M
633
+ # We want to modify the (empty) L2 entry from cluster #0,
634
+ # but we write to #4 in order to initialize the L2 table first
635
+ $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
636
+ poke_file "$TEST_IMG" $(($l2_offset+7)) "\x01"
637
+ alloc=""; zero=""
638
+ _verify_l2_bitmap 0
639
+ $QEMU_IO -c "$corruption_test_cmd -q 0 1k" "$TEST_IMG"
640
+ if [ "$corruption_test_cmd" = "write" ]; then
641
+ alloc="0"; zero=""
642
+ fi
643
+ _verify_l2_bitmap 0
644
+
645
+ echo
646
+ echo "# 'subcluster is allocated' bit set"
647
+ echo
648
+ _make_test_img -o extended_l2=on 1M
649
+ # We want to corrupt the (empty) L2 entry from cluster #0,
650
+ # but we write to #4 in order to initialize the L2 table first
651
+ $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
652
+ poke_file "$TEST_IMG" $(($l2_offset+15)) "\x01"
653
+ alloc="0"; zero=""
654
+ _verify_l2_bitmap 0
655
+ $QEMU_IO -c "$corruption_test_cmd 0 1k" "$TEST_IMG"
656
+
657
+ echo
658
+ echo "# Both 'subcluster is zero' and 'subcluster is allocated' bits set"
659
+ echo
660
+ _make_test_img -o extended_l2=on 1M
661
+ # We want to corrupt the (empty) L2 entry from cluster #1,
662
+ # but we write to #4 in order to initialize the L2 table first
663
+ $QEMU_IO -c 'write -q 256k 1k' "$TEST_IMG"
664
+ # Corrupt the L2 entry from cluster #1
665
+ poke_file_be "$TEST_IMG" $(($l2_offset+24)) 8 $(((1 << 32) | 1))
666
+ alloc="0"; zero="0"
667
+ _verify_l2_bitmap 1
668
+ $QEMU_IO -c "$corruption_test_cmd 0 192k" "$TEST_IMG"
669
+
670
+ echo
671
+ echo "### Compressed cluster with subcluster bitmap != 0 - $corruption_test_cmd test ###"
672
+ echo
673
+ # We actually don't consider this a corrupted image.
674
+ # The bitmap in compressed clusters is unused so QEMU should just ignore it.
675
+ _make_test_img -o extended_l2=on 1M
676
+ $QEMU_IO -c 'write -q -P 11 -c 0 64k' "$TEST_IMG"
677
+ # Change the L2 bitmap to allocate subcluster #31 and zeroize subcluster #0
678
+ poke_file "$TEST_IMG" $(($l2_offset+11)) "\x01\x80"
679
+ alloc="31"; zero="0"
680
+ _verify_l2_bitmap 0
681
+ $QEMU_IO -c "$corruption_test_cmd -P 11 0 64k" "$TEST_IMG" | _filter_qemu_io
682
+ # Writing allocates a new uncompressed cluster so we get a new bitmap
683
+ if [ "$corruption_test_cmd" = "write" ]; then
684
+ alloc="$(seq 0 31)"; zero=""
685
+ fi
686
+ _verify_l2_bitmap 0
687
+done
688
+
689
+############################################################
690
+############################################################
691
+############################################################
692
+
693
+echo
694
+echo "### Detect and repair unaligned clusters ###"
695
+echo
696
+# Create a backing file and fill it with data
697
+$QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create
698
+$QEMU_IO -c "write -q -P 0xff 0 128k" -f raw "$TEST_IMG.base" | _filter_qemu_io
699
+
700
+echo "# Corrupted L2 entry, allocated subcluster #"
701
+# Create a new image, allocate a cluster and write some data to it
702
+_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base"
703
+$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG"
704
+# Corrupt the L2 entry by making the offset unaligned
705
+poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02"
706
+# This cannot be repaired, qemu-img check will fail to fix it
707
+_check_test_img -r all
708
+# Attempting to read the image will still show that it's corrupted
709
+$QEMU_IO -c 'read -q 0 2k' "$TEST_IMG"
710
+
711
+echo "# Corrupted L2 entry, no allocated subclusters #"
712
+# Create a new image, allocate a cluster and zeroize subcluster #2
713
+_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base"
714
+$QEMU_IO -c 'write -q -P 1 4k 2k' "$TEST_IMG"
715
+$QEMU_IO -c 'write -q -z 4k 2k' "$TEST_IMG"
716
+# Corrupt the L2 entry by making the offset unaligned
717
+poke_file "$TEST_IMG" "$(($l2_offset+6))" "\x02"
718
+# This time none of the subclusters are allocated so we can repair the image
719
+_check_test_img -r all
720
+# And the data can be read normally
721
+$QEMU_IO -c 'read -q -P 0xff 0 4k' "$TEST_IMG"
722
+$QEMU_IO -c 'read -q -P 0x00 4k 2k' "$TEST_IMG"
723
+$QEMU_IO -c 'read -q -P 0xff 6k 122k' "$TEST_IMG"
724
+
725
+############################################################
726
+############################################################
727
+############################################################
728
+
729
+echo
730
+echo "### Image creation options ###"
731
+echo
732
+echo "# cluster_size < 16k"
733
+_make_test_img -o extended_l2=on,cluster_size=8k 1M
734
+
735
+echo "# backing file and preallocation=metadata"
736
+# For preallocation with backing files, create a backing file first
737
+$QEMU_IMG create -f raw "$TEST_IMG.base" 1M | _filter_img_create
738
+$QEMU_IO -c "write -q -P 0xff 0 1M" -f raw "$TEST_IMG.base" | _filter_qemu_io
739
+
740
+_make_test_img -o extended_l2=on,preallocation=metadata -F raw -b "$TEST_IMG.base" 512k
741
+$QEMU_IMG resize "$TEST_IMG" 1M
742
+$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
743
+$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
744
+$QEMU_IMG map "$TEST_IMG" | _filter_testdir
745
+
746
+echo "# backing file and preallocation=falloc"
747
+_make_test_img -o extended_l2=on,preallocation=falloc -F raw -b "$TEST_IMG.base" 512k
748
+$QEMU_IMG resize "$TEST_IMG" 1M
749
+$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
750
+$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
751
+$QEMU_IMG map "$TEST_IMG" | _filter_testdir
752
+
753
+echo "# backing file and preallocation=full"
754
+_make_test_img -o extended_l2=on,preallocation=full -F raw -b "$TEST_IMG.base" 512k
755
+$QEMU_IMG resize "$TEST_IMG" 1M
756
+$QEMU_IO -c 'read -P 0xff 0 512k' "$TEST_IMG" | _filter_qemu_io
757
+$QEMU_IO -c 'read -P 0x00 512k 512k' "$TEST_IMG" | _filter_qemu_io
758
+$QEMU_IMG map "$TEST_IMG" | _filter_testdir
759
+
760
+echo
761
+echo "### Image resizing with preallocation and backing files ###"
762
+echo
763
+# In this case the new subclusters must have the 'all zeroes' bit set
764
+echo "# resize --preallocation=metadata"
765
+_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
766
+$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k
767
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
768
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
769
+
770
+# In this case and the next one the new subclusters must be allocated
771
+echo "# resize --preallocation=falloc"
772
+_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
773
+$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k
774
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
775
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
776
+
777
+echo "# resize --preallocation=full"
778
+_make_test_img -o extended_l2=on -F raw -b "$TEST_IMG.base" 503k
779
+$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k
780
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
781
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
782
+
783
+echo
784
+echo "### Image resizing with preallocation without backing files ###"
785
+echo
786
+# In this case the new subclusters must have the 'all zeroes' bit set
787
+echo "# resize --preallocation=metadata"
788
+_make_test_img -o extended_l2=on 503k
789
+$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
790
+$QEMU_IMG resize --preallocation=metadata "$TEST_IMG" 1013k
791
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
792
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
793
+
794
+# In this case and the next one the new subclusters must be allocated
795
+echo "# resize --preallocation=falloc"
796
+_make_test_img -o extended_l2=on 503k
797
+$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
798
+$QEMU_IMG resize --preallocation=falloc "$TEST_IMG" 1013k
799
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
800
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
801
+
802
+echo "# resize --preallocation=full"
803
+_make_test_img -o extended_l2=on 503k
804
+$QEMU_IO -c 'write -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
805
+$QEMU_IMG resize --preallocation=full "$TEST_IMG" 1013k
806
+$QEMU_IO -c 'read -P 0xff 0 503k' "$TEST_IMG" | _filter_qemu_io
807
+$QEMU_IO -c 'read -P 0x00 503k 510k' "$TEST_IMG" | _filter_qemu_io
808
+
809
+echo
810
+echo "### qemu-img measure ###"
811
+echo
812
+echo "# 512MB, extended_l2=off" # This needs one L2 table
813
+$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=off
814
+echo "# 512MB, extended_l2=on" # This needs two L2 tables
815
+$QEMU_IMG measure --size 512M -O qcow2 -o extended_l2=on
816
+
817
+echo "# 16K clusters, 64GB, extended_l2=off" # This needs one full L1 table cluster
818
+$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=off
819
+echo "# 16K clusters, 64GB, extended_l2=on" # This needs two full L2 table clusters
820
+$QEMU_IMG measure --size 64G -O qcow2 -o cluster_size=16k,extended_l2=on
821
+
822
+echo "# 8k clusters" # This should fail
823
+$QEMU_IMG measure --size 1M -O qcow2 -o cluster_size=8k,extended_l2=on
824
+
825
+echo "# 1024 TB" # Maximum allowed size with extended_l2=on and 64K clusters
826
+$QEMU_IMG measure --size 1024T -O qcow2 -o extended_l2=on
827
+echo "# 1025 TB" # This should fail
828
+$QEMU_IMG measure --size 1025T -O qcow2 -o extended_l2=on
829
+
830
+echo
831
+echo "### qemu-img amend ###"
832
+echo
833
+_make_test_img -o extended_l2=on 1M
834
+$QEMU_IMG amend -o extended_l2=off "$TEST_IMG" && echo "Unexpected pass"
835
+
836
+_make_test_img -o extended_l2=off 1M
837
+$QEMU_IMG amend -o extended_l2=on "$TEST_IMG" && echo "Unexpected pass"
838
+
839
+echo
840
+echo "### Test copy-on-write on an image with snapshots ###"
841
+echo
842
+_make_test_img -o extended_l2=on 1M
843
+
844
+# For each cluster from #0 to #9 this loop zeroes subcluster #7
845
+# and allocates subclusters #13 and #18.
846
+alloc="13 18"; zero="7"
847
+for c in $(seq 0 9); do
848
+ $QEMU_IO -c "write -q -z $((64*$c+14))k 2k" \
849
+ -c "write -q -P $((0xd0+$c)) $((64*$c+26))k 2k" \
850
+ -c "write -q -P $((0xe0+$c)) $((64*$c+36))k 2k" "$TEST_IMG"
851
+ _verify_l2_bitmap "$c"
852
+done
853
+
854
+# Create a snapshot and set l2_offset to the new L2 table
855
+$QEMU_IMG snapshot -c snap1 "$TEST_IMG"
856
+l2_offset=$((0x110000))
857
+
858
+# Write different patterns to each one of the clusters
859
+# in order to see how copy-on-write behaves in each case.
860
+$QEMU_IO -c "write -q -P 0xf0 $((64*0+30))k 1k" \
861
+ -c "write -q -P 0xf1 $((64*1+20))k 1k" \
862
+ -c "write -q -P 0xf2 $((64*2+40))k 1k" \
863
+ -c "write -q -P 0xf3 $((64*3+26))k 1k" \
864
+ -c "write -q -P 0xf4 $((64*4+14))k 1k" \
865
+ -c "write -q -P 0xf5 $((64*5+1))k 1k" \
866
+ -c "write -q -z $((64*6+30))k 3k" \
867
+ -c "write -q -z $((64*7+26))k 2k" \
868
+ -c "write -q -z $((64*8+26))k 1k" \
869
+ -c "write -q -z $((64*9+12))k 1k" \
870
+ "$TEST_IMG"
871
+alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 0
872
+alloc="$(seq 10 18)"; zero="7" _verify_l2_bitmap 1
873
+alloc="$(seq 13 20)"; zero="7" _verify_l2_bitmap 2
874
+alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 3
875
+alloc="$(seq 7 18)"; zero="" _verify_l2_bitmap 4
876
+alloc="$(seq 0 18)"; zero="" _verify_l2_bitmap 5
877
+alloc="13 18"; zero="7 15 16" _verify_l2_bitmap 6
878
+alloc="18"; zero="7 13" _verify_l2_bitmap 7
879
+alloc="$(seq 13 18)"; zero="7" _verify_l2_bitmap 8
880
+alloc="13 18"; zero="6 7" _verify_l2_bitmap 9
881
+
882
+echo
883
+echo "### Test concurrent requests ###"
884
+echo
885
+
886
+_concurrent_io()
887
+{
888
+# Allocate three subclusters in the same cluster.
889
+# This works because handle_dependencies() checks whether the requests
890
+# allocate the same cluster, even if the COW regions don't overlap (in
891
+# this case they don't).
892
+cat <<EOF
893
+open -o driver=$IMGFMT blkdebug::$TEST_IMG
894
+break write_aio A
895
+aio_write -P 10 30k 2k
896
+wait_break A
897
+aio_write -P 11 20k 2k
898
+aio_write -P 12 40k 2k
899
+resume A
900
+aio_flush
901
+EOF
902
+}
903
+
904
+_concurrent_verify()
905
+{
906
+cat <<EOF
907
+open -o driver=$IMGFMT $TEST_IMG
908
+read -q -P 10 30k 2k
909
+read -q -P 11 20k 2k
910
+read -q -P 12 40k 2k
911
+EOF
912
+}
913
+
914
+_make_test_img -o extended_l2=on 1M
915
+_concurrent_io | $QEMU_IO | _filter_qemu_io
916
+_concurrent_verify | $QEMU_IO | _filter_qemu_io
917
+
918
+# success, all done
919
+echo "*** done"
920
+rm -f $seq.full
921
+status=0
922
diff --git a/tests/qemu-iotests/271.out b/tests/qemu-iotests/271.out
923
new file mode 100644
924
index XXXXXXX..XXXXXXX
925
--- /dev/null
926
+++ b/tests/qemu-iotests/271.out
927
@@ -XXX,XX +XXX,XX @@
928
+QA output created by 271
929
+
930
+### Standard write tests (backing file: yes) ###
931
+
932
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
933
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=1048576
934
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
935
+write -q -P PATTERN 0 1k
936
+L2 entry #0: 0x8000000000050000 0000000000000001
937
+write -q -P PATTERN 3k 512
938
+L2 entry #0: 0x8000000000050000 0000000000000003
939
+write -q -P PATTERN 5k 1k
940
+L2 entry #0: 0x8000000000050000 0000000000000007
941
+write -q -P PATTERN 6k 2k
942
+L2 entry #0: 0x8000000000050000 000000000000000f
943
+write -q -P PATTERN 8k 6k
944
+L2 entry #0: 0x8000000000050000 000000000000007f
945
+write -q -P PATTERN 15k 4k
946
+L2 entry #0: 0x8000000000050000 00000000000003ff
947
+write -q -P PATTERN 32k 1k
948
+L2 entry #0: 0x8000000000050000 00000000000103ff
949
+write -q -P PATTERN 63k 4k
950
+L2 entry #0: 0x8000000000050000 00000000800103ff
951
+L2 entry #1: 0x8000000000060000 0000000000000003
952
+write -q -z 2k 2k
953
+L2 entry #0: 0x8000000000050000 00000002800103fd
954
+write -q -z 0 64k
955
+L2 entry #0: 0x8000000000050000 ffffffff00000000
956
+write -q -P PATTERN 0 64k
957
+L2 entry #0: 0x8000000000050000 00000000ffffffff
958
+write -q -z -u 0 32k
959
+L2 entry #0: 0x8000000000050000 0000ffffffff0000
960
+write -q -z -u 0 64k
961
+L2 entry #0: 0x0000000000000000 ffffffff00000000
962
+write -q -P PATTERN 3k 512
963
+L2 entry #0: 0x8000000000050000 fffffffd00000002
964
+write -q -P PATTERN 0 64k
965
+L2 entry #0: 0x8000000000050000 00000000ffffffff
966
+discard -q 0 64k
967
+L2 entry #0: 0x0000000000000000 ffffffff00000000
968
+write -q -c -P PATTERN 0 64k
969
+L2 entry #0: 0x4000000000050000 0000000000000000
970
+write -q -P PATTERN 3k 512
971
+L2 entry #0: 0x8000000000070000 00000000ffffffff
972
+
973
+### Standard write tests (backing file: no) ###
974
+
975
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
976
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
977
+write -q -P PATTERN 0 1k
978
+L2 entry #0: 0x8000000000050000 0000000000000001
979
+write -q -P PATTERN 3k 512
980
+L2 entry #0: 0x8000000000050000 0000000000000003
981
+write -q -P PATTERN 5k 1k
982
+L2 entry #0: 0x8000000000050000 0000000000000007
983
+write -q -P PATTERN 6k 2k
984
+L2 entry #0: 0x8000000000050000 000000000000000f
985
+write -q -P PATTERN 8k 6k
986
+L2 entry #0: 0x8000000000050000 000000000000007f
987
+write -q -P PATTERN 15k 4k
988
+L2 entry #0: 0x8000000000050000 00000000000003ff
989
+write -q -P PATTERN 32k 1k
990
+L2 entry #0: 0x8000000000050000 00000000000103ff
991
+write -q -P PATTERN 63k 4k
992
+L2 entry #0: 0x8000000000050000 00000000800103ff
993
+L2 entry #1: 0x8000000000060000 0000000000000003
994
+write -q -z 2k 2k
995
+L2 entry #0: 0x8000000000050000 00000002800103fd
996
+write -q -z 0 64k
997
+L2 entry #0: 0x8000000000050000 ffffffff00000000
998
+write -q -P PATTERN 0 64k
999
+L2 entry #0: 0x8000000000050000 00000000ffffffff
1000
+write -q -z -u 0 32k
1001
+L2 entry #0: 0x8000000000050000 0000ffffffff0000
1002
+write -q -z -u 0 64k
1003
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1004
+write -q -P PATTERN 3k 512
1005
+L2 entry #0: 0x8000000000050000 fffffffd00000002
1006
+write -q -P PATTERN 0 64k
1007
+L2 entry #0: 0x8000000000050000 00000000ffffffff
1008
+discard -q 0 64k
1009
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1010
+write -q -c -P PATTERN 0 64k
1011
+L2 entry #0: 0x4000000000050000 0000000000000000
1012
+write -q -P PATTERN 3k 512
1013
+L2 entry #0: 0x8000000000070000 00000000ffffffff
1014
+
1015
+### Overwriting several clusters without COW ###
1016
+
1017
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=1048576
1018
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1019
+write -q -P PATTERN 24k 40k
1020
+L2 entry #0: 0x8000000000050000 00000000fffff000
1021
+write -q -P PATTERN 90k 2k
1022
+L2 entry #1: 0x8000000000060000 0000000000002000
1023
+write -q -P PATTERN 156k 2k
1024
+L2 entry #2: 0x8000000000070000 0000000000004000
1025
+write -q -z 156k 2k
1026
+L2 entry #2: 0x8000000000070000 0000400000000000
1027
+write -q -P PATTERN 192k 34k
1028
+L2 entry #3: 0x8000000000080000 000000000001ffff
1029
+write -q -P PATTERN 24k 192k
1030
+L2 entry #0: 0x8000000000050000 00000000fffff000
1031
+L2 entry #1: 0x8000000000060000 00000000ffffffff
1032
+L2 entry #2: 0x8000000000070000 00000000ffffffff
1033
+L2 entry #3: 0x8000000000080000 000000000001ffff
1034
+
1035
+### Writing zeroes 1: unallocated clusters (backing file: yes) ###
1036
+
1037
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
1038
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=2132992
1039
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1040
+write -q -z 0 192k
1041
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1042
+L2 entry #1: 0x0000000000000000 ffffffff00000000
1043
+L2 entry #2: 0x0000000000000000 ffffffff00000000
1044
+write -q -z 224k 128k
1045
+L2 entry #3: 0x0000000000000000 ffff000000000000
1046
+L2 entry #4: 0x0000000000000000 ffffffff00000000
1047
+L2 entry #5: 0x0000000000000000 0000ffff00000000
1048
+write -q -z 415k 128k
1049
+L2 entry #6: 0x8000000000050000 ffff000000008000
1050
+L2 entry #7: 0x0000000000000000 ffffffff00000000
1051
+L2 entry #8: 0x8000000000060000 00007fff00008000
1052
+
1053
+### Writing zeroes 2: allocated clusters (backing file: yes) ###
1054
+
1055
+write -q -P PATTERN 576k 576k
1056
+L2 entry #9: 0x8000000000070000 00000000ffffffff
1057
+L2 entry #10: 0x8000000000080000 00000000ffffffff
1058
+L2 entry #11: 0x8000000000090000 00000000ffffffff
1059
+L2 entry #12: 0x80000000000a0000 00000000ffffffff
1060
+L2 entry #13: 0x80000000000b0000 00000000ffffffff
1061
+L2 entry #14: 0x80000000000c0000 00000000ffffffff
1062
+L2 entry #15: 0x80000000000d0000 00000000ffffffff
1063
+L2 entry #16: 0x80000000000e0000 00000000ffffffff
1064
+L2 entry #17: 0x80000000000f0000 00000000ffffffff
1065
+write -q -z 576k 192k
1066
+L2 entry #9: 0x8000000000070000 ffffffff00000000
1067
+L2 entry #10: 0x8000000000080000 ffffffff00000000
1068
+L2 entry #11: 0x8000000000090000 ffffffff00000000
1069
+write -q -z 800k 128k
1070
+L2 entry #12: 0x80000000000a0000 ffff00000000ffff
1071
+L2 entry #13: 0x80000000000b0000 ffffffff00000000
1072
+L2 entry #14: 0x80000000000c0000 0000ffffffff0000
1073
+write -q -z 991k 128k
1074
+L2 entry #15: 0x80000000000d0000 ffff00000000ffff
1075
+L2 entry #16: 0x80000000000e0000 ffffffff00000000
1076
+L2 entry #17: 0x80000000000f0000 00007fffffff8000
1077
+
1078
+### Writing zeroes 3: compressed clusters (backing file: yes) ###
1079
+
1080
+write -q -c -P PATTERN 1152k 64k
1081
+L2 entry #18: 0x4000000000100000 0000000000000000
1082
+write -q -c -P PATTERN 1216k 64k
1083
+L2 entry #19: 0x4000000000110000 0000000000000000
1084
+write -q -c -P PATTERN 1280k 64k
1085
+L2 entry #20: 0x4000000000120000 0000000000000000
1086
+write -q -c -P PATTERN 1344k 64k
1087
+L2 entry #21: 0x4000000000130000 0000000000000000
1088
+write -q -c -P PATTERN 1408k 64k
1089
+L2 entry #22: 0x4000000000140000 0000000000000000
1090
+write -q -c -P PATTERN 1472k 64k
1091
+L2 entry #23: 0x4000000000150000 0000000000000000
1092
+write -q -c -P PATTERN 1536k 64k
1093
+L2 entry #24: 0x4000000000160000 0000000000000000
1094
+write -q -c -P PATTERN 1600k 64k
1095
+L2 entry #25: 0x4000000000170000 0000000000000000
1096
+write -q -c -P PATTERN 1664k 64k
1097
+L2 entry #26: 0x4000000000180000 0000000000000000
1098
+write -q -c -P PATTERN 1728k 64k
1099
+L2 entry #27: 0x4000000000190000 0000000000000000
1100
+write -q -c -P PATTERN 1792k 64k
1101
+L2 entry #28: 0x40000000001a0000 0000000000000000
1102
+write -q -z 1152k 192k
1103
+L2 entry #18: 0x0000000000000000 ffffffff00000000
1104
+L2 entry #19: 0x0000000000000000 ffffffff00000000
1105
+L2 entry #20: 0x0000000000000000 ffffffff00000000
1106
+write -q -z 1376k 128k
1107
+L2 entry #21: 0x8000000000100000 00000000ffffffff
1108
+L2 entry #22: 0x8000000000110000 00000000ffffffff
1109
+L2 entry #23: 0x8000000000120000 00000000ffffffff
1110
+write -q -z 1567k 129k
1111
+L2 entry #24: 0x8000000000130000 00000000ffffffff
1112
+L2 entry #25: 0x8000000000140000 00000000ffffffff
1113
+L2 entry #26: 0x8000000000150000 00000000ffffffff
1114
+write -q -z 1759k 128k
1115
+L2 entry #27: 0x8000000000160000 ffff00000000ffff
1116
+L2 entry #28: 0x0000000000000000 ffffffff00000000
1117
+L2 entry #29: 0x8000000000170000 00007fff00008000
1118
+
1119
+### Writing zeroes 4: other tests (backing file: yes) ###
1120
+
1121
+write -q -z 1951k 8k
1122
+L2 entry #30: 0x8000000000180000 0007000000088000
1123
+write -q -z 2048k 35k
1124
+L2 entry #32: 0x0000000000000000 0003ffff00000000
1125
+
1126
+### Writing zeroes 1: unallocated clusters (backing file: no) ###
1127
+
1128
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
1129
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992
1130
+write -q -z 0 192k
1131
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1132
+L2 entry #1: 0x0000000000000000 ffffffff00000000
1133
+L2 entry #2: 0x0000000000000000 ffffffff00000000
1134
+write -q -z 224k 128k
1135
+L2 entry #3: 0x0000000000000000 ffff000000000000
1136
+L2 entry #4: 0x0000000000000000 ffffffff00000000
1137
+L2 entry #5: 0x0000000000000000 0000ffff00000000
1138
+write -q -z 415k 128k
1139
+L2 entry #6: 0x0000000000000000 ffff800000000000
1140
+L2 entry #7: 0x0000000000000000 ffffffff00000000
1141
+L2 entry #8: 0x0000000000000000 0000ffff00000000
1142
+
1143
+### Writing zeroes 2: allocated clusters (backing file: no) ###
1144
+
1145
+write -q -P PATTERN 576k 576k
1146
+L2 entry #9: 0x8000000000050000 00000000ffffffff
1147
+L2 entry #10: 0x8000000000060000 00000000ffffffff
1148
+L2 entry #11: 0x8000000000070000 00000000ffffffff
1149
+L2 entry #12: 0x8000000000080000 00000000ffffffff
1150
+L2 entry #13: 0x8000000000090000 00000000ffffffff
1151
+L2 entry #14: 0x80000000000a0000 00000000ffffffff
1152
+L2 entry #15: 0x80000000000b0000 00000000ffffffff
1153
+L2 entry #16: 0x80000000000c0000 00000000ffffffff
1154
+L2 entry #17: 0x80000000000d0000 00000000ffffffff
1155
+write -q -z 576k 192k
1156
+L2 entry #9: 0x8000000000050000 ffffffff00000000
1157
+L2 entry #10: 0x8000000000060000 ffffffff00000000
1158
+L2 entry #11: 0x8000000000070000 ffffffff00000000
1159
+write -q -z 800k 128k
1160
+L2 entry #12: 0x8000000000080000 ffff00000000ffff
1161
+L2 entry #13: 0x8000000000090000 ffffffff00000000
1162
+L2 entry #14: 0x80000000000a0000 0000ffffffff0000
1163
+write -q -z 991k 128k
1164
+L2 entry #15: 0x80000000000b0000 ffff00000000ffff
1165
+L2 entry #16: 0x80000000000c0000 ffffffff00000000
1166
+L2 entry #17: 0x80000000000d0000 00007fffffff8000
1167
+
1168
+### Writing zeroes 3: compressed clusters (backing file: no) ###
1169
+
1170
+write -q -c -P PATTERN 1152k 64k
1171
+L2 entry #18: 0x40000000000e0000 0000000000000000
1172
+write -q -c -P PATTERN 1216k 64k
1173
+L2 entry #19: 0x40000000000f0000 0000000000000000
1174
+write -q -c -P PATTERN 1280k 64k
1175
+L2 entry #20: 0x4000000000100000 0000000000000000
1176
+write -q -c -P PATTERN 1344k 64k
1177
+L2 entry #21: 0x4000000000110000 0000000000000000
1178
+write -q -c -P PATTERN 1408k 64k
1179
+L2 entry #22: 0x4000000000120000 0000000000000000
1180
+write -q -c -P PATTERN 1472k 64k
1181
+L2 entry #23: 0x4000000000130000 0000000000000000
1182
+write -q -c -P PATTERN 1536k 64k
1183
+L2 entry #24: 0x4000000000140000 0000000000000000
1184
+write -q -c -P PATTERN 1600k 64k
1185
+L2 entry #25: 0x4000000000150000 0000000000000000
1186
+write -q -c -P PATTERN 1664k 64k
1187
+L2 entry #26: 0x4000000000160000 0000000000000000
1188
+write -q -c -P PATTERN 1728k 64k
1189
+L2 entry #27: 0x4000000000170000 0000000000000000
1190
+write -q -c -P PATTERN 1792k 64k
1191
+L2 entry #28: 0x4000000000180000 0000000000000000
1192
+write -q -z 1152k 192k
1193
+L2 entry #18: 0x0000000000000000 ffffffff00000000
1194
+L2 entry #19: 0x0000000000000000 ffffffff00000000
1195
+L2 entry #20: 0x0000000000000000 ffffffff00000000
1196
+write -q -z 1376k 128k
1197
+L2 entry #21: 0x80000000000e0000 00000000ffffffff
1198
+L2 entry #22: 0x80000000000f0000 00000000ffffffff
1199
+L2 entry #23: 0x8000000000100000 00000000ffffffff
1200
+write -q -z 1567k 129k
1201
+L2 entry #24: 0x8000000000110000 00000000ffffffff
1202
+L2 entry #25: 0x8000000000120000 00000000ffffffff
1203
+L2 entry #26: 0x8000000000130000 00000000ffffffff
1204
+write -q -z 1759k 128k
1205
+L2 entry #27: 0x8000000000140000 ffff00000000ffff
1206
+L2 entry #28: 0x0000000000000000 ffffffff00000000
1207
+L2 entry #29: 0x0000000000000000 0000ffff00000000
1208
+
1209
+### Writing zeroes 4: other tests (backing file: no) ###
1210
+
1211
+write -q -z 1951k 8k
1212
+L2 entry #30: 0x0000000000000000 000f800000000000
1213
+write -q -z 2048k 35k
1214
+L2 entry #32: 0x0000000000000000 0003ffff00000000
1215
+
1216
+### Zero + unmap 1: allocated clusters (backing file: yes) ###
1217
+
1218
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
1219
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=2132992
1220
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1221
+write -q -P PATTERN 576k 576k
1222
+L2 entry #9: 0x8000000000050000 00000000ffffffff
1223
+L2 entry #10: 0x8000000000060000 00000000ffffffff
1224
+L2 entry #11: 0x8000000000070000 00000000ffffffff
1225
+L2 entry #12: 0x8000000000080000 00000000ffffffff
1226
+L2 entry #13: 0x8000000000090000 00000000ffffffff
1227
+L2 entry #14: 0x80000000000a0000 00000000ffffffff
1228
+L2 entry #15: 0x80000000000b0000 00000000ffffffff
1229
+L2 entry #16: 0x80000000000c0000 00000000ffffffff
1230
+L2 entry #17: 0x80000000000d0000 00000000ffffffff
1231
+write -q -z -u 576k 192k
1232
+L2 entry #9: 0x0000000000000000 ffffffff00000000
1233
+L2 entry #10: 0x0000000000000000 ffffffff00000000
1234
+L2 entry #11: 0x0000000000000000 ffffffff00000000
1235
+write -q -z -u 800k 128k
1236
+L2 entry #12: 0x8000000000080000 ffff00000000ffff
1237
+L2 entry #13: 0x0000000000000000 ffffffff00000000
1238
+L2 entry #14: 0x80000000000a0000 0000ffffffff0000
1239
+write -q -z -u 991k 128k
1240
+L2 entry #15: 0x80000000000b0000 ffff00000000ffff
1241
+L2 entry #16: 0x0000000000000000 ffffffff00000000
1242
+L2 entry #17: 0x80000000000d0000 00007fffffff8000
1243
+
1244
+### Zero + unmap 2: compressed clusters (backing file: yes) ###
1245
+
1246
+write -q -c -P PATTERN 1152k 64k
1247
+L2 entry #18: 0x4000000000050000 0000000000000000
1248
+write -q -c -P PATTERN 1216k 64k
1249
+L2 entry #19: 0x4000000000060000 0000000000000000
1250
+write -q -c -P PATTERN 1280k 64k
1251
+L2 entry #20: 0x4000000000070000 0000000000000000
1252
+write -q -c -P PATTERN 1344k 64k
1253
+L2 entry #21: 0x4000000000090000 0000000000000000
1254
+write -q -c -P PATTERN 1408k 64k
1255
+L2 entry #22: 0x40000000000c0000 0000000000000000
1256
+write -q -c -P PATTERN 1472k 64k
1257
+L2 entry #23: 0x40000000000e0000 0000000000000000
1258
+write -q -c -P PATTERN 1536k 64k
1259
+L2 entry #24: 0x40000000000f0000 0000000000000000
1260
+write -q -c -P PATTERN 1600k 64k
1261
+L2 entry #25: 0x4000000000100000 0000000000000000
1262
+write -q -c -P PATTERN 1664k 64k
1263
+L2 entry #26: 0x4000000000110000 0000000000000000
1264
+write -q -c -P PATTERN 1728k 64k
1265
+L2 entry #27: 0x4000000000120000 0000000000000000
1266
+write -q -c -P PATTERN 1792k 64k
1267
+L2 entry #28: 0x4000000000130000 0000000000000000
1268
+write -q -z -u 1152k 192k
1269
+L2 entry #18: 0x0000000000000000 ffffffff00000000
1270
+L2 entry #19: 0x0000000000000000 ffffffff00000000
1271
+L2 entry #20: 0x0000000000000000 ffffffff00000000
1272
+write -q -z -u 1376k 128k
1273
+L2 entry #21: 0x8000000000050000 00000000ffffffff
1274
+L2 entry #22: 0x8000000000060000 00000000ffffffff
1275
+L2 entry #23: 0x8000000000070000 00000000ffffffff
1276
+write -q -z -u 1567k 129k
1277
+L2 entry #24: 0x8000000000090000 00000000ffffffff
1278
+L2 entry #25: 0x80000000000e0000 00000000ffffffff
1279
+L2 entry #26: 0x80000000000f0000 00000000ffffffff
1280
+write -q -z -u 1759k 128k
1281
+L2 entry #27: 0x80000000000c0000 ffff00000000ffff
1282
+L2 entry #28: 0x0000000000000000 ffffffff00000000
1283
+L2 entry #29: 0x8000000000100000 00007fff00008000
1284
+
1285
+### Zero + unmap 1: allocated clusters (backing file: no) ###
1286
+
1287
+Formatting 'TEST_DIR/t.IMGFMT.raw', fmt=raw size=2132992
1288
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2132992
1289
+write -q -P PATTERN 576k 576k
1290
+L2 entry #9: 0x8000000000050000 00000000ffffffff
1291
+L2 entry #10: 0x8000000000060000 00000000ffffffff
1292
+L2 entry #11: 0x8000000000070000 00000000ffffffff
1293
+L2 entry #12: 0x8000000000080000 00000000ffffffff
1294
+L2 entry #13: 0x8000000000090000 00000000ffffffff
1295
+L2 entry #14: 0x80000000000a0000 00000000ffffffff
1296
+L2 entry #15: 0x80000000000b0000 00000000ffffffff
1297
+L2 entry #16: 0x80000000000c0000 00000000ffffffff
1298
+L2 entry #17: 0x80000000000d0000 00000000ffffffff
1299
+write -q -z -u 576k 192k
1300
+L2 entry #9: 0x0000000000000000 ffffffff00000000
1301
+L2 entry #10: 0x0000000000000000 ffffffff00000000
1302
+L2 entry #11: 0x0000000000000000 ffffffff00000000
1303
+write -q -z -u 800k 128k
1304
+L2 entry #12: 0x8000000000080000 ffff00000000ffff
1305
+L2 entry #13: 0x0000000000000000 ffffffff00000000
1306
+L2 entry #14: 0x80000000000a0000 0000ffffffff0000
1307
+write -q -z -u 991k 128k
1308
+L2 entry #15: 0x80000000000b0000 ffff00000000ffff
1309
+L2 entry #16: 0x0000000000000000 ffffffff00000000
1310
+L2 entry #17: 0x80000000000d0000 00007fffffff8000
1311
+
1312
+### Zero + unmap 2: compressed clusters (backing file: no) ###
1313
+
1314
+write -q -c -P PATTERN 1152k 64k
1315
+L2 entry #18: 0x4000000000050000 0000000000000000
1316
+write -q -c -P PATTERN 1216k 64k
1317
+L2 entry #19: 0x4000000000060000 0000000000000000
1318
+write -q -c -P PATTERN 1280k 64k
1319
+L2 entry #20: 0x4000000000070000 0000000000000000
1320
+write -q -c -P PATTERN 1344k 64k
1321
+L2 entry #21: 0x4000000000090000 0000000000000000
1322
+write -q -c -P PATTERN 1408k 64k
1323
+L2 entry #22: 0x40000000000c0000 0000000000000000
1324
+write -q -c -P PATTERN 1472k 64k
1325
+L2 entry #23: 0x40000000000e0000 0000000000000000
1326
+write -q -c -P PATTERN 1536k 64k
1327
+L2 entry #24: 0x40000000000f0000 0000000000000000
1328
+write -q -c -P PATTERN 1600k 64k
1329
+L2 entry #25: 0x4000000000100000 0000000000000000
1330
+write -q -c -P PATTERN 1664k 64k
1331
+L2 entry #26: 0x4000000000110000 0000000000000000
1332
+write -q -c -P PATTERN 1728k 64k
1333
+L2 entry #27: 0x4000000000120000 0000000000000000
1334
+write -q -c -P PATTERN 1792k 64k
1335
+L2 entry #28: 0x4000000000130000 0000000000000000
1336
+write -q -z -u 1152k 192k
1337
+L2 entry #18: 0x0000000000000000 ffffffff00000000
1338
+L2 entry #19: 0x0000000000000000 ffffffff00000000
1339
+L2 entry #20: 0x0000000000000000 ffffffff00000000
1340
+write -q -z -u 1376k 128k
1341
+L2 entry #21: 0x8000000000050000 00000000ffffffff
1342
+L2 entry #22: 0x8000000000060000 00000000ffffffff
1343
+L2 entry #23: 0x8000000000070000 00000000ffffffff
1344
+write -q -z -u 1567k 129k
1345
+L2 entry #24: 0x8000000000090000 00000000ffffffff
1346
+L2 entry #25: 0x80000000000e0000 00000000ffffffff
1347
+L2 entry #26: 0x80000000000f0000 00000000ffffffff
1348
+write -q -z -u 1759k 128k
1349
+L2 entry #27: 0x80000000000c0000 ffff00000000ffff
1350
+L2 entry #28: 0x0000000000000000 ffffffff00000000
1351
+L2 entry #29: 0x0000000000000000 0000ffff00000000
1352
+
1353
+### Discarding clusters with non-zero bitmaps (backing file: yes) ###
1354
+
1355
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1356
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1357
+L2 entry #1: 0x0000000000000000 ffffffff00000000
1358
+Image resized.
1359
+Image resized.
1360
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1361
+L2 entry #1: 0x0000000000000000 ffffffff00000000
1362
+
1363
+### Discarding clusters with non-zero bitmaps (backing file: no) ###
1364
+
1365
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1366
+L2 entry #0: 0x0000000000000000 ffffffff00000000
1367
+L2 entry #1: 0x0000000000000000 ffffffff00000000
1368
+Image resized.
1369
+Image resized.
1370
+L2 entry #0: 0x0000000000000000 0000ffff00000000
1371
+L2 entry #1: 0x0000000000000000 0000000000000000
1372
+
1373
+### Corrupted L2 entries - read test (allocated) ###
1374
+
1375
+# 'cluster is zero' bit set on the standard cluster descriptor
1376
+
1377
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1378
+L2 entry #0: 0x8000000000050001 0000000000000001
1379
+L2 entry #0: 0x8000000000050001 0000000000000001
1380
+
1381
+# Both 'subcluster is zero' and 'subcluster is allocated' bits set
1382
+
1383
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1384
+L2 entry #1: 0x8000000000060000 00000001ffffffff
1385
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
1386
+read failed: Input/output error
1387
+
1388
+### Corrupted L2 entries - read test (unallocated) ###
1389
+
1390
+# 'cluster is zero' bit set on the standard cluster descriptor
1391
+
1392
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1393
+L2 entry #0: 0x0000000000000001 0000000000000000
1394
+L2 entry #0: 0x0000000000000001 0000000000000000
1395
+
1396
+# 'subcluster is allocated' bit set
1397
+
1398
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1399
+L2 entry #0: 0x0000000000000000 0000000000000001
1400
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
1401
+read failed: Input/output error
1402
+
1403
+# Both 'subcluster is zero' and 'subcluster is allocated' bits set
1404
+
1405
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1406
+L2 entry #1: 0x0000000000000000 0000000100000001
1407
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
1408
+read failed: Input/output error
1409
+
1410
+### Compressed cluster with subcluster bitmap != 0 - read test ###
1411
+
1412
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1413
+L2 entry #0: 0x4000000000050000 0000000180000000
1414
+read 65536/65536 bytes at offset 0
1415
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1416
+L2 entry #0: 0x4000000000050000 0000000180000000
1417
+
1418
+### Corrupted L2 entries - write test (allocated) ###
1419
+
1420
+# 'cluster is zero' bit set on the standard cluster descriptor
1421
+
1422
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1423
+L2 entry #0: 0x8000000000050001 0000000000000001
1424
+L2 entry #0: 0x8000000000050001 0000000000000001
1425
+
1426
+# Both 'subcluster is zero' and 'subcluster is allocated' bits set
1427
+
1428
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1429
+L2 entry #1: 0x8000000000060000 00000001ffffffff
1430
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
1431
+write failed: Input/output error
1432
+
1433
+### Corrupted L2 entries - write test (unallocated) ###
1434
+
1435
+# 'cluster is zero' bit set on the standard cluster descriptor
1436
+
1437
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1438
+L2 entry #0: 0x0000000000000001 0000000000000000
1439
+L2 entry #0: 0x8000000000060000 0000000000000001
1440
+
1441
+# 'subcluster is allocated' bit set
1442
+
1443
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1444
+L2 entry #0: 0x0000000000000000 0000000000000001
1445
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
1446
+write failed: Input/output error
1447
+
1448
+# Both 'subcluster is zero' and 'subcluster is allocated' bits set
1449
+
1450
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1451
+L2 entry #1: 0x0000000000000000 0000000100000001
1452
+qcow2: Marking image as corrupt: Invalid cluster entry found (L2 offset: 0x40000, L2 index: 0x1); further corruption events will be suppressed
1453
+write failed: Input/output error
1454
+
1455
+### Compressed cluster with subcluster bitmap != 0 - write test ###
1456
+
1457
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1458
+L2 entry #0: 0x4000000000050000 0000000180000000
1459
+wrote 65536/65536 bytes at offset 0
1460
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1461
+L2 entry #0: 0x8000000000060000 00000000ffffffff
1462
+
1463
+### Detect and repair unaligned clusters ###
1464
+
1465
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072
1466
+# Corrupted L2 entry, allocated subcluster #
1467
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1468
+ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
1469
+ERROR cluster 6 refcount=0 reference=1
1470
+Rebuilding refcount structure
1471
+ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
1472
+Repairing cluster 1 refcount=1 reference=0
1473
+Repairing cluster 2 refcount=1 reference=0
1474
+ERROR offset=50200: Data cluster is not properly aligned; L2 entry corrupted.
1475
+The following inconsistencies were found and repaired:
1476
+
1477
+ 0 leaked clusters
1478
+ 1 corruptions
1479
+
1480
+Double checking the fixed image now...
1481
+
1482
+1 errors were found on the image.
1483
+Data may be corrupted, or further writes to the image may corrupt it.
1484
+qcow2: Marking image as corrupt: Cluster allocation offset 0x50200 unaligned (L2 offset: 0x40000, L2 index: 0); further corruption events will be suppressed
1485
+read failed: Input/output error
1486
+# Corrupted L2 entry, no allocated subclusters #
1487
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1488
+Repairing offset=50200: Preallocated cluster is not properly aligned; L2 entry corrupted.
1489
+Leaked cluster 5 refcount=1 reference=0
1490
+Repairing cluster 5 refcount=1 reference=0
1491
+The following inconsistencies were found and repaired:
1492
+
1493
+ 1 leaked clusters
1494
+ 1 corruptions
1495
+
1496
+Double checking the fixed image now...
1497
+No errors were found on the image.
1498
+
1499
+### Image creation options ###
1500
+
1501
+# cluster_size < 16k
1502
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1503
+qemu-img: TEST_DIR/t.IMGFMT: Extended L2 entries are only supported with cluster sizes of at least 16384 bytes
1504
+# backing file and preallocation=metadata
1505
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=1048576
1506
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=metadata
1507
+Image resized.
1508
+read 524288/524288 bytes at offset 0
1509
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1510
+read 524288/524288 bytes at offset 524288
1511
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1512
+Offset Length Mapped to File
1513
+0 0x80000 0 TEST_DIR/t.qcow2.base
1514
+# backing file and preallocation=falloc
1515
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=falloc
1516
+Image resized.
1517
+read 524288/524288 bytes at offset 0
1518
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1519
+read 524288/524288 bytes at offset 524288
1520
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1521
+Offset Length Mapped to File
1522
+0 0x80000 0 TEST_DIR/t.qcow2.base
1523
+# backing file and preallocation=full
1524
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=524288 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw preallocation=full
1525
+Image resized.
1526
+read 524288/524288 bytes at offset 0
1527
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1528
+read 524288/524288 bytes at offset 524288
1529
+512 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1530
+Offset Length Mapped to File
1531
+0 0x80000 0 TEST_DIR/t.qcow2.base
1532
+
1533
+### Image resizing with preallocation and backing files ###
1534
+
1535
+# resize --preallocation=metadata
1536
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1537
+Image resized.
1538
+read 515072/515072 bytes at offset 0
1539
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1540
+read 522240/522240 bytes at offset 515072
1541
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1542
+# resize --preallocation=falloc
1543
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1544
+Image resized.
1545
+read 515072/515072 bytes at offset 0
1546
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1547
+read 522240/522240 bytes at offset 515072
1548
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1549
+# resize --preallocation=full
1550
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw
1551
+Image resized.
1552
+read 515072/515072 bytes at offset 0
1553
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1554
+read 522240/522240 bytes at offset 515072
1555
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1556
+
1557
+### Image resizing with preallocation without backing files ###
1558
+
1559
+# resize --preallocation=metadata
1560
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
1561
+wrote 515072/515072 bytes at offset 0
1562
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1563
+Image resized.
1564
+read 515072/515072 bytes at offset 0
1565
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1566
+read 522240/522240 bytes at offset 515072
1567
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1568
+# resize --preallocation=falloc
1569
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
1570
+wrote 515072/515072 bytes at offset 0
1571
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1572
+Image resized.
1573
+read 515072/515072 bytes at offset 0
1574
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1575
+read 522240/522240 bytes at offset 515072
1576
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1577
+# resize --preallocation=full
1578
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=515072
1579
+wrote 515072/515072 bytes at offset 0
1580
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1581
+Image resized.
1582
+read 515072/515072 bytes at offset 0
1583
+503 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1584
+read 522240/522240 bytes at offset 515072
1585
+510 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1586
+
1587
+### qemu-img measure ###
1588
+
1589
+# 512MB, extended_l2=off
1590
+required size: 327680
1591
+fully allocated size: 537198592
1592
+# 512MB, extended_l2=on
1593
+required size: 393216
1594
+fully allocated size: 537264128
1595
+# 16K clusters, 64GB, extended_l2=off
1596
+required size: 42008576
1597
+fully allocated size: 68761485312
1598
+# 16K clusters, 64GB, extended_l2=on
1599
+required size: 75579392
1600
+fully allocated size: 68795056128
1601
+# 8k clusters
1602
+qemu-img: Extended L2 entries are only supported with cluster sizes of at least 16384 bytes
1603
+# 1024 TB
1604
+required size: 309285027840
1605
+fully allocated size: 1126209191870464
1606
+# 1025 TB
1607
+qemu-img: The image size is too large (try using a larger cluster size)
1608
+
1609
+### qemu-img amend ###
1610
+
1611
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1612
+qemu-img: Invalid parameter 'extended_l2'
1613
+This option is only supported for image creation
1614
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1615
+qemu-img: Invalid parameter 'extended_l2'
1616
+This option is only supported for image creation
1617
+
1618
+### Test copy-on-write on an image with snapshots ###
1619
+
1620
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1621
+L2 entry #0: 0x8000000000050000 0000008000042000
1622
+L2 entry #1: 0x8000000000060000 0000008000042000
1623
+L2 entry #2: 0x8000000000070000 0000008000042000
1624
+L2 entry #3: 0x8000000000080000 0000008000042000
1625
+L2 entry #4: 0x8000000000090000 0000008000042000
1626
+L2 entry #5: 0x80000000000a0000 0000008000042000
1627
+L2 entry #6: 0x80000000000b0000 0000008000042000
1628
+L2 entry #7: 0x80000000000c0000 0000008000042000
1629
+L2 entry #8: 0x80000000000d0000 0000008000042000
1630
+L2 entry #9: 0x80000000000e0000 0000008000042000
1631
+L2 entry #0: 0x8000000000120000 000000800007e000
1632
+L2 entry #1: 0x8000000000130000 000000800007fc00
1633
+L2 entry #2: 0x8000000000140000 00000080001fe000
1634
+L2 entry #3: 0x8000000000150000 000000800007e000
1635
+L2 entry #4: 0x8000000000160000 000000000007ff80
1636
+L2 entry #5: 0x8000000000170000 000000000007ffff
1637
+L2 entry #6: 0x00000000000b0000 0001808000042000
1638
+L2 entry #7: 0x00000000000c0000 0000208000040000
1639
+L2 entry #8: 0x8000000000180000 000000800007e000
1640
+L2 entry #9: 0x00000000000e0000 000000c000042000
1641
+
1642
+### Test concurrent requests ###
1643
+
1644
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
1645
+blkdebug: Suspended request 'A'
1646
+blkdebug: Resuming request 'A'
1647
+wrote 2048/2048 bytes at offset 30720
1648
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1649
+wrote 2048/2048 bytes at offset 20480
1650
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1651
+wrote 2048/2048 bytes at offset 40960
1652
+2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
1653
+*** done
1654
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
1655
index XXXXXXX..XXXXXXX 100644
1656
--- a/tests/qemu-iotests/group
1657
+++ b/tests/qemu-iotests/group
1658
@@ -XXX,XX +XXX,XX @@
1659
267 rw auto quick snapshot
1660
268 rw auto quick
1661
270 rw backing quick
1662
+271 rw auto
1663
272 rw
1664
273 backing quick
1665
274 rw backing
1666
--
1667
2.26.2
1668
1669
diff view generated by jsdifflib