1
The following changes since commit 36f87b4513373b3cd79c87c9197d17face95d4ac:
1
The following changes since commit ca61fa4b803e5d0abaf6f1ceb690f23bb78a4def:
2
2
3
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.10-20170630' into staging (2017-06-30 11:58:49 +0100)
3
Merge remote-tracking branch 'remotes/quic/tags/pull-hex-20211006' into staging (2021-10-06 12:11:14 -0700)
4
4
5
are available in the git repository at:
5
are available in the Git repository at:
6
6
7
git://github.com/famz/qemu.git tags/block-pull-request
7
https://gitlab.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to c61e684e44272f2acb2bef34cf2aa234582a73a9:
9
for you to fetch changes up to 1cc7eada97914f090125e588497986f6f7900514:
10
10
11
block: Exploit BDRV_BLOCK_EOF for larger zero blocks (2017-06-30 21:48:06 +0800)
11
iothread: use IOThreadParamInfo in iothread_[set|get]_param() (2021-10-07 15:29:50 +0100)
12
13
----------------------------------------------------------------
14
Pull request
12
15
13
----------------------------------------------------------------
16
----------------------------------------------------------------
14
17
15
Hi Peter,
18
Stefano Garzarella (2):
19
iothread: rename PollParamInfo to IOThreadParamInfo
20
iothread: use IOThreadParamInfo in iothread_[set|get]_param()
16
21
17
Here are Eric Blake's enhancement to block layer API. Thanks!
22
iothread.c | 28 +++++++++++++++-------------
18
23
1 file changed, 15 insertions(+), 13 deletions(-)
19
----------------------------------------------------------------
20
21
Eric Blake (2):
22
block: Add BDRV_BLOCK_EOF to bdrv_get_block_status()
23
block: Exploit BDRV_BLOCK_EOF for larger zero blocks
24
25
block/io.c | 42 +++++++++++++++++++++++++++++++++---------
26
include/block/block.h | 2 ++
27
tests/qemu-iotests/154 | 4 ----
28
tests/qemu-iotests/154.out | 12 ++++++------
29
4 files changed, 41 insertions(+), 19 deletions(-)
30
24
31
--
25
--
32
2.9.4
26
2.31.1
33
27
34
28
29
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
When we have a BDS with unallocated clusters, but asking the status
3
Commit 1793ad0247 ("iothread: add aio-max-batch parameter") added
4
of its underlying bs->file or backing layer encounters an end-of-file
4
a new parameter (aio-max-batch) to IOThread and used PollParamInfo
5
condition, we know that the rest of the unallocated area will read as
5
structure to handle it.
6
zeroes. However, pre-patch, this required two separate calls to
7
bdrv_get_block_status(), as the first call stops at the point where
8
the underlying file ends. Thanks to BDRV_BLOCK_EOF, we can now widen
9
the results of the primary status if the secondary status already
10
includes BDRV_BLOCK_ZERO.
11
6
12
In turn, this fixes a TODO mentioned in iotest 154, where we can now
7
Since it is not a parameter of the polling mechanism, we rename the
13
see that all sectors in a partial cluster at the end of a file read
8
structure to a more generic IOThreadParamInfo.
14
as zero when coupling the shorter backing file's status along with our
15
knowledge that the remaining sectors came from an unallocated cluster.
16
9
17
Also, note that the loop in bdrv_co_get_block_status_above() had an
10
Suggested-by: Kevin Wolf <kwolf@redhat.com>
18
inefficent exit: in cases where the active layer sets BDRV_BLOCK_ZERO
11
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
19
but does NOT set BDRV_BLOCK_ALLOCATED (namely, where we know we read
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
20
zeroes merely because our unallocated clusters lie beyond the backing
13
Message-id: 20210727145936.147032-2-sgarzare@redhat.com
21
file's shorter length), we still ended up probing the backing layer
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
22
even though we already had a good answer.
15
---
16
iothread.c | 14 +++++++-------
17
1 file changed, 7 insertions(+), 7 deletions(-)
23
18
24
Signed-off-by: Eric Blake <eblake@redhat.com>
19
diff --git a/iothread.c b/iothread.c
25
Message-Id: <20170505021500.19315-3-eblake@redhat.com>
26
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
27
Signed-off-by: Fam Zheng <famz@redhat.com>
28
---
29
block/io.c | 27 ++++++++++++++++++++++-----
30
tests/qemu-iotests/154 | 4 ----
31
tests/qemu-iotests/154.out | 12 ++++++------
32
3 files changed, 28 insertions(+), 15 deletions(-)
33
34
diff --git a/block/io.c b/block/io.c
35
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
36
--- a/block/io.c
21
--- a/iothread.c
37
+++ b/block/io.c
22
+++ b/iothread.c
38
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
23
@@ -XXX,XX +XXX,XX @@ static void iothread_complete(UserCreatable *obj, Error **errp)
39
/* Ignore errors. This is just providing extra information, it
24
typedef struct {
40
* is useful but not necessary.
25
const char *name;
41
*/
26
ptrdiff_t offset; /* field's byte offset in IOThread struct */
42
- if (!file_pnum) {
27
-} PollParamInfo;
43
- /* !file_pnum indicates an offset at or beyond the EOF; it is
28
+} IOThreadParamInfo;
44
- * perfectly valid for the format block driver to point to such
29
45
- * offsets, so catch it and mark everything as zero */
30
-static PollParamInfo poll_max_ns_info = {
46
+ if (ret2 & BDRV_BLOCK_EOF &&
31
+static IOThreadParamInfo poll_max_ns_info = {
47
+ (!file_pnum || ret2 & BDRV_BLOCK_ZERO)) {
32
"poll-max-ns", offsetof(IOThread, poll_max_ns),
48
+ /*
33
};
49
+ * It is valid for the format block driver to read
34
-static PollParamInfo poll_grow_info = {
50
+ * beyond the end of the underlying file's current
35
+static IOThreadParamInfo poll_grow_info = {
51
+ * size; such areas read as zero.
36
"poll-grow", offsetof(IOThread, poll_grow),
52
+ */
37
};
53
ret |= BDRV_BLOCK_ZERO;
38
-static PollParamInfo poll_shrink_info = {
54
} else {
39
+static IOThreadParamInfo poll_shrink_info = {
55
/* Limit request to the range reported by the protocol driver */
40
"poll-shrink", offsetof(IOThread, poll_shrink),
56
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status_above(BlockDriverState *bs,
41
};
42
-static PollParamInfo aio_max_batch_info = {
43
+static IOThreadParamInfo aio_max_batch_info = {
44
"aio-max-batch", offsetof(IOThread, aio_max_batch),
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static void iothread_get_param(Object *obj, Visitor *v,
48
const char *name, void *opaque, Error **errp)
57
{
49
{
58
BlockDriverState *p;
50
IOThread *iothread = IOTHREAD(obj);
59
int64_t ret = 0;
51
- PollParamInfo *info = opaque;
60
+ bool first = true;
52
+ IOThreadParamInfo *info = opaque;
61
53
int64_t *field = (void *)iothread + info->offset;
62
assert(bs != base);
54
63
for (p = bs; p != base; p = backing_bs(p)) {
55
visit_type_int64(v, name, field, errp);
64
ret = bdrv_co_get_block_status(p, sector_num, nb_sectors, pnum, file);
56
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
65
- if (ret < 0 || ret & BDRV_BLOCK_ALLOCATED) {
57
const char *name, void *opaque, Error **errp)
66
+ if (ret < 0) {
58
{
67
+ break;
59
IOThread *iothread = IOTHREAD(obj);
68
+ }
60
- PollParamInfo *info = opaque;
69
+ if (ret & BDRV_BLOCK_ZERO && ret & BDRV_BLOCK_EOF && !first) {
61
+ IOThreadParamInfo *info = opaque;
70
+ /*
62
int64_t *field = (void *)iothread + info->offset;
71
+ * Reading beyond the end of the file continues to read
63
int64_t value;
72
+ * zeroes, but we can only widen the result to the
64
73
+ * unallocated length we learned from an earlier
74
+ * iteration.
75
+ */
76
+ *pnum = nb_sectors;
77
+ }
78
+ if (ret & (BDRV_BLOCK_ZERO | BDRV_BLOCK_DATA)) {
79
break;
80
}
81
/* [sector_num, pnum] unallocated on this layer, which could be only
82
* the first part of [sector_num, nb_sectors]. */
83
nb_sectors = MIN(nb_sectors, *pnum);
84
+ first = false;
85
}
86
return ret;
87
}
88
diff --git a/tests/qemu-iotests/154 b/tests/qemu-iotests/154
89
index XXXXXXX..XXXXXXX 100755
90
--- a/tests/qemu-iotests/154
91
+++ b/tests/qemu-iotests/154
92
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
93
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
94
95
# Repeat with backing file holding unallocated cluster.
96
-# TODO: Note that this forces an allocation, because we aren't yet able to
97
-# quickly detect that reads beyond EOF of the backing file are always zero
98
CLUSTER_SIZE=2048 TEST_IMG="$TEST_IMG.base" _make_test_img $((size + 1024))
99
100
# Write at the front: sector-wise, the request is:
101
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "alloc $size 2048" "$TEST_IMG" | _filter_qemu_io
102
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
103
104
# Repeat with backing file holding zero'd cluster
105
-# TODO: Note that this forces an allocation, because we aren't yet able to
106
-# quickly detect that reads beyond EOF of the backing file are always zero
107
$QEMU_IO -c "write -z $size 512" "$TEST_IMG.base" | _filter_qemu_io
108
109
# Write at the front: sector-wise, the request is:
110
diff --git a/tests/qemu-iotests/154.out b/tests/qemu-iotests/154.out
111
index XXXXXXX..XXXXXXX 100644
112
--- a/tests/qemu-iotests/154.out
113
+++ b/tests/qemu-iotests/154.out
114
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 134217728
115
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
116
2048/2048 bytes allocated at offset 128 MiB
117
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
118
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
119
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
120
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
121
wrote 512/512 bytes at offset 134219264
122
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
123
2048/2048 bytes allocated at offset 128 MiB
124
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
125
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
126
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
127
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
128
wrote 1024/1024 bytes at offset 134218240
129
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
130
2048/2048 bytes allocated at offset 128 MiB
131
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
132
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
133
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
134
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
135
wrote 2048/2048 bytes at offset 134217728
136
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
137
@@ -XXX,XX +XXX,XX @@ wrote 512/512 bytes at offset 134217728
138
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
139
2048/2048 bytes allocated at offset 128 MiB
140
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
141
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
142
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
143
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
144
wrote 512/512 bytes at offset 134219264
145
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
146
2048/2048 bytes allocated at offset 128 MiB
147
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
148
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
149
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
150
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
151
wrote 1024/1024 bytes at offset 134218240
152
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
153
2048/2048 bytes allocated at offset 128 MiB
154
[{ "start": 0, "length": 134217728, "depth": 1, "zero": true, "data": false},
155
-{ "start": 134217728, "length": 2048, "depth": 0, "zero": false, "data": true, "offset": OFFSET}]
156
+{ "start": 134217728, "length": 2048, "depth": 0, "zero": true, "data": false}]
157
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134219776 backing_file=TEST_DIR/t.IMGFMT.base
158
wrote 2048/2048 bytes at offset 134217728
159
2 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
160
--
65
--
161
2.9.4
66
2.31.1
162
67
163
68
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Stefano Garzarella <sgarzare@redhat.com>
2
2
3
Just as the block layer already sets BDRV_BLOCK_ALLOCATED as a
3
Commit 0445409d74 ("iothread: generalize
4
shortcut for subsequent operations, there are also some optimizations
4
iothread_set_param/iothread_get_param") moved common code to set and
5
that are made easier if we can quickly tell that *pnum will advance
5
get IOThread parameters in two new functions.
6
us to the end of a file, via a new BDRV_BLOCK_EOF which gets set
7
by the block layer.
8
6
9
This just plumbs up the new bit; subsequent patches will make use
7
These functions are called inside callbacks, so we don't need to use an
10
of it.
8
opaque pointer. Let's replace `void *opaque` parameter with
9
`IOThreadParamInfo *info`.
11
10
12
Signed-off-by: Eric Blake <eblake@redhat.com>
11
Suggested-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20170505021500.19315-2-eblake@redhat.com>
12
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Fam Zheng <famz@redhat.com>
14
Message-id: 20210727145936.147032-3-sgarzare@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
16
---
17
block/io.c | 15 +++++++++++----
17
iothread.c | 18 ++++++++++--------
18
include/block/block.h | 2 ++
18
1 file changed, 10 insertions(+), 8 deletions(-)
19
2 files changed, 13 insertions(+), 4 deletions(-)
20
19
21
diff --git a/block/io.c b/block/io.c
20
diff --git a/iothread.c b/iothread.c
22
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
23
--- a/block/io.c
22
--- a/iothread.c
24
+++ b/block/io.c
23
+++ b/iothread.c
25
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvCoGetBlockStatusData {
24
@@ -XXX,XX +XXX,XX @@ static IOThreadParamInfo aio_max_batch_info = {
26
* Drivers not implementing the functionality are assumed to not support
25
};
27
* backing files, hence all their sectors are reported as allocated.
26
28
*
27
static void iothread_get_param(Object *obj, Visitor *v,
29
- * If 'sector_num' is beyond the end of the disk image the return value is 0
28
- const char *name, void *opaque, Error **errp)
30
- * and 'pnum' is set to 0.
29
+ const char *name, IOThreadParamInfo *info, Error **errp)
31
+ * If 'sector_num' is beyond the end of the disk image the return value is
30
{
32
+ * BDRV_BLOCK_EOF and 'pnum' is set to 0.
31
IOThread *iothread = IOTHREAD(obj);
33
*
32
- IOThreadParamInfo *info = opaque;
34
* 'pnum' is set to the number of sectors (including and immediately following
33
int64_t *field = (void *)iothread + info->offset;
35
* the specified sector) that are known to be in the same
34
36
* allocated/unallocated state.
35
visit_type_int64(v, name, field, errp);
37
*
36
}
38
* 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
37
39
- * beyond the end of the disk image it will be clamped.
38
static bool iothread_set_param(Object *obj, Visitor *v,
40
+ * beyond the end of the disk image it will be clamped; if 'pnum' is set to
39
- const char *name, void *opaque, Error **errp)
41
+ * the end of the image, then the returned value will include BDRV_BLOCK_EOF.
40
+ const char *name, IOThreadParamInfo *info, Error **errp)
42
*
41
{
43
* If returned value is positive and BDRV_BLOCK_OFFSET_VALID bit is set, 'file'
42
IOThread *iothread = IOTHREAD(obj);
44
* points to the BDS which the sector range is allocated in.
43
- IOThreadParamInfo *info = opaque;
45
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
44
int64_t *field = (void *)iothread + info->offset;
46
45
int64_t value;
47
if (sector_num >= total_sectors) {
46
48
*pnum = 0;
47
@@ -XXX,XX +XXX,XX @@ static bool iothread_set_param(Object *obj, Visitor *v,
49
- return 0;
48
static void iothread_get_poll_param(Object *obj, Visitor *v,
50
+ return BDRV_BLOCK_EOF;
49
const char *name, void *opaque, Error **errp)
50
{
51
+ IOThreadParamInfo *info = opaque;
52
53
- iothread_get_param(obj, v, name, opaque, errp);
54
+ iothread_get_param(obj, v, name, info, errp);
55
}
56
57
static void iothread_set_poll_param(Object *obj, Visitor *v,
58
const char *name, void *opaque, Error **errp)
59
{
60
IOThread *iothread = IOTHREAD(obj);
61
+ IOThreadParamInfo *info = opaque;
62
63
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
64
+ if (!iothread_set_param(obj, v, name, info, errp)) {
65
return;
51
}
66
}
52
67
53
n = total_sectors - sector_num;
68
@@ -XXX,XX +XXX,XX @@ static void iothread_set_poll_param(Object *obj, Visitor *v,
54
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
69
static void iothread_get_aio_param(Object *obj, Visitor *v,
55
if (!bs->drv->bdrv_co_get_block_status) {
70
const char *name, void *opaque, Error **errp)
56
*pnum = nb_sectors;
71
{
57
ret = BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED;
72
+ IOThreadParamInfo *info = opaque;
58
+ if (sector_num + nb_sectors == total_sectors) {
73
59
+ ret |= BDRV_BLOCK_EOF;
74
- iothread_get_param(obj, v, name, opaque, errp);
60
+ }
75
+ iothread_get_param(obj, v, name, info, errp);
61
if (bs->drv->protocol_name) {
62
ret |= BDRV_BLOCK_OFFSET_VALID | (sector_num * BDRV_SECTOR_SIZE);
63
}
64
@@ -XXX,XX +XXX,XX @@ static int64_t coroutine_fn bdrv_co_get_block_status(BlockDriverState *bs,
65
66
out:
67
bdrv_dec_in_flight(bs);
68
+ if (ret >= 0 && sector_num + *pnum == total_sectors) {
69
+ ret |= BDRV_BLOCK_EOF;
70
+ }
71
return ret;
72
}
76
}
73
77
74
diff --git a/include/block/block.h b/include/block/block.h
78
static void iothread_set_aio_param(Object *obj, Visitor *v,
75
index XXXXXXX..XXXXXXX 100644
79
const char *name, void *opaque, Error **errp)
76
--- a/include/block/block.h
80
{
77
+++ b/include/block/block.h
81
IOThread *iothread = IOTHREAD(obj);
78
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
82
+ IOThreadParamInfo *info = opaque;
79
* BDRV_BLOCK_OFFSET_VALID: an associated offset exists for accessing raw data
83
80
* BDRV_BLOCK_ALLOCATED: the content of the block is determined by this
84
- if (!iothread_set_param(obj, v, name, opaque, errp)) {
81
* layer (short for DATA || ZERO), set by block layer
85
+ if (!iothread_set_param(obj, v, name, info, errp)) {
82
+ * BDRV_BLOCK_EOF: the returned pnum covers through end of file for this layer
86
return;
83
*
87
}
84
* Internal flag:
88
85
* BDRV_BLOCK_RAW: used internally to indicate that the request was
86
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
87
#define BDRV_BLOCK_OFFSET_VALID 0x04
88
#define BDRV_BLOCK_RAW 0x08
89
#define BDRV_BLOCK_ALLOCATED 0x10
90
+#define BDRV_BLOCK_EOF 0x20
91
#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK
92
93
typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
94
--
89
--
95
2.9.4
90
2.31.1
96
91
97
92
diff view generated by jsdifflib