1
The following changes since commit ad1b4ec39caa5b3f17cbd8160283a03a3dcfe2ae:
1
The following changes since commit 07f426c35eddd79388a23d11cb278600d7e3831d:
2
2
3
Merge remote-tracking branch 'remotes/kraxel/tags/input-20180515-pull-request' into staging (2018-05-15 12:50:06 +0100)
3
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180926' into staging (2018-09-28 18:56:09 +0100)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 1fce860ea5eba1ca00a67911fc0b8a5d80009514:
9
for you to fetch changes up to dd353157942a59c21da07da5ac8749a871f7c3ed:
10
10
11
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-05-15' into queue-block (2018-05-15 16:19:53 +0200)
11
tests/test-bdrv-drain: Fix too late qemu_event_reset() (2018-10-01 19:13:55 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches:
15
15
16
- Switch AIO/callback based block drivers to a byte-based interface
16
- qcow2 cache option default changes (Linux: 32 MB maximum, limited by
17
- Block jobs: Expose error string via query-block-jobs
17
whatever cache size can be made use of with the specific image;
18
- Block job cleanups and fixes
18
default cache-clean-interval of 10 minutes)
19
- hmp: Allow using a qdev id in block_set_io_throttle
19
- reopen: Allow specifying unchanged child node references, and changing
20
- Copy-on-read block driver
20
a few generic options (discard, detect-zeroes)
21
- The qcow2 default refcount cache size has been decreased
21
- Fix werror/rerror defaults for -device drive=<node-name>
22
- Various bug fixes
22
- Test case fixes
23
23
----------------------------------------------------------------
24
----------------------------------------------------------------
24
Alberto Garcia (5):
25
Alberto Garcia (9):
25
hmp: Allow using a qdev id in block_set_io_throttle
26
qemu-io: Fix writethrough check in reopen
26
Fix error message about compressed clusters with OFLAG_COPIED
27
file-posix: x-check-cache-dropped should default to false on reopen
27
specs/qcow2: Clarify that compressed clusters have the COPIED bit reset
28
block: Remove child references from bs->{options,explicit_options}
28
qcow2: Give the refcount cache the minimum possible size by default
29
block: Don't look for child references in append_open_options()
29
docs: Document the new default sizes of the qcow2 caches
30
block: Allow child references on reopen
31
block: Forbid trying to change unsupported options during reopen
32
file-posix: Forbid trying to change unsupported options during reopen
33
block: Allow changing 'discard' on reopen
34
block: Allow changing 'detect-zeroes' on reopen
30
35
31
Daniel Henrique Barboza (1):
36
Fam Zheng (1):
32
block-backend: simplify blk_get_aio_context
37
file-posix: Include filename in locking error message
33
38
34
Eric Blake (7):
39
Kevin Wolf (3):
35
block: Support byte-based aio callbacks
40
block-backend: Set werror/rerror defaults in blk_new()
36
file-win32: Switch to byte-based callbacks
41
test-replication: Lock AioContext around blk_unref()
37
null: Switch to byte-based read/write
42
tests/test-bdrv-drain: Fix too late qemu_event_reset()
38
rbd: Switch to byte-based callbacks
39
vxhs: Switch to byte-based callbacks
40
block: Drop last of the sector-based aio callbacks
41
block: Merge .bdrv_co_writev{,_flags} in drivers
42
43
43
John Snow (1):
44
Leonid Bloch (10):
44
blockjob: expose error string via query
45
qcow2: Options' documentation fixes
46
include: Add a lookup table of sizes
47
qcow2: Make sizes more humanly readable
48
qcow2: Avoid duplication in setting the refcount cache size
49
qcow2: Assign the L2 cache relatively to the image size
50
qcow2: Increase the default upper limit on the L2 cache size
51
qcow2: Resize the cache upon image resizing
52
qcow2: Set the default cache-clean-interval to 10 minutes
53
qcow2: Explicit number replaced by a constant
54
qcow2: Fix cache-clean-interval documentation
45
55
46
Kevin Wolf (7):
56
qapi/block-core.json | 4 +-
47
blockjob: Fix assertion in block_job_finalize()
57
docs/qcow2-cache.txt | 59 ++++++++++++--------
48
blockjob: Wrappers for progress counter access
58
block/qcow2.h | 19 ++++---
49
blockjob: Move RateLimit to BlockJob
59
include/block/block.h | 1 +
50
blockjob: Implement block_job_set_speed() centrally
60
include/qemu/units.h | 55 ++++++++++++++++++
51
blockjob: Introduce block_job_ratelimit_get_delay()
61
block.c | 135 +++++++++++++++++++++++++++++----------------
52
blockjob: Add block_job_driver()
62
block/block-backend.c | 3 +
53
Merge remote-tracking branch 'mreitz/tags/pull-block-2018-05-15' into queue-block
63
block/file-posix.c | 19 +++++--
64
block/qcow2.c | 43 +++++++++------
65
qemu-io-cmds.c | 2 +-
66
tests/test-bdrv-drain.c | 4 +-
67
tests/test-replication.c | 11 ++++
68
qemu-options.hx | 12 ++--
69
tests/qemu-iotests/067.out | 1 +
70
tests/qemu-iotests/137 | 8 ++-
71
tests/qemu-iotests/137.out | 4 +-
72
tests/qemu-iotests/153.out | 76 ++++++++++++-------------
73
tests/qemu-iotests/182.out | 2 +-
74
18 files changed, 307 insertions(+), 151 deletions(-)
54
75
55
Max Reitz (17):
56
iotests: Split 214 off of 122
57
iotests: Add failure matching to common.qemu
58
iotests: Skip 181 and 201 without userfaultfd
59
block: Add COR filter driver
60
block: BLK_PERM_WRITE includes ..._UNCHANGED
61
block: Add BDRV_REQ_WRITE_UNCHANGED flag
62
block: Set BDRV_REQ_WRITE_UNCHANGED for COR writes
63
block/quorum: Support BDRV_REQ_WRITE_UNCHANGED
64
block: Support BDRV_REQ_WRITE_UNCHANGED in filters
65
iotests: Clean up wrap image in 197
66
iotests: Copy 197 for COR filter driver
67
iotests: Add test for COR across nodes
68
qemu-img: Check post-truncation size
69
block: Document BDRV_REQ_WRITE_UNCHANGED support
70
qemu-io: Use purely string blockdev options
71
qemu-img: Use only string options in img_open_opts
72
iotests: Add test for -U/force-share conflicts
73
74
qapi/block-core.json | 11 ++-
75
docs/interop/qcow2.txt | 8 +-
76
docs/qcow2-cache.txt | 33 ++++----
77
block/qcow2.h | 4 -
78
include/block/block.h | 9 ++-
79
include/block/block_int.h | 28 +++++--
80
include/block/blockjob.h | 32 ++++++++
81
include/block/blockjob_int.h | 11 ++-
82
include/block/raw-aio.h | 2 +-
83
block/backup.c | 62 ++++++---------
84
block/blkdebug.c | 9 ++-
85
block/blkreplay.c | 3 +
86
block/blkverify.c | 3 +
87
block/block-backend.c | 8 +-
88
block/commit.c | 35 +++------
89
block/copy-on-read.c | 173 +++++++++++++++++++++++++++++++++++++++++
90
block/file-win32.c | 47 ++++++-----
91
block/gluster.c | 4 +-
92
block/io.c | 75 ++++++++++--------
93
block/iscsi.c | 8 +-
94
block/mirror.c | 44 ++++-------
95
block/null.c | 45 +++++------
96
block/parallels.c | 4 +-
97
block/qcow.c | 6 +-
98
block/qcow2-refcount.c | 4 +-
99
block/qcow2.c | 31 +++++---
100
block/qed.c | 3 +-
101
block/quorum.c | 19 +++--
102
block/raw-format.c | 9 ++-
103
block/rbd.c | 40 +++++-----
104
block/replication.c | 4 +-
105
block/sheepdog.c | 4 +-
106
block/ssh.c | 4 +-
107
block/stream.c | 33 +++-----
108
block/throttle.c | 6 +-
109
block/vhdx.c | 4 +-
110
block/vxhs.c | 43 +++++-----
111
block/win32-aio.c | 5 +-
112
blockjob.c | 40 +++++++---
113
hmp.c | 14 +++-
114
qemu-img.c | 43 ++++++++--
115
qemu-io.c | 4 +-
116
block/Makefile.objs | 2 +-
117
hmp-commands.hx | 3 +-
118
tests/qemu-iotests/122 | 47 -----------
119
tests/qemu-iotests/122.out | 33 --------
120
tests/qemu-iotests/137.out | 2 +-
121
tests/qemu-iotests/153 | 17 ++++
122
tests/qemu-iotests/153.out | 16 ++++
123
tests/qemu-iotests/181 | 13 ++++
124
tests/qemu-iotests/197 | 1 +
125
tests/qemu-iotests/201 | 13 ++++
126
tests/qemu-iotests/214 | 97 +++++++++++++++++++++++
127
tests/qemu-iotests/214.out | 35 +++++++++
128
tests/qemu-iotests/215 | 120 ++++++++++++++++++++++++++++
129
tests/qemu-iotests/215.out | 26 +++++++
130
tests/qemu-iotests/216 | 115 +++++++++++++++++++++++++++
131
tests/qemu-iotests/216.out | 28 +++++++
132
tests/qemu-iotests/common.qemu | 58 ++++++++++++--
133
tests/qemu-iotests/group | 3 +
134
60 files changed, 1174 insertions(+), 429 deletions(-)
135
create mode 100644 block/copy-on-read.c
136
create mode 100755 tests/qemu-iotests/214
137
create mode 100644 tests/qemu-iotests/214.out
138
create mode 100755 tests/qemu-iotests/215
139
create mode 100644 tests/qemu-iotests/215.out
140
create mode 100755 tests/qemu-iotests/216
141
create mode 100644 tests/qemu-iotests/216.out
142
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Fam Zheng <famz@redhat.com>
2
2
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
3
Image locking errors happening at device initialization time doesn't say
4
Message-id: 20180502202051.15493-4-mreitz@redhat.com
4
which file cannot be locked, for instance,
5
6
-device scsi-disk,drive=drive-1: Failed to get shared "write" lock
7
Is another process using the image?
8
9
could refer to either the overlay image or its backing image.
10
11
Hoist the error_append_hint to the caller of raw_check_lock_bytes where
12
file name is known, and include it in the error hint.
13
14
Signed-off-by: Fam Zheng <famz@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
17
---
8
tests/qemu-iotests/153 | 17 +++++++++++++++++
18
block/file-posix.c | 10 +++---
9
tests/qemu-iotests/153.out | 16 ++++++++++++++++
19
tests/qemu-iotests/153.out | 76 +++++++++++++++++++++++-----------------------
10
2 files changed, 33 insertions(+)
20
tests/qemu-iotests/182.out | 2 +-
11
21
3 files changed, 45 insertions(+), 43 deletions(-)
12
diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153
22
13
index XXXXXXX..XXXXXXX 100755
23
diff --git a/block/file-posix.c b/block/file-posix.c
14
--- a/tests/qemu-iotests/153
24
index XXXXXXX..XXXXXXX 100644
15
+++ b/tests/qemu-iotests/153
25
--- a/block/file-posix.c
16
@@ -XXX,XX +XXX,XX @@ _run_cmd $QEMU_IO "${TEST_IMG}" -c 'write 0 512'
26
+++ b/block/file-posix.c
17
27
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
18
_cleanup_qemu
28
"Failed to get \"%s\" lock",
19
29
perm_name);
20
+echo
30
g_free(perm_name);
21
+echo "== Detecting -U and force-share conflicts =="
31
- error_append_hint(errp,
22
+
32
- "Is another process using the image?\n");
23
+echo
33
return ret;
24
+echo 'No conflict:'
34
}
25
+$QEMU_IMG info -U --image-opts driver=null-co,force-share=on
35
}
26
+echo
36
@@ -XXX,XX +XXX,XX @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm,
27
+echo 'Conflict:'
37
"Failed to get shared \"%s\" lock",
28
+$QEMU_IMG info -U --image-opts driver=null-co,force-share=off
38
perm_name);
29
+
39
g_free(perm_name);
30
+echo
40
- error_append_hint(errp,
31
+echo 'No conflict:'
41
- "Is another process using the image?\n");
32
+$QEMU_IO -c 'open -r -U -o driver=null-co,force-share=on'
42
return ret;
33
+echo
43
}
34
+echo 'Conflict:'
44
}
35
+$QEMU_IO -c 'open -r -U -o driver=null-co,force-share=off'
45
@@ -XXX,XX +XXX,XX @@ static int raw_handle_perm_lock(BlockDriverState *bs,
36
+
46
if (!ret) {
37
# success, all done
47
return 0;
38
echo "*** done"
48
}
39
rm -f $seq.full
49
+ error_append_hint(errp,
50
+ "Is another process using the image [%s]?\n",
51
+ bs->filename);
52
}
53
op = RAW_PL_ABORT;
54
/* fall through to unlock bytes. */
55
@@ -XXX,XX +XXX,XX @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
56
/* Step two: Check that nobody else has taken conflicting locks */
57
result = raw_check_lock_bytes(fd, perm, shared, errp);
58
if (result < 0) {
59
+ error_append_hint(errp,
60
+ "Is another process using the image [%s]?\n",
61
+ file_opts->filename);
62
goto out_unlock;
63
}
64
40
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
65
diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out
41
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/qemu-iotests/153.out
67
--- a/tests/qemu-iotests/153.out
43
+++ b/tests/qemu-iotests/153.out
68
+++ b/tests/qemu-iotests/153.out
69
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t
70
71
== Launching another QEMU, opts: '' ==
72
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
73
-Is another process using the image?
74
+Is another process using the image [TEST_DIR/t.qcow2]?
75
76
== Launching another QEMU, opts: 'read-only=on' ==
77
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,read-only=on: Failed to get shared "write" lock
78
-Is another process using the image?
79
+Is another process using the image [TEST_DIR/t.qcow2]?
80
81
== Launching another QEMU, opts: 'read-only=on,force-share=on' ==
82
44
@@ -XXX,XX +XXX,XX @@ Is another process using the image?
83
@@ -XXX,XX +XXX,XX @@ Is another process using the image?
84
85
_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
86
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
87
-Is another process using the image?
88
+Is another process using the image [TEST_DIR/t.qcow2]?
89
90
_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
91
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
92
-Is another process using the image?
93
+Is another process using the image [TEST_DIR/t.qcow2]?
94
95
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
96
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
97
-Is another process using the image?
98
+Is another process using the image [TEST_DIR/t.qcow2]?
99
no file open, try 'help open'
100
101
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
102
can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock
103
-Is another process using the image?
104
+Is another process using the image [TEST_DIR/t.qcow2]?
105
no file open, try 'help open'
106
107
_qemu_img_wrapper info TEST_DIR/t.qcow2
108
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
109
-Is another process using the image?
110
+Is another process using the image [TEST_DIR/t.qcow2]?
111
112
_qemu_img_wrapper check TEST_DIR/t.qcow2
113
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
114
-Is another process using the image?
115
+Is another process using the image [TEST_DIR/t.qcow2]?
116
117
_qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2
118
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
119
-Is another process using the image?
120
+Is another process using the image [TEST_DIR/t.qcow2]?
121
122
_qemu_img_wrapper map TEST_DIR/t.qcow2
123
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
124
-Is another process using the image?
125
+Is another process using the image [TEST_DIR/t.qcow2]?
126
127
_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
128
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
129
-Is another process using the image?
130
+Is another process using the image [TEST_DIR/t.qcow2]?
131
132
_qemu_img_wrapper commit TEST_DIR/t.qcow2
133
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
134
-Is another process using the image?
135
+Is another process using the image [TEST_DIR/t.qcow2]?
136
137
_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
138
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
139
-Is another process using the image?
140
+Is another process using the image [TEST_DIR/t.qcow2]?
141
142
_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
143
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
144
-Is another process using the image?
145
+Is another process using the image [TEST_DIR/t.qcow2]?
146
147
_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
148
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
149
-Is another process using the image?
150
+Is another process using the image [TEST_DIR/t.qcow2]?
151
152
_qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert
153
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
154
-Is another process using the image?
155
+Is another process using the image [TEST_DIR/t.qcow2]?
156
157
_qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1
158
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
159
-Is another process using the image?
160
+Is another process using the image [TEST_DIR/t.qcow2]?
161
162
_qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
163
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock
164
-Is another process using the image?
165
+Is another process using the image [TEST_DIR/t.qcow2]?
166
167
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
168
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
169
-Is another process using the image?
170
+Is another process using the image [TEST_DIR/t.qcow2]?
171
172
_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
173
qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
174
-Is another process using the image?
175
+Is another process using the image [TEST_DIR/t.qcow2]?
176
file format: IMGFMT
177
178
== Running utility commands -U ==
179
@@ -XXX,XX +XXX,XX @@ Try 'qemu-img --help' for more information
180
181
_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
182
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
183
-Is another process using the image?
184
+Is another process using the image [TEST_DIR/t.qcow2]?
185
186
_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
187
188
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t
189
190
== Launching another QEMU, opts: '' ==
191
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock
192
-Is another process using the image?
193
+Is another process using the image [TEST_DIR/t.qcow2]?
194
195
== Launching another QEMU, opts: 'read-only=on' ==
196
197
@@ -XXX,XX +XXX,XX @@ Is another process using the image?
198
199
_qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2
200
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
201
-Is another process using the image?
202
+Is another process using the image [TEST_DIR/t.qcow2]?
203
204
_qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2
205
206
_qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512
207
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
208
-Is another process using the image?
209
+Is another process using the image [TEST_DIR/t.qcow2]?
210
no file open, try 'help open'
211
212
_qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512
213
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper map TEST_DIR/t.qcow2
214
215
_qemu_img_wrapper amend -o TEST_DIR/t.qcow2
216
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
217
-Is another process using the image?
218
+Is another process using the image [TEST_DIR/t.qcow2]?
219
220
_qemu_img_wrapper commit TEST_DIR/t.qcow2
221
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
222
-Is another process using the image?
223
+Is another process using the image [TEST_DIR/t.qcow2]?
224
225
_qemu_img_wrapper resize TEST_DIR/t.qcow2 32M
226
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
227
-Is another process using the image?
228
+Is another process using the image [TEST_DIR/t.qcow2]?
229
230
_qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
231
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
232
-Is another process using the image?
233
+Is another process using the image [TEST_DIR/t.qcow2]?
234
235
_qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2
236
237
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2
238
239
_qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2
240
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
241
-Is another process using the image?
242
+Is another process using the image [TEST_DIR/t.qcow2]?
243
244
_qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
245
qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock
246
-Is another process using the image?
247
+Is another process using the image [TEST_DIR/t.qcow2]?
248
file format: IMGFMT
249
250
== Running utility commands -U ==
251
@@ -XXX,XX +XXX,XX @@ Try 'qemu-img --help' for more information
252
253
_qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base
254
qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock
255
-Is another process using the image?
256
+Is another process using the image [TEST_DIR/t.qcow2]?
257
258
_qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2
259
260
@@ -XXX,XX +XXX,XX @@ Round done
261
262
== Two devices with the same image (read-only=off - read-only=off) ==
263
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock
264
-Is another process using the image?
265
+Is another process using the image [TEST_DIR/t.qcow2]?
266
267
== Two devices with the same image (read-only=off - read-only=on) ==
268
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=on: Failed to get shared "write" lock
269
-Is another process using the image?
270
+Is another process using the image [TEST_DIR/t.qcow2]?
271
272
== Two devices with the same image (read-only=off - read-only=on,force-share=on) ==
273
274
== Two devices with the same image (read-only=on - read-only=off) ==
275
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock
276
-Is another process using the image?
277
+Is another process using the image [TEST_DIR/t.qcow2]?
278
279
== Two devices with the same image (read-only=on - read-only=on) ==
280
281
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR
282
283
== Backing image also as an active device ==
284
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
285
-Is another process using the image?
286
+Is another process using the image [TEST_DIR/t.qcow2]?
287
288
== Backing image also as an active device (ro) ==
289
290
== Symbolic link ==
291
QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock
292
-Is another process using the image?
293
+Is another process using the image [TEST_DIR/t.qcow2]?
294
295
== Active commit to intermediate layer should work when base in use ==
296
{"return": {}}
297
@@ -XXX,XX +XXX,XX @@ Adding drive
298
299
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
300
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
301
-Is another process using the image?
302
+Is another process using the image [TEST_DIR/t.qcow2]?
303
Creating overlay with qemu-img when the guest is running should be allowed
304
305
_qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay
306
@@ -XXX,XX +XXX,XX @@ _qemu_img_wrapper info TEST_DIR/t.qcow2
307
308
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
309
can't open device TEST_DIR/t.qcow2: Failed to get "write" lock
310
-Is another process using the image?
311
+Is another process using the image [TEST_DIR/t.qcow2]?
45
Closing the other
312
Closing the other
46
313
47
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
314
_qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512
48
+
315
diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out
49
+== Detecting -U and force-share conflicts ==
316
index XXXXXXX..XXXXXXX 100644
50
+
317
--- a/tests/qemu-iotests/182.out
51
+No conflict:
318
+++ b/tests/qemu-iotests/182.out
52
+image: null-co://
319
@@ -XXX,XX +XXX,XX @@ Starting QEMU
53
+file format: null-co
320
54
+virtual size: 1.0G (1073741824 bytes)
321
Starting a second QEMU using the same image should fail
55
+disk size: unavailable
322
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock
56
+
323
-Is another process using the image?
57
+Conflict:
324
+Is another process using the image [TEST_DIR/t.qcow2]?
58
+qemu-img: --force-share/-U conflicts with image options
59
+
60
+No conflict:
61
+
62
+Conflict:
63
+-U conflicts with image options
64
*** done
325
*** done
65
--
326
--
66
2.13.6
327
2.13.6
67
328
68
329
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Some block drivers (iscsi and file-posix when dealing with device files)
3
"qemu-io reopen" doesn't allow changing the writethrough setting of
4
do not actually support truncation, even though they provide a
4
the cache, but the check is wrong, causing an error even on a simple
5
.bdrv_truncate() method and will happily return success when providing a
5
reopen with the default parameters:
6
new size that does not exceed the current size. This is because these
7
drivers expect the user to resize the image outside of qemu and then
8
provide qemu with that information through the block_resize command
9
(compare cb1b83e740384b4e0d950f3d7c81c02b8ce86c2e).
10
6
11
Of course, anyone using qemu-img resize will find that behavior useless.
7
$ qemu-img create -f qcow2 hd.qcow2 1M
12
So we should check the actual size of the image after the supposedly
8
$ qemu-system-x86_64 -monitor stdio -drive if=virtio,file=hd.qcow2
13
successful truncation took place, emit an error if nothing changed and
9
(qemu) qemu-io virtio0 reopen
14
emit a warning if the target size was not met.
10
Cannot change cache.writeback: Device attached
15
11
16
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1523065
12
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
18
Message-id: 20180421163957.29872-1-mreitz@redhat.com
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
15
---
22
qemu-img.c | 39 +++++++++++++++++++++++++++++++++++----
16
qemu-io-cmds.c | 2 +-
23
1 file changed, 35 insertions(+), 4 deletions(-)
17
1 file changed, 1 insertion(+), 1 deletion(-)
24
18
25
diff --git a/qemu-img.c b/qemu-img.c
19
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
26
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
21
--- a/qemu-io-cmds.c
28
+++ b/qemu-img.c
22
+++ b/qemu-io-cmds.c
29
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
23
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
30
Error *err = NULL;
24
return -EINVAL;
31
int c, ret, relative;
32
const char *filename, *fmt, *size;
33
- int64_t n, total_size, current_size;
34
+ int64_t n, total_size, current_size, new_size;
35
bool quiet = false;
36
BlockBackend *blk = NULL;
37
PreallocMode prealloc = PREALLOC_MODE_OFF;
38
@@ -XXX,XX +XXX,XX @@ static int img_resize(int argc, char **argv)
39
}
25
}
40
26
41
ret = blk_truncate(blk, total_size, prealloc, &err);
27
- if (writethrough != blk_enable_write_cache(blk) &&
42
- if (!ret) {
28
+ if (!writethrough != blk_enable_write_cache(blk) &&
43
- qprintf(quiet, "Image resized.\n");
29
blk_get_attached_dev(blk))
44
- } else {
30
{
45
+ if (ret < 0) {
31
error_report("Cannot change cache.writeback: Device attached");
46
error_report_err(err);
47
+ goto out;
48
+ }
49
+
50
+ new_size = blk_getlength(blk);
51
+ if (new_size < 0) {
52
+ error_report("Failed to verify truncated image length: %s",
53
+ strerror(-new_size));
54
+ ret = -1;
55
+ goto out;
56
}
57
+
58
+ /* Some block drivers implement a truncation method, but only so
59
+ * the user can cause qemu to refresh the image's size from disk.
60
+ * The idea is that the user resizes the image outside of qemu and
61
+ * then invokes block_resize to inform qemu about it.
62
+ * (This includes iscsi and file-posix for device files.)
63
+ * Of course, that is not the behavior someone invoking
64
+ * qemu-img resize would find useful, so we catch that behavior
65
+ * here and tell the user. */
66
+ if (new_size != total_size && new_size == current_size) {
67
+ error_report("Image was not resized; resizing may not be supported "
68
+ "for this image");
69
+ ret = -1;
70
+ goto out;
71
+ }
72
+
73
+ if (new_size != total_size) {
74
+ warn_report("Image should have been resized to %" PRIi64
75
+ " bytes, but was resized to %" PRIi64 " bytes",
76
+ total_size, new_size);
77
+ }
78
+
79
+ qprintf(quiet, "Image resized.\n");
80
+
81
out:
82
blk_unref(blk);
83
if (ret) {
84
--
32
--
85
2.13.6
33
2.13.6
86
34
87
35
diff view generated by jsdifflib
1
This gets us rid of more direct accesses to BlockJob fields from the
1
From: Alberto Garcia <berto@igalia.com>
2
job drivers.
3
2
3
The default value of x-check-cache-dropped is false. There's no reason
4
to use the previous value as a default in raw_reopen_prepare() because
5
bdrv_reopen_queue_child() already takes care of putting the old
6
options in the BDRVReopenState.options QDict.
7
8
If x-check-cache-dropped was previously set but is now missing from
9
the reopen QDict then it should be reset to false.
10
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
---
14
---
9
include/block/blockjob_int.h | 8 ++++++++
15
block/file-posix.c | 2 +-
10
block/backup.c | 18 +++++++-----------
16
1 file changed, 1 insertion(+), 1 deletion(-)
11
block/commit.c | 4 ++--
12
block/mirror.c | 5 +----
13
block/stream.c | 4 ++--
14
blockjob.c | 9 +++++++++
15
6 files changed, 29 insertions(+), 19 deletions(-)
16
17
17
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
18
diff --git a/block/file-posix.c b/block/file-posix.c
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/blockjob_int.h
20
--- a/block/file-posix.c
20
+++ b/include/block/blockjob_int.h
21
+++ b/block/file-posix.c
21
@@ -XXX,XX +XXX,XX @@ void block_job_sleep_ns(BlockJob *job, int64_t ns);
22
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
22
void block_job_yield(BlockJob *job);
23
24
/**
25
+ * block_job_ratelimit_get_delay:
26
+ *
27
+ * Calculate and return delay for the next request in ns. See the documentation
28
+ * of ratelimit_calculate_delay() for details.
29
+ */
30
+int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n);
31
+
32
+/**
33
* block_job_early_fail:
34
* @bs: The block device.
35
*
36
diff --git a/block/backup.c b/block/backup.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/backup.c
39
+++ b/block/backup.c
40
@@ -XXX,XX +XXX,XX @@ static void backup_complete(BlockJob *job, void *opaque)
41
42
static bool coroutine_fn yield_and_check(BackupBlockJob *job)
43
{
44
+ uint64_t delay_ns;
45
+
46
if (block_job_is_cancelled(&job->common)) {
47
return true;
48
}
23
}
49
24
50
- /* we need to yield so that bdrv_drain_all() returns.
25
rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
51
- * (without, VM does not reboot)
26
- s->check_cache_dropped);
52
- */
27
+ false);
53
- if (job->common.speed) {
28
54
- uint64_t delay_ns = ratelimit_calculate_delay(&job->common.limit,
29
if (s->type == FTYPE_CD) {
55
- job->bytes_read);
30
rs->open_flags |= O_NONBLOCK;
56
- job->bytes_read = 0;
57
- block_job_sleep_ns(&job->common, delay_ns);
58
- } else {
59
- block_job_sleep_ns(&job->common, 0);
60
- }
61
+ /* We need to yield even for delay_ns = 0 so that bdrv_drain_all() can
62
+ * return. Without a yield, the VM would not reboot. */
63
+ delay_ns = block_job_ratelimit_get_delay(&job->common, job->bytes_read);
64
+ job->bytes_read = 0;
65
+ block_job_sleep_ns(&job->common, delay_ns);
66
67
if (block_job_is_cancelled(&job->common)) {
68
return true;
69
diff --git a/block/commit.c b/block/commit.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/block/commit.c
72
+++ b/block/commit.c
73
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
74
/* Publish progress */
75
block_job_progress_update(&s->common, n);
76
77
- if (copy && s->common.speed) {
78
- delay_ns = ratelimit_calculate_delay(&s->common.limit, n);
79
+ if (copy) {
80
+ delay_ns = block_job_ratelimit_get_delay(&s->common, n);
81
} else {
82
delay_ns = 0;
83
}
84
diff --git a/block/mirror.c b/block/mirror.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/mirror.c
87
+++ b/block/mirror.c
88
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
89
assert(io_bytes);
90
offset += io_bytes;
91
nb_chunks -= DIV_ROUND_UP(io_bytes, s->granularity);
92
- if (s->common.speed) {
93
- delay_ns = ratelimit_calculate_delay(&s->common.limit,
94
- io_bytes_acct);
95
- }
96
+ delay_ns = block_job_ratelimit_get_delay(&s->common, io_bytes_acct);
97
}
98
return delay_ns;
99
}
100
diff --git a/block/stream.c b/block/stream.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/block/stream.c
103
+++ b/block/stream.c
104
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
105
106
/* Publish progress */
107
block_job_progress_update(&s->common, n);
108
- if (copy && s->common.speed) {
109
- delay_ns = ratelimit_calculate_delay(&s->common.limit, n);
110
+ if (copy) {
111
+ delay_ns = block_job_ratelimit_get_delay(&s->common, n);
112
} else {
113
delay_ns = 0;
114
}
115
diff --git a/blockjob.c b/blockjob.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/blockjob.c
118
+++ b/blockjob.c
119
@@ -XXX,XX +XXX,XX @@ void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
120
block_job_enter_cond(job, block_job_timer_pending);
121
}
122
123
+int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n)
124
+{
125
+ if (!job->speed) {
126
+ return 0;
127
+ }
128
+
129
+ return ratelimit_calculate_delay(&job->limit, n);
130
+}
131
+
132
void block_job_complete(BlockJob *job, Error **errp)
133
{
134
/* Should not be reachable via external interface for internal jobs */
135
--
31
--
136
2.13.6
32
2.13.6
137
33
138
34
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Block drivers allow opening their children using a reference to an
4
byte-based. Now that all drivers with aio callbacks are using the
4
existing BlockDriverState. These references remain stored in the
5
byte-based interfaces, we can remove the sector-based versions.
5
'options' and 'explicit_options' QDicts, but we don't need to keep
6
them once everything is open.
6
7
7
Signed-off-by: Eric Blake <eblake@redhat.com>
8
What is more important, these values can become wrong if the children
9
change:
10
11
$ qemu-img create -f qcow2 hd0.qcow2 10M
12
$ qemu-img create -f qcow2 hd1.qcow2 10M
13
$ qemu-img create -f qcow2 hd2.qcow2 10M
14
$ $QEMU -drive if=none,file=hd0.qcow2,node-name=hd0 \
15
-drive if=none,file=hd1.qcow2,node-name=hd1,backing=hd0 \
16
-drive file=hd2.qcow2,node-name=hd2,backing=hd1
17
18
After this hd2 has hd1 as its backing file. Now let's remove it using
19
block_stream:
20
21
(qemu) block_stream hd2 0 hd0.qcow2
22
23
Now hd0 is the backing file of hd2, but hd2's options QDicts still
24
contain backing=hd1.
25
26
Signed-off-by: Alberto Garcia <berto@igalia.com>
27
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
29
---
10
include/block/block_int.h | 6 ----
30
block.c | 13 ++++++++++++-
11
block/io.c | 84 ++++++++++++++++++++---------------------------
31
1 file changed, 12 insertions(+), 1 deletion(-)
12
2 files changed, 36 insertions(+), 54 deletions(-)
13
32
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
33
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block_int.h
35
--- a/block.c
17
+++ b/include/block/block_int.h
36
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
37
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
19
void (*bdrv_refresh_filename)(BlockDriverState *bs, QDict *options);
20
21
/* aio */
22
- BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
23
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
24
- BlockCompletionFunc *cb, void *opaque);
25
BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
26
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
27
BlockCompletionFunc *cb, void *opaque);
28
- BlockAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
29
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
30
- BlockCompletionFunc *cb, void *opaque);
31
BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
32
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
33
BlockCompletionFunc *cb, void *opaque);
34
diff --git a/block/io.c b/block/io.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/io.c
37
+++ b/block/io.c
38
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
39
return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
40
}
41
42
- /* FIXME - no need to calculate these if .bdrv_aio_preadv exists */
43
- sector_num = offset >> BDRV_SECTOR_BITS;
44
- nb_sectors = bytes >> BDRV_SECTOR_BITS;
45
-
46
- if (!drv->bdrv_aio_preadv) {
47
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
48
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
49
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
50
- }
51
-
52
- if (drv->bdrv_co_readv) {
53
- return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
54
- } else {
55
+ if (drv->bdrv_aio_preadv) {
56
BlockAIOCB *acb;
57
CoroutineIOCompletion co = {
58
.coroutine = qemu_coroutine_self(),
59
};
60
61
- if (drv->bdrv_aio_preadv) {
62
- acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
63
- bdrv_co_io_em_complete, &co);
64
- } else {
65
- acb = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
66
- bdrv_co_io_em_complete, &co);
67
- }
68
+ acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
69
+ bdrv_co_io_em_complete, &co);
70
if (acb == NULL) {
71
return -EIO;
72
} else {
73
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
74
return co.ret;
75
}
38
}
76
}
39
}
77
+
40
78
+ sector_num = offset >> BDRV_SECTOR_BITS;
41
- /* Remove all children options from bs->options and bs->explicit_options */
79
+ nb_sectors = bytes >> BDRV_SECTOR_BITS;
42
+ /* Remove all children options and references
80
+
43
+ * from bs->options and bs->explicit_options */
81
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
44
QLIST_FOREACH(child, &bs->children, next) {
82
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
45
char *child_key_dot;
83
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
46
child_key_dot = g_strdup_printf("%s.", child->name);
84
+ assert(drv->bdrv_co_readv);
47
qdict_extract_subqdict(bs->explicit_options, NULL, child_key_dot);
85
+
48
qdict_extract_subqdict(bs->options, NULL, child_key_dot);
86
+ return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
49
+ qdict_del(bs->explicit_options, child->name);
87
}
50
+ qdict_del(bs->options, child->name);
88
51
g_free(child_key_dot);
89
static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
90
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
91
goto emulate_flags;
92
}
52
}
93
53
94
- /* FIXME - no need to calculate these if .bdrv_aio_pwritev exists */
54
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
95
- sector_num = offset >> BDRV_SECTOR_BITS;
55
{
96
- nb_sectors = bytes >> BDRV_SECTOR_BITS;
56
BlockDriver *drv;
97
-
57
BlockDriverState *bs;
98
- if (!drv->bdrv_aio_pwritev) {
58
+ BdrvChild *child;
99
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
59
bool old_can_write, new_can_write;
100
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
60
101
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
61
assert(reopen_state != NULL);
102
- }
62
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
103
-
63
bs->open_flags = reopen_state->flags;
104
- if (drv->bdrv_co_writev_flags) {
64
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
105
- ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov,
65
106
- flags & bs->supported_write_flags);
66
+ /* Remove child references from bs->options and bs->explicit_options.
107
- flags &= ~bs->supported_write_flags;
67
+ * Child options were already removed in bdrv_reopen_queue_child() */
108
- } else if (drv->bdrv_co_writev) {
68
+ QLIST_FOREACH(child, &bs->children, next) {
109
- assert(!bs->supported_write_flags);
69
+ qdict_del(bs->explicit_options, child->name);
110
- ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
70
+ qdict_del(bs->options, child->name);
111
- } else {
112
+ if (drv->bdrv_aio_pwritev) {
113
BlockAIOCB *acb;
114
CoroutineIOCompletion co = {
115
.coroutine = qemu_coroutine_self(),
116
};
117
118
- if (drv->bdrv_aio_pwritev) {
119
- acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov,
120
- flags & bs->supported_write_flags,
121
- bdrv_co_io_em_complete, &co);
122
- flags &= ~bs->supported_write_flags;
123
- } else {
124
- assert(!bs->supported_write_flags);
125
- acb = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
126
- bdrv_co_io_em_complete, &co);
127
- }
128
+ acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov,
129
+ flags & bs->supported_write_flags,
130
+ bdrv_co_io_em_complete, &co);
131
+ flags &= ~bs->supported_write_flags;
132
if (acb == NULL) {
133
ret = -EIO;
134
} else {
135
qemu_coroutine_yield();
136
ret = co.ret;
137
}
138
+ goto emulate_flags;
139
+ }
71
+ }
140
+
72
+
141
+ sector_num = offset >> BDRV_SECTOR_BITS;
73
bdrv_refresh_limits(bs, NULL);
142
+ nb_sectors = bytes >> BDRV_SECTOR_BITS;
74
143
+
75
bdrv_set_perm(reopen_state->bs, reopen_state->perm,
144
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
145
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
146
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
147
+
148
+ if (drv->bdrv_co_writev_flags) {
149
+ ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov,
150
+ flags & bs->supported_write_flags);
151
+ flags &= ~bs->supported_write_flags;
152
+ } else {
153
+ assert(drv->bdrv_co_writev);
154
+ assert(!bs->supported_write_flags);
155
+ ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
156
}
157
158
emulate_flags:
159
--
76
--
160
2.13.6
77
2.13.6
161
78
162
79
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Compressed clusters are not supposed to have the COPIED bit set, but
3
In the previous patch we removed child references from bs->options, so
4
this is not made explicit in the specs, so let's document it.
4
there's no need to look for them here anymore.
5
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Message-id: 74552e1d6e858d3159cb0c0e188e80bc9248e337.1523376013.git.berto@igalia.com
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
9
---
11
docs/interop/qcow2.txt | 8 ++++----
10
block.c | 13 +------------
12
1 file changed, 4 insertions(+), 4 deletions(-)
11
1 file changed, 1 insertion(+), 12 deletions(-)
13
12
14
diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt
13
diff --git a/block.c b/block.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/interop/qcow2.txt
15
--- a/block.c
17
+++ b/docs/interop/qcow2.txt
16
+++ b/block.c
18
@@ -XXX,XX +XXX,XX @@ L2 table entry:
17
@@ -XXX,XX +XXX,XX @@ static bool append_open_options(QDict *d, BlockDriverState *bs)
19
62: 0 for standard clusters
18
{
20
1 for compressed clusters
19
const QDictEntry *entry;
21
20
QemuOptDesc *desc;
22
- 63: 0 for a cluster that is unused or requires COW, 1 if its
21
- BdrvChild *child;
23
- refcount is exactly one. This information is only accurate
22
bool found_any = false;
24
- in L2 tables that are reachable from the active L1
23
25
- table.
24
for (entry = qdict_first(bs->options); entry;
26
+ 63: 0 for clusters that are unused, compressed or require COW.
25
entry = qdict_next(bs->options, entry))
27
+ 1 for standard clusters whose refcount is exactly one.
26
{
28
+ This information is only accurate in L2 tables
27
- /* Exclude node-name references to children */
29
+ that are reachable from the active L1 table.
28
- QLIST_FOREACH(child, &bs->children, next) {
30
29
- if (!strcmp(entry->key, child->name)) {
31
Standard Cluster Descriptor:
30
- break;
32
31
- }
32
- }
33
- if (child) {
34
- continue;
35
- }
36
-
37
- /* And exclude all non-driver-specific options */
38
+ /* Exclude all non-driver-specific options */
39
for (desc = bdrv_runtime_opts.desc; desc->name; desc++) {
40
if (!strcmp(qdict_entry_key(entry), desc->name)) {
41
break;
33
--
42
--
34
2.13.6
43
2.13.6
35
44
36
45
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
Compressed clusters are not supposed to have the COPIED bit set.
3
In the previous patches we removed all child references from
4
"qemu-img check" detects that and prints an error message reporting
4
bs->{options,explicit_options} because keeping them is useless and
5
the number of the affected host cluster. This doesn't make much sense
5
wrong.
6
because compressed clusters are not aligned to host clusters, so it
7
would be better to report the offset instead. Plus, the calculation is
8
wrong and it uses the raw L2 entry as if it was simply an offset.
9
6
10
This patch fixes the error message and reports the offset of the
7
Because of this, any attempt to reopen a BlockDriverState using a
11
compressed cluster.
8
child reference as one of its options would result in a failure,
9
because bdrv_reopen_prepare() would detect that there's a new option
10
(the child reference) that wasn't present in bs->options.
11
12
But passing child references on reopen can be useful. It's a way to
13
specify a BDS's child without having to pass recursively all of the
14
child's options, and if the reference points to a different BDS then
15
this can allow us to replace the child.
16
17
However, replacing the child is something that needs to be implemented
18
case by case and only when it makes sense. For now, this patch allows
19
passing a child reference as long as it points to the current child of
20
the BlockDriverState.
21
22
It's also important to remember that, as a consequence of the
23
previous patches, this child reference will be removed from
24
bs->{options,explicit_options} after the reopening has been completed.
12
25
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
26
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Message-id: 0f687957feb72e80c740403191a47e607c2463fe.1523376013.git.berto@igalia.com
27
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Max Reitz <mreitz@redhat.com>
28
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
29
---
17
block/qcow2-refcount.c | 4 ++--
30
block.c | 18 ++++++++++++++++++
18
1 file changed, 2 insertions(+), 2 deletions(-)
31
1 file changed, 18 insertions(+)
19
32
20
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
33
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
22
--- a/block/qcow2-refcount.c
35
--- a/block.c
23
+++ b/block/qcow2-refcount.c
36
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
37
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
25
case QCOW2_CLUSTER_COMPRESSED:
38
QObject *new = entry->value;
26
/* Compressed clusters don't have QCOW_OFLAG_COPIED */
39
QObject *old = qdict_get(reopen_state->bs->options, entry->key);
27
if (l2_entry & QCOW_OFLAG_COPIED) {
40
28
- fprintf(stderr, "ERROR: cluster %" PRId64 ": "
41
+ /* Allow child references (child_name=node_name) as long as they
29
+ fprintf(stderr, "ERROR: coffset=0x%" PRIx64 ": "
42
+ * point to the current child (i.e. everything stays the same). */
30
"copied flag must never be set for compressed "
43
+ if (qobject_type(new) == QTYPE_QSTRING) {
31
- "clusters\n", l2_entry >> s->cluster_bits);
44
+ BdrvChild *child;
32
+ "clusters\n", l2_entry & s->cluster_offset_mask);
45
+ QLIST_FOREACH(child, &reopen_state->bs->children, next) {
33
l2_entry &= ~QCOW_OFLAG_COPIED;
46
+ if (!strcmp(child->name, entry->key)) {
34
res->corruptions++;
47
+ break;
35
}
48
+ }
49
+ }
50
+
51
+ if (child) {
52
+ const char *str = qobject_get_try_str(new);
53
+ if (!strcmp(child->bs->node_name, str)) {
54
+ continue; /* Found child with this name, skip option */
55
+ }
56
+ }
57
+ }
58
+
59
/*
60
* TODO: When using -drive to specify blockdev options, all values
61
* will be strings; however, when using -blockdev, blockdev-add or
36
--
62
--
37
2.13.6
63
2.13.6
38
64
39
65
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
The bdrv_reopen_prepare() function checks all options passed to each
4
byte-based. Add new sector-based aio callbacks for read and write,
4
BlockDriverState (in the reopen_state->options QDict) and makes all
5
to match the fact that bdrv_aio_pdiscard is already byte-based.
5
necessary preparations to apply the option changes requested by the
6
user.
6
7
7
Ideally, drivers should be converted to use coroutine callbacks
8
Options are removed from the QDict as they are processed, so at the
8
rather than aio; but that is not quite as trivial (and if we were
9
end of bdrv_reopen_prepare() only the options that can't be changed
9
to do that conversion, the null-aio driver would disappear), so for
10
are left. Then a loop goes over all remaining options and verifies
10
the short term, converting the signature but keeping things with
11
that the old and new values are identical, returning an error if
11
aio is easier. However, we CAN declare that a driver that uses
12
they're not.
12
the byte-based aio interfaces now defaults to byte-based
13
operations, and must explicitly provide a refresh_limits override
14
to stick with larger alignments (making the alignment issues more
15
obvious directly in the drivers touched in the next few patches).
16
13
17
Once all drivers are converted, the sector-based aio callbacks will
14
The problem is that at the moment there are options that are removed
18
be removed; in the meantime, a FIXME comment is added due to a
15
from the QDict although they can't be changed. The consequence of this
19
slight inefficiency that will be touched up as part of that later
16
is any modification to any of those options is silently ignored:
20
cleanup.
21
17
22
Simplify some instances of 'bs->drv' into 'drv' while touching this,
18
(qemu) qemu-io virtio0 "reopen -o discard=on"
23
since the local variable already exists to reduce typing.
24
19
25
Signed-off-by: Eric Blake <eblake@redhat.com>
20
This happens when all options from bdrv_runtime_opts are removed
21
from the QDict but then only a few of them are processed. Since
22
it's especially important that "node-name" and "driver" are not
23
changed, the code puts them back into the QDict so they are checked
24
at the end of the function. Instead of putting only those two options
25
back into the QDict, this patch puts all unprocessed options using
26
qemu_opts_to_qdict().
27
28
update_flags_from_options() also needs to be modified to prevent
29
BDRV_OPT_CACHE_NO_FLUSH, BDRV_OPT_CACHE_DIRECT and BDRV_OPT_READ_ONLY
30
from going back to the QDict.
31
32
Signed-off-by: Alberto Garcia <berto@igalia.com>
33
Reviewed-by: Max Reitz <mreitz@redhat.com>
26
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
---
35
---
28
include/block/block_int.h | 6 ++++++
36
block.c | 22 +++++++---------------
29
block/io.c | 38 +++++++++++++++++++++++++++++---------
37
1 file changed, 7 insertions(+), 15 deletions(-)
30
2 files changed, 35 insertions(+), 9 deletions(-)
31
38
32
diff --git a/include/block/block_int.h b/include/block/block_int.h
39
diff --git a/block.c b/block.c
33
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/block_int.h
41
--- a/block.c
35
+++ b/include/block/block_int.h
42
+++ b/block.c
36
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
43
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
37
BlockAIOCB *(*bdrv_aio_readv)(BlockDriverState *bs,
44
*flags &= ~BDRV_O_CACHE_MASK;
38
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
45
39
BlockCompletionFunc *cb, void *opaque);
46
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
40
+ BlockAIOCB *(*bdrv_aio_preadv)(BlockDriverState *bs,
47
- if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
41
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
48
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
42
+ BlockCompletionFunc *cb, void *opaque);
49
*flags |= BDRV_O_NO_FLUSH;
43
BlockAIOCB *(*bdrv_aio_writev)(BlockDriverState *bs,
44
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
45
BlockCompletionFunc *cb, void *opaque);
46
+ BlockAIOCB *(*bdrv_aio_pwritev)(BlockDriverState *bs,
47
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags,
48
+ BlockCompletionFunc *cb, void *opaque);
49
BlockAIOCB *(*bdrv_aio_flush)(BlockDriverState *bs,
50
BlockCompletionFunc *cb, void *opaque);
51
BlockAIOCB *(*bdrv_aio_pdiscard)(BlockDriverState *bs,
52
diff --git a/block/io.c b/block/io.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/io.c
55
+++ b/block/io.c
56
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp)
57
}
50
}
58
51
59
/* Default alignment based on whether driver has byte interface */
52
assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT));
60
- bs->bl.request_alignment = drv->bdrv_co_preadv ? 1 : 512;
53
- if (qemu_opt_get_bool(opts, BDRV_OPT_CACHE_DIRECT, false)) {
61
+ bs->bl.request_alignment = (drv->bdrv_co_preadv ||
54
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_DIRECT, false)) {
62
+ drv->bdrv_aio_preadv) ? 1 : 512;
55
*flags |= BDRV_O_NOCACHE;
63
64
/* Take some limits from the children as a default */
65
if (bs->file) {
66
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
67
return drv->bdrv_co_preadv(bs, offset, bytes, qiov, flags);
68
}
56
}
69
57
70
+ /* FIXME - no need to calculate these if .bdrv_aio_preadv exists */
58
*flags &= ~BDRV_O_RDWR;
71
sector_num = offset >> BDRV_SECTOR_BITS;
59
72
nb_sectors = bytes >> BDRV_SECTOR_BITS;
60
assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
73
61
- if (!qemu_opt_get_bool(opts, BDRV_OPT_READ_ONLY, false)) {
74
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
62
+ if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
75
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
63
*flags |= BDRV_O_RDWR;
76
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
77
+ if (!drv->bdrv_aio_preadv) {
78
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
79
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
80
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
81
+ }
82
83
if (drv->bdrv_co_readv) {
84
return drv->bdrv_co_readv(bs, sector_num, nb_sectors, qiov);
85
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
86
.coroutine = qemu_coroutine_self(),
87
};
88
89
- acb = bs->drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
90
+ if (drv->bdrv_aio_preadv) {
91
+ acb = drv->bdrv_aio_preadv(bs, offset, bytes, qiov, flags,
92
+ bdrv_co_io_em_complete, &co);
93
+ } else {
94
+ acb = drv->bdrv_aio_readv(bs, sector_num, qiov, nb_sectors,
95
bdrv_co_io_em_complete, &co);
96
+ }
97
if (acb == NULL) {
98
return -EIO;
99
} else {
100
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
101
goto emulate_flags;
102
}
64
}
103
65
104
+ /* FIXME - no need to calculate these if .bdrv_aio_pwritev exists */
66
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
105
sector_num = offset >> BDRV_SECTOR_BITS;
67
BlockDriver *drv;
106
nb_sectors = bytes >> BDRV_SECTOR_BITS;
68
QemuOpts *opts;
107
69
QDict *orig_reopen_opts;
108
- assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
70
- const char *value;
109
- assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
71
bool read_only;
110
- assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
72
111
+ if (!drv->bdrv_aio_pwritev) {
73
assert(reopen_state != NULL);
112
+ assert((offset & (BDRV_SECTOR_SIZE - 1)) == 0);
74
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
113
+ assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
75
114
+ assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
76
update_flags_from_options(&reopen_state->flags, opts);
115
+ }
77
116
78
- /* node-name and driver must be unchanged. Put them back into the QDict, so
117
if (drv->bdrv_co_writev_flags) {
79
- * that they are checked at the end of this function. */
118
ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov,
80
- value = qemu_opt_get(opts, "node-name");
119
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
81
- if (value) {
120
.coroutine = qemu_coroutine_self(),
82
- qdict_put_str(reopen_state->options, "node-name", value);
121
};
83
- }
122
84
-
123
- acb = bs->drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
85
- value = qemu_opt_get(opts, "driver");
124
+ if (drv->bdrv_aio_pwritev) {
86
- if (value) {
125
+ acb = drv->bdrv_aio_pwritev(bs, offset, bytes, qiov,
87
- qdict_put_str(reopen_state->options, "driver", value);
126
+ flags & bs->supported_write_flags,
88
- }
127
+ bdrv_co_io_em_complete, &co);
89
+ /* All other options (including node-name and driver) must be unchanged.
128
+ flags &= ~bs->supported_write_flags;
90
+ * Put them back into the QDict, so that they are checked at the end
129
+ } else {
91
+ * of this function. */
130
+ assert(!bs->supported_write_flags);
92
+ qemu_opts_to_qdict(opts, reopen_state->options);
131
+ acb = drv->bdrv_aio_writev(bs, sector_num, qiov, nb_sectors,
93
132
bdrv_co_io_em_complete, &co);
94
/* If we are to stay read-only, do not allow permission change
133
+ }
95
* to r/w. Attempting to set to r/w may fail if either BDRV_O_ALLOW_RDWR is
134
if (acb == NULL) {
135
ret = -EIO;
136
} else {
137
--
96
--
138
2.13.6
97
2.13.6
139
98
140
99
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
The QMP version of this command can take a qdev ID since 7a9877a02635,
3
The file-posix code is used for the "file", "host_device" and
4
but the HMP version is still using the deprecated block device name so
4
"host_cdrom" drivers, and it allows reopening images. However the only
5
there's no way to refer to a block device added like this:
5
option that is actually processed is "x-check-cache-dropped", and
6
changes in all other options (e.g. "filename") are silently ignored:
6
7
7
-blockdev node-name=disk0,driver=qcow2,file.driver=file,file.filename=hd.qcow2
8
(qemu) qemu-io virtio0 "reopen -o file.filename=no-such-file"
8
-device virtio-blk-pci,id=virtio-blk-pci0,drive=disk0
9
9
10
This patch works around this problem by using the specified name as a
10
While we could allow changing some of the other options, let's keep
11
qdev ID if the block device name is not found.
11
things as they are for now but return an error if the user tries to
12
change any of them.
12
13
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Signed-off-by: Alberto Garcia <berto@igalia.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
---
17
hmp.c | 14 ++++++++++++--
18
block/file-posix.c | 9 +++++++--
18
hmp-commands.hx | 3 ++-
19
1 file changed, 7 insertions(+), 2 deletions(-)
19
2 files changed, 14 insertions(+), 3 deletions(-)
20
20
21
diff --git a/hmp.c b/hmp.c
21
diff --git a/block/file-posix.c b/block/file-posix.c
22
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hmp.c
23
--- a/block/file-posix.c
24
+++ b/hmp.c
24
+++ b/block/file-posix.c
25
@@ -XXX,XX +XXX,XX @@ void hmp_change(Monitor *mon, const QDict *qdict)
25
@@ -XXX,XX +XXX,XX @@ static int raw_reopen_prepare(BDRVReopenState *state,
26
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
26
goto out;
27
{
27
}
28
Error *err = NULL;
28
29
+ char *device = (char *) qdict_get_str(qdict, "device");
29
- rs->check_cache_dropped = qemu_opt_get_bool(opts, "x-check-cache-dropped",
30
BlockIOThrottle throttle = {
30
- false);
31
- .has_device = true,
31
+ rs->check_cache_dropped =
32
- .device = (char *) qdict_get_str(qdict, "device"),
32
+ qemu_opt_get_bool_del(opts, "x-check-cache-dropped", false);
33
.bps = qdict_get_int(qdict, "bps"),
34
.bps_rd = qdict_get_int(qdict, "bps_rd"),
35
.bps_wr = qdict_get_int(qdict, "bps_wr"),
36
@@ -XXX,XX +XXX,XX @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
37
.iops_wr = qdict_get_int(qdict, "iops_wr"),
38
};
39
40
+ /* qmp_block_set_io_throttle has separate parameters for the
41
+ * (deprecated) block device name and the qdev ID but the HMP
42
+ * version has only one, so we must decide which one to pass. */
43
+ if (blk_by_name(device)) {
44
+ throttle.has_device = true;
45
+ throttle.device = device;
46
+ } else {
47
+ throttle.has_id = true;
48
+ throttle.id = device;
49
+ }
50
+
33
+
51
qmp_block_set_io_throttle(&throttle, &err);
34
+ /* This driver's reopen function doesn't currently allow changing
52
hmp_handle_error(mon, &err);
35
+ * other options, so let's put them back in the original QDict and
53
}
36
+ * bdrv_reopen_prepare() will detect changes and complain. */
54
diff --git a/hmp-commands.hx b/hmp-commands.hx
37
+ qemu_opts_to_qdict(opts, state->options);
55
index XXXXXXX..XXXXXXX 100644
38
56
--- a/hmp-commands.hx
39
if (s->type == FTYPE_CD) {
57
+++ b/hmp-commands.hx
40
rs->open_flags |= O_NONBLOCK;
58
@@ -XXX,XX +XXX,XX @@ ETEXI
59
STEXI
60
@item block_set_io_throttle @var{device} @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
61
@findex block_set_io_throttle
62
-Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}
63
+Change I/O throttle limits for a block drive to @var{bps} @var{bps_rd} @var{bps_wr} @var{iops} @var{iops_rd} @var{iops_wr}.
64
+@var{device} can be a block device name, a qdev ID or a QOM path.
65
ETEXI
66
67
{
68
--
41
--
69
2.13.6
42
2.13.6
70
43
71
44
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
'discard' is one of the basic BlockdevOptions available for all
4
byte-based. Make the change for the last few sector-based callbacks
4
drivers, but it's not handled by bdrv_reopen_prepare() so any attempt
5
in the null-co and null-aio drivers.
5
to change it results in an error:
6
6
7
Note that since the null driver does nothing on writes, it trivially
7
(qemu) qemu-io virtio0 "reopen -o discard=on"
8
supports the BDRV_REQ_FUA flag (all writes have already landed to
8
Cannot change the option 'discard'
9
the same bit-bucket without needing an extra flush call). Also, since
10
the null driver does just as well with byte-based requests, we can
11
now avoid cycles wasted on read-modify-write by taking advantage of
12
the block layer now defaulting the alignment to 1 instead of 512.
13
9
14
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Since there's no reason why we shouldn't allow changing it and the
11
implementation is simple let's just do it.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
15
---
17
block/null.c | 45 +++++++++++++++++++++++----------------------
16
block.c | 11 +++++++++++
18
1 file changed, 23 insertions(+), 22 deletions(-)
17
1 file changed, 11 insertions(+)
19
18
20
diff --git a/block/null.c b/block/null.c
19
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
22
--- a/block/null.c
21
--- a/block.c
23
+++ b/block/null.c
22
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ static int null_file_open(BlockDriverState *bs, QDict *options, int flags,
23
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
25
}
24
BlockDriver *drv;
26
s->read_zeroes = qemu_opt_get_bool(opts, NULL_OPT_ZEROES, false);
25
QemuOpts *opts;
26
QDict *orig_reopen_opts;
27
+ char *discard = NULL;
28
bool read_only;
29
30
assert(reopen_state != NULL);
31
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
32
33
update_flags_from_options(&reopen_state->flags, opts);
34
35
+ discard = qemu_opt_get_del(opts, "discard");
36
+ if (discard != NULL) {
37
+ if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
38
+ error_setg(errp, "Invalid discard option");
39
+ ret = -EINVAL;
40
+ goto error;
41
+ }
42
+ }
43
+
44
/* All other options (including node-name and driver) must be unchanged.
45
* Put them back into the QDict, so that they are checked at the end
46
* of this function. */
47
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
48
error:
27
qemu_opts_del(opts);
49
qemu_opts_del(opts);
28
+ bs->supported_write_flags = BDRV_REQ_FUA;
50
qobject_unref(orig_reopen_opts);
51
+ g_free(discard);
29
return ret;
52
return ret;
30
}
53
}
31
32
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int null_co_common(BlockDriverState *bs)
33
return 0;
34
}
35
36
-static coroutine_fn int null_co_readv(BlockDriverState *bs,
37
- int64_t sector_num, int nb_sectors,
38
- QEMUIOVector *qiov)
39
+static coroutine_fn int null_co_preadv(BlockDriverState *bs,
40
+ uint64_t offset, uint64_t bytes,
41
+ QEMUIOVector *qiov, int flags)
42
{
43
BDRVNullState *s = bs->opaque;
44
45
if (s->read_zeroes) {
46
- qemu_iovec_memset(qiov, 0, 0, nb_sectors * BDRV_SECTOR_SIZE);
47
+ qemu_iovec_memset(qiov, 0, 0, bytes);
48
}
49
50
return null_co_common(bs);
51
}
52
53
-static coroutine_fn int null_co_writev(BlockDriverState *bs,
54
- int64_t sector_num, int nb_sectors,
55
- QEMUIOVector *qiov)
56
+static coroutine_fn int null_co_pwritev(BlockDriverState *bs,
57
+ uint64_t offset, uint64_t bytes,
58
+ QEMUIOVector *qiov, int flags)
59
{
60
return null_co_common(bs);
61
}
62
@@ -XXX,XX +XXX,XX @@ static inline BlockAIOCB *null_aio_common(BlockDriverState *bs,
63
return &acb->common;
64
}
65
66
-static BlockAIOCB *null_aio_readv(BlockDriverState *bs,
67
- int64_t sector_num, QEMUIOVector *qiov,
68
- int nb_sectors,
69
- BlockCompletionFunc *cb,
70
- void *opaque)
71
+static BlockAIOCB *null_aio_preadv(BlockDriverState *bs,
72
+ uint64_t offset, uint64_t bytes,
73
+ QEMUIOVector *qiov, int flags,
74
+ BlockCompletionFunc *cb,
75
+ void *opaque)
76
{
77
BDRVNullState *s = bs->opaque;
78
79
if (s->read_zeroes) {
80
- qemu_iovec_memset(qiov, 0, 0, nb_sectors * BDRV_SECTOR_SIZE);
81
+ qemu_iovec_memset(qiov, 0, 0, bytes);
82
}
83
84
return null_aio_common(bs, cb, opaque);
85
}
86
87
-static BlockAIOCB *null_aio_writev(BlockDriverState *bs,
88
- int64_t sector_num, QEMUIOVector *qiov,
89
- int nb_sectors,
90
- BlockCompletionFunc *cb,
91
- void *opaque)
92
+static BlockAIOCB *null_aio_pwritev(BlockDriverState *bs,
93
+ uint64_t offset, uint64_t bytes,
94
+ QEMUIOVector *qiov, int flags,
95
+ BlockCompletionFunc *cb,
96
+ void *opaque)
97
{
98
return null_aio_common(bs, cb, opaque);
99
}
100
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_co = {
101
.bdrv_close = null_close,
102
.bdrv_getlength = null_getlength,
103
104
- .bdrv_co_readv = null_co_readv,
105
- .bdrv_co_writev = null_co_writev,
106
+ .bdrv_co_preadv = null_co_preadv,
107
+ .bdrv_co_pwritev = null_co_pwritev,
108
.bdrv_co_flush_to_disk = null_co_flush,
109
.bdrv_reopen_prepare = null_reopen_prepare,
110
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_null_aio = {
112
.bdrv_close = null_close,
113
.bdrv_getlength = null_getlength,
114
115
- .bdrv_aio_readv = null_aio_readv,
116
- .bdrv_aio_writev = null_aio_writev,
117
+ .bdrv_aio_preadv = null_aio_preadv,
118
+ .bdrv_aio_pwritev = null_aio_pwritev,
119
.bdrv_aio_flush = null_aio_flush,
120
.bdrv_reopen_prepare = null_reopen_prepare,
121
54
122
--
55
--
123
2.13.6
56
2.13.6
124
57
125
58
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Alberto Garcia <berto@igalia.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
'detect-zeroes' is one of the basic BlockdevOptions available for all
4
byte-based. Make the change for the last few sector-based callbacks
4
drivers, but it's not handled by bdrv_reopen_prepare(), so any attempt
5
in the vxhs driver.
5
to change it results in an error:
6
6
7
Note that the driver was already using byte-based calls for
7
(qemu) qemu-io virtio0 "reopen -o detect-zeroes=on"
8
performing actual I/O, so this just gets rid of a round trip
8
Cannot change the option 'detect-zeroes'
9
of scaling; however, as I don't know if VxHS is tolerant of
10
non-sector AIO operations, I went with the conservative approach
11
of adding .bdrv_refresh_limits to override the block layer
12
defaults back to the pre-patch value of 512.
13
9
14
Signed-off-by: Eric Blake <eblake@redhat.com>
10
Since there's no reason why we shouldn't allow changing it and the
11
implementation is simple let's just do it.
12
13
Signed-off-by: Alberto Garcia <berto@igalia.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
15
---
17
block/vxhs.c | 43 ++++++++++++++++++++++---------------------
16
include/block/block.h | 1 +
18
1 file changed, 22 insertions(+), 21 deletions(-)
17
block.c | 64 ++++++++++++++++++++++++++++++++-------------------
18
2 files changed, 41 insertions(+), 24 deletions(-)
19
19
20
diff --git a/block/vxhs.c b/block/vxhs.c
20
diff --git a/include/block/block.h b/include/block/block.h
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/vxhs.c
22
--- a/include/block/block.h
23
+++ b/block/vxhs.c
23
+++ b/include/block/block.h
24
@@ -XXX,XX +XXX,XX @@ static void vxhs_parse_filename(const char *filename, QDict *options,
24
@@ -XXX,XX +XXX,XX @@ typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
25
typedef struct BDRVReopenState {
26
BlockDriverState *bs;
27
int flags;
28
+ BlockdevDetectZeroesOptions detect_zeroes;
29
uint64_t perm, shared_perm;
30
QDict *options;
31
QDict *explicit_options;
32
diff --git a/block.c b/block.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block.c
35
+++ b/block.c
36
@@ -XXX,XX +XXX,XX @@ static void bdrv_join_options(BlockDriverState *bs, QDict *options,
25
}
37
}
26
}
38
}
27
39
28
+static void vxhs_refresh_limits(BlockDriverState *bs, Error **errp)
40
+static BlockdevDetectZeroesOptions bdrv_parse_detect_zeroes(QemuOpts *opts,
41
+ int open_flags,
42
+ Error **errp)
29
+{
43
+{
30
+ /* XXX Does VXHS support AIO on less than 512-byte alignment? */
44
+ Error *local_err = NULL;
31
+ bs->bl.request_alignment = 512;
45
+ char *value = qemu_opt_get_del(opts, "detect-zeroes");
46
+ BlockdevDetectZeroesOptions detect_zeroes =
47
+ qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup, value,
48
+ BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, &local_err);
49
+ g_free(value);
50
+ if (local_err) {
51
+ error_propagate(errp, local_err);
52
+ return detect_zeroes;
53
+ }
54
+
55
+ if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
56
+ !(open_flags & BDRV_O_UNMAP))
57
+ {
58
+ error_setg(errp, "setting detect-zeroes to unmap is not allowed "
59
+ "without setting discard operation to unmap");
60
+ }
61
+
62
+ return detect_zeroes;
32
+}
63
+}
33
+
64
+
34
static int vxhs_init_and_ref(void)
65
/**
35
{
66
* Set open flags for a given discard mode
36
if (vxhs_ref++ == 0) {
67
*
37
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo vxhs_aiocb_info = {
68
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
38
* and is passed to QNIO. When QNIO completes the work,
69
const char *driver_name = NULL;
39
* it will be passed back through the callback.
70
const char *node_name = NULL;
40
*/
71
const char *discard;
41
-static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
72
- const char *detect_zeroes;
42
- QEMUIOVector *qiov, int nb_sectors,
73
QemuOpts *opts;
43
+static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, uint64_t offset,
74
BlockDriver *drv;
44
+ QEMUIOVector *qiov, uint64_t size,
75
Error *local_err = NULL;
45
BlockCompletionFunc *cb, void *opaque,
76
@@ -XXX,XX +XXX,XX @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
46
VDISKAIOCmd iodir)
77
}
47
{
78
}
48
VXHSAIOCB *acb = NULL;
79
49
BDRVVXHSState *s = bs->opaque;
80
- detect_zeroes = qemu_opt_get(opts, "detect-zeroes");
50
- size_t size;
81
- if (detect_zeroes) {
51
- uint64_t offset;
82
- BlockdevDetectZeroesOptions value =
52
int iio_flags = 0;
83
- qapi_enum_parse(&BlockdevDetectZeroesOptions_lookup,
53
int ret = 0;
84
- detect_zeroes,
54
void *dev_handle = s->vdisk_hostinfo.dev_handle;
85
- BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF,
55
86
- &local_err);
56
- offset = sector_num * BDRV_SECTOR_SIZE;
87
- if (local_err) {
57
- size = nb_sectors * BDRV_SECTOR_SIZE;
88
- error_propagate(errp, local_err);
58
acb = qemu_aio_get(&vxhs_aiocb_info, bs, cb, opaque);
89
- ret = -EINVAL;
59
90
- goto fail_opts;
60
/*
91
- }
61
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num,
92
-
62
switch (iodir) {
93
- if (value == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP &&
63
case VDISK_AIO_WRITE:
94
- !(bs->open_flags & BDRV_O_UNMAP))
64
ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov,
95
- {
65
- offset, (uint64_t)size, iio_flags);
96
- error_setg(errp, "setting detect-zeroes to unmap is not allowed "
66
+ offset, size, iio_flags);
97
- "without setting discard operation to unmap");
67
break;
98
- ret = -EINVAL;
68
case VDISK_AIO_READ:
99
- goto fail_opts;
69
ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov,
100
- }
70
- offset, (uint64_t)size, iio_flags);
101
-
71
+ offset, size, iio_flags);
102
- bs->detect_zeroes = value;
72
break;
103
+ bs->detect_zeroes =
73
default:
104
+ bdrv_parse_detect_zeroes(opts, bs->open_flags, &local_err);
74
trace_vxhs_aio_rw_invalid(iodir);
105
+ if (local_err) {
75
@@ -XXX,XX +XXX,XX @@ errout:
106
+ error_propagate(errp, local_err);
76
return NULL;
107
+ ret = -EINVAL;
77
}
108
+ goto fail_opts;
78
109
}
79
-static BlockAIOCB *vxhs_aio_readv(BlockDriverState *bs,
110
80
- int64_t sector_num, QEMUIOVector *qiov,
111
if (filename != NULL) {
81
- int nb_sectors,
112
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
82
+static BlockAIOCB *vxhs_aio_preadv(BlockDriverState *bs,
113
}
83
+ uint64_t offset, uint64_t bytes,
114
}
84
+ QEMUIOVector *qiov, int flags,
115
85
BlockCompletionFunc *cb, void *opaque)
116
+ reopen_state->detect_zeroes =
86
{
117
+ bdrv_parse_detect_zeroes(opts, reopen_state->flags, &local_err);
87
- return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors, cb,
118
+ if (local_err) {
88
- opaque, VDISK_AIO_READ);
119
+ error_propagate(errp, local_err);
89
+ return vxhs_aio_rw(bs, offset, qiov, bytes, cb, opaque, VDISK_AIO_READ);
120
+ ret = -EINVAL;
90
}
121
+ goto error;
91
122
+ }
92
-static BlockAIOCB *vxhs_aio_writev(BlockDriverState *bs,
123
+
93
- int64_t sector_num, QEMUIOVector *qiov,
124
/* All other options (including node-name and driver) must be unchanged.
94
- int nb_sectors,
125
* Put them back into the QDict, so that they are checked at the end
95
- BlockCompletionFunc *cb, void *opaque)
126
* of this function. */
96
+static BlockAIOCB *vxhs_aio_pwritev(BlockDriverState *bs,
127
@@ -XXX,XX +XXX,XX @@ void bdrv_reopen_commit(BDRVReopenState *reopen_state)
97
+ uint64_t offset, uint64_t bytes,
128
bs->options = reopen_state->options;
98
+ QEMUIOVector *qiov, int flags,
129
bs->open_flags = reopen_state->flags;
99
+ BlockCompletionFunc *cb, void *opaque)
130
bs->read_only = !(reopen_state->flags & BDRV_O_RDWR);
100
{
131
+ bs->detect_zeroes = reopen_state->detect_zeroes;
101
- return vxhs_aio_rw(bs, sector_num, qiov, nb_sectors,
132
102
- cb, opaque, VDISK_AIO_WRITE);
133
/* Remove child references from bs->options and bs->explicit_options.
103
+ return vxhs_aio_rw(bs, offset, qiov, bytes, cb, opaque, VDISK_AIO_WRITE);
134
* Child options were already removed in bdrv_reopen_queue_child() */
104
}
105
106
static void vxhs_close(BlockDriverState *bs)
107
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_vxhs = {
108
.instance_size = sizeof(BDRVVXHSState),
109
.bdrv_file_open = vxhs_open,
110
.bdrv_parse_filename = vxhs_parse_filename,
111
+ .bdrv_refresh_limits = vxhs_refresh_limits,
112
.bdrv_close = vxhs_close,
113
.bdrv_getlength = vxhs_getlength,
114
- .bdrv_aio_readv = vxhs_aio_readv,
115
- .bdrv_aio_writev = vxhs_aio_writev,
116
+ .bdrv_aio_preadv = vxhs_aio_preadv,
117
+ .bdrv_aio_pwritev = vxhs_aio_pwritev,
118
};
119
120
static void bdrv_vxhs_init(void)
121
--
135
--
122
2.13.6
136
2.13.6
123
137
124
138
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
We have too many driver callback interfaces; simplify the mess
3
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
4
somewhat by merging the flags parameter of .bdrv_co_writev_flags()
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
into .bdrv_co_writev(). Note that as long as a driver doesn't set
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
.supported_write_flags, the flags argument will be 0 and behavior is
7
identical. Also note that the public function bdrv_co_writev() still
8
lacks a flags argument; so the driver signature is thus intentionally
9
slightly different. But that's not the end of the world, nor the first
10
time that the driver interface differs slightly from the public
11
interface.
12
13
Ideally, we should be rewriting all of these drivers to use modern
14
byte-based interfaces. But that's a more invasive patch to write
15
and audit, compared to the simplification done here.
16
17
Signed-off-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
7
---
21
include/block/block_int.h | 2 --
8
docs/qcow2-cache.txt | 21 ++++++++++++++-------
22
block/gluster.c | 4 +++-
9
qemu-options.hx | 9 ++++++---
23
block/io.c | 13 ++++---------
10
2 files changed, 20 insertions(+), 10 deletions(-)
24
block/iscsi.c | 8 ++++----
25
block/parallels.c | 4 +++-
26
block/qcow.c | 6 ++++--
27
block/qed.c | 3 ++-
28
block/replication.c | 4 +++-
29
block/sheepdog.c | 4 +++-
30
block/ssh.c | 4 +++-
31
block/vhdx.c | 4 +++-
32
11 files changed, 32 insertions(+), 24 deletions(-)
33
11
34
diff --git a/include/block/block_int.h b/include/block/block_int.h
12
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
35
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block_int.h
14
--- a/docs/qcow2-cache.txt
37
+++ b/include/block/block_int.h
15
+++ b/docs/qcow2-cache.txt
38
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
16
@@ -XXX,XX +XXX,XX @@ Choosing the right cache sizes
39
int coroutine_fn (*bdrv_co_preadv)(BlockDriverState *bs,
17
In order to choose the cache sizes we need to know how they relate to
40
uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int flags);
18
the amount of allocated space.
41
int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
19
42
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
20
-The amount of virtual disk that can be mapped by the L2 and refcount
43
- int coroutine_fn (*bdrv_co_writev_flags)(BlockDriverState *bs,
21
+The part of the virtual disk that can be mapped by the L2 and refcount
44
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int flags);
22
caches (in bytes) is:
45
/**
23
46
* @offset: position in bytes to write at
24
disk_size = l2_cache_size * cluster_size / 8
47
diff --git a/block/gluster.c b/block/gluster.c
25
disk_size = refcount_cache_size * cluster_size * 8 / refcount_bits
26
27
With the default values for cluster_size (64KB) and refcount_bits
28
-(16), that is
29
+(16), this becomes:
30
31
disk_size = l2_cache_size * 8192
32
disk_size = refcount_cache_size * 32768
33
@@ -XXX,XX +XXX,XX @@ need:
34
l2_cache_size = disk_size_GB * 131072
35
refcount_cache_size = disk_size_GB * 32768
36
37
-QEMU has a default L2 cache of 1MB (1048576 bytes) and a refcount
38
-cache of 256KB (262144 bytes), so using the formulas we've just seen
39
-we have
40
+For example, 1MB of L2 cache is needed to cover every 8 GB of the virtual
41
+image size (given that the default cluster size is used):
42
43
- 1048576 / 131072 = 8 GB of virtual disk covered by that cache
44
- 262144 / 32768 = 8 GB
45
+ 8 GB / 8192 = 1 MB
46
+
47
+The refcount cache is 4 times the cluster size by default. With the default
48
+cluster size of 64 KB, it is 256 KB (262144 bytes). This is sufficient for
49
+8 GB of image size:
50
+
51
+ 262144 * 32768 = 8 GB
52
53
54
How to configure the cache sizes
55
@@ -XXX,XX +XXX,XX @@ There are a few things that need to be taken into account:
56
memory as possible to the L2 cache before increasing the refcount
57
cache size.
58
59
+ - At most two of "l2-cache-size", "refcount-cache-size", and "cache-size"
60
+ can be set simultaneously.
61
+
62
Unlike L2 tables, refcount blocks are not used during normal I/O but
63
only during allocations and internal snapshots. In most cases they are
64
accessed sequentially (even during random guest I/O) so increasing the
65
diff --git a/qemu-options.hx b/qemu-options.hx
48
index XXXXXXX..XXXXXXX 100644
66
index XXXXXXX..XXXXXXX 100644
49
--- a/block/gluster.c
67
--- a/qemu-options.hx
50
+++ b/block/gluster.c
68
+++ b/qemu-options.hx
51
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
69
@@ -XXX,XX +XXX,XX @@ image file)
52
static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
70
53
int64_t sector_num,
71
@item cache-size
54
int nb_sectors,
72
The maximum total size of the L2 table and refcount block caches in bytes
55
- QEMUIOVector *qiov)
73
-(default: 1048576 bytes or 8 clusters, whichever is larger)
56
+ QEMUIOVector *qiov,
74
+(default: the sum of l2-cache-size and refcount-cache-size)
57
+ int flags)
75
58
{
76
@item l2-cache-size
59
+ assert(!flags);
77
The maximum size of the L2 table cache in bytes
60
return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
78
-(default: 4/5 of the total cache size)
61
}
79
+(default: if cache-size is not defined - 1048576 bytes or 8 clusters, whichever
62
80
+is larger; otherwise, as large as possible or needed within the cache-size,
63
diff --git a/block/io.c b/block/io.c
81
+while permitting the requested or the minimal refcount cache size)
64
index XXXXXXX..XXXXXXX 100644
82
65
--- a/block/io.c
83
@item refcount-cache-size
66
+++ b/block/io.c
84
The maximum size of the refcount block cache in bytes
67
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
85
-(default: 1/5 of the total cache size)
68
assert((bytes & (BDRV_SECTOR_SIZE - 1)) == 0);
86
+(default: 4 times the cluster size; or if cache-size is specified, the part of
69
assert((bytes >> BDRV_SECTOR_BITS) <= BDRV_REQUEST_MAX_SECTORS);
87
+it which is not used for the L2 cache)
70
88
71
- if (drv->bdrv_co_writev_flags) {
89
@item cache-clean-interval
72
- ret = drv->bdrv_co_writev_flags(bs, sector_num, nb_sectors, qiov,
90
Clean unused entries in the L2 and refcount caches. The interval is in seconds.
73
- flags & bs->supported_write_flags);
74
- flags &= ~bs->supported_write_flags;
75
- } else {
76
- assert(drv->bdrv_co_writev);
77
- assert(!bs->supported_write_flags);
78
- ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov);
79
- }
80
+ assert(drv->bdrv_co_writev);
81
+ ret = drv->bdrv_co_writev(bs, sector_num, nb_sectors, qiov,
82
+ flags & bs->supported_write_flags);
83
+ flags &= ~bs->supported_write_flags;
84
85
emulate_flags:
86
if (ret == 0 && (flags & BDRV_REQ_FUA)) {
87
diff --git a/block/iscsi.c b/block/iscsi.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/iscsi.c
90
+++ b/block/iscsi.c
91
@@ -XXX,XX +XXX,XX @@ static inline bool iscsi_allocmap_is_valid(IscsiLun *iscsilun,
92
}
93
94
static int coroutine_fn
95
-iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
96
- QEMUIOVector *iov, int flags)
97
+iscsi_co_writev(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
98
+ QEMUIOVector *iov, int flags)
99
{
100
IscsiLun *iscsilun = bs->opaque;
101
struct IscsiTask iTask;
102
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iscsi = {
103
.bdrv_co_pdiscard = iscsi_co_pdiscard,
104
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
105
.bdrv_co_readv = iscsi_co_readv,
106
- .bdrv_co_writev_flags = iscsi_co_writev_flags,
107
+ .bdrv_co_writev = iscsi_co_writev,
108
.bdrv_co_flush_to_disk = iscsi_co_flush,
109
110
#ifdef __linux__
111
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_iser = {
112
.bdrv_co_pdiscard = iscsi_co_pdiscard,
113
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
114
.bdrv_co_readv = iscsi_co_readv,
115
- .bdrv_co_writev_flags = iscsi_co_writev_flags,
116
+ .bdrv_co_writev = iscsi_co_writev,
117
.bdrv_co_flush_to_disk = iscsi_co_flush,
118
119
#ifdef __linux__
120
diff --git a/block/parallels.c b/block/parallels.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/block/parallels.c
123
+++ b/block/parallels.c
124
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_block_status(BlockDriverState *bs,
125
}
126
127
static coroutine_fn int parallels_co_writev(BlockDriverState *bs,
128
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov)
129
+ int64_t sector_num, int nb_sectors,
130
+ QEMUIOVector *qiov, int flags)
131
{
132
BDRVParallelsState *s = bs->opaque;
133
uint64_t bytes_done = 0;
134
QEMUIOVector hd_qiov;
135
int ret = 0;
136
137
+ assert(!flags);
138
qemu_iovec_init(&hd_qiov, qiov->niov);
139
140
while (nb_sectors > 0) {
141
diff --git a/block/qcow.c b/block/qcow.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/block/qcow.c
144
+++ b/block/qcow.c
145
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_readv(BlockDriverState *bs, int64_t sector_num,
146
}
147
148
static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
149
- int nb_sectors, QEMUIOVector *qiov)
150
+ int nb_sectors, QEMUIOVector *qiov,
151
+ int flags)
152
{
153
BDRVQcowState *s = bs->opaque;
154
int index_in_cluster;
155
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
156
uint8_t *buf;
157
void *orig_buf;
158
159
+ assert(!flags);
160
s->cluster_cache_offset = -1; /* disable compressed cache */
161
162
/* We must always copy the iov when encrypting, so we
163
@@ -XXX,XX +XXX,XX @@ qcow_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
164
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
165
/* could not compress: write normal cluster */
166
ret = qcow_co_writev(bs, offset >> BDRV_SECTOR_BITS,
167
- bytes >> BDRV_SECTOR_BITS, qiov);
168
+ bytes >> BDRV_SECTOR_BITS, qiov, 0);
169
if (ret < 0) {
170
goto fail;
171
}
172
diff --git a/block/qed.c b/block/qed.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/qed.c
175
+++ b/block/qed.c
176
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_readv(BlockDriverState *bs,
177
178
static int coroutine_fn bdrv_qed_co_writev(BlockDriverState *bs,
179
int64_t sector_num, int nb_sectors,
180
- QEMUIOVector *qiov)
181
+ QEMUIOVector *qiov, int flags)
182
{
183
+ assert(!flags);
184
return qed_co_request(bs, sector_num, qiov, nb_sectors, QED_AIOCB_WRITE);
185
}
186
187
diff --git a/block/replication.c b/block/replication.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/block/replication.c
190
+++ b/block/replication.c
191
@@ -XXX,XX +XXX,XX @@ out:
192
static coroutine_fn int replication_co_writev(BlockDriverState *bs,
193
int64_t sector_num,
194
int remaining_sectors,
195
- QEMUIOVector *qiov)
196
+ QEMUIOVector *qiov,
197
+ int flags)
198
{
199
BDRVReplicationState *s = bs->opaque;
200
QEMUIOVector hd_qiov;
201
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_writev(BlockDriverState *bs,
202
int ret;
203
int64_t n;
204
205
+ assert(!flags);
206
ret = replication_get_io_status(s);
207
if (ret < 0) {
208
goto out;
209
diff --git a/block/sheepdog.c b/block/sheepdog.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/block/sheepdog.c
212
+++ b/block/sheepdog.c
213
@@ -XXX,XX +XXX,XX @@ static void sd_aio_complete(SheepdogAIOCB *acb)
214
}
215
216
static coroutine_fn int sd_co_writev(BlockDriverState *bs, int64_t sector_num,
217
- int nb_sectors, QEMUIOVector *qiov)
218
+ int nb_sectors, QEMUIOVector *qiov,
219
+ int flags)
220
{
221
SheepdogAIOCB acb;
222
int ret;
223
int64_t offset = (sector_num + nb_sectors) * BDRV_SECTOR_SIZE;
224
BDRVSheepdogState *s = bs->opaque;
225
226
+ assert(!flags);
227
if (offset > s->inode.vdi_size) {
228
ret = sd_truncate(bs, offset, PREALLOC_MODE_OFF, NULL);
229
if (ret < 0) {
230
diff --git a/block/ssh.c b/block/ssh.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/block/ssh.c
233
+++ b/block/ssh.c
234
@@ -XXX,XX +XXX,XX @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
235
236
static coroutine_fn int ssh_co_writev(BlockDriverState *bs,
237
int64_t sector_num,
238
- int nb_sectors, QEMUIOVector *qiov)
239
+ int nb_sectors, QEMUIOVector *qiov,
240
+ int flags)
241
{
242
BDRVSSHState *s = bs->opaque;
243
int ret;
244
245
+ assert(!flags);
246
qemu_co_mutex_lock(&s->lock);
247
ret = ssh_write(s, bs, sector_num * BDRV_SECTOR_SIZE,
248
nb_sectors * BDRV_SECTOR_SIZE, qiov);
249
diff --git a/block/vhdx.c b/block/vhdx.c
250
index XXXXXXX..XXXXXXX 100644
251
--- a/block/vhdx.c
252
+++ b/block/vhdx.c
253
@@ -XXX,XX +XXX,XX @@ int vhdx_user_visible_write(BlockDriverState *bs, BDRVVHDXState *s)
254
}
255
256
static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
257
- int nb_sectors, QEMUIOVector *qiov)
258
+ int nb_sectors, QEMUIOVector *qiov,
259
+ int flags)
260
{
261
int ret = -ENOTSUP;
262
BDRVVHDXState *s = bs->opaque;
263
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int vhdx_co_writev(BlockDriverState *bs, int64_t sector_num,
264
uint64_t bat_prior_offset = 0;
265
bool bat_update = false;
266
267
+ assert(!flags);
268
qemu_iovec_init(&hd_qiov, qiov->niov);
269
270
qemu_co_mutex_lock(&s->lock);
271
--
91
--
272
2.13.6
92
2.13.6
273
93
274
94
diff view generated by jsdifflib
1
The backup block job directly accesses the driver field in BlockJob. Add
1
From: Leonid Bloch <lbloch@janustech.com>
2
a wrapper for getting it.
3
2
3
Adding a lookup table for the powers of two, with the appropriate size
4
prefixes. This is needed when a size has to be stringified, in which
5
case something like '(1 * KiB)' would become a literal '(1 * (1L << 10))'
6
string. Powers of two are used very often for sizes, so such a table
7
will also make it easier and more intuitive to write them.
8
9
This table is generatred using the following AWK script:
10
11
BEGIN {
12
    suffix="KMGTPE";
13
    for(i=10; i<64; i++) {
14
        val=2**i;
15
        s=substr(suffix, int(i/10), 1);
16
        n=2**(i%10);
17
        pad=21-int(log(n)/log(10));
18
        printf("#define S_%d%siB %*d\n", n, s, pad, val);
19
    }
20
}
21
22
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
23
Reviewed-by: Alberto Garcia <berto@igalia.com>
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: John Snow <jsnow@redhat.com>
8
---
26
---
9
include/block/blockjob.h | 7 +++++++
27
include/qemu/units.h | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++
10
block/backup.c | 8 +++++---
28
1 file changed, 55 insertions(+)
11
blockjob.c | 5 +++++
12
3 files changed, 17 insertions(+), 3 deletions(-)
13
29
14
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
30
diff --git a/include/qemu/units.h b/include/qemu/units.h
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/blockjob.h
32
--- a/include/qemu/units.h
17
+++ b/include/block/blockjob.h
33
+++ b/include/qemu/units.h
18
@@ -XXX,XX +XXX,XX @@ void block_job_txn_add_job(BlockJobTxn *txn, BlockJob *job);
34
@@ -XXX,XX +XXX,XX @@
19
*/
35
#define PiB (INT64_C(1) << 50)
20
bool block_job_is_internal(BlockJob *job);
36
#define EiB (INT64_C(1) << 60)
21
37
22
+/**
38
+#define S_1KiB 1024
23
+ * block_job_driver:
39
+#define S_2KiB 2048
24
+ *
40
+#define S_4KiB 4096
25
+ * Returns the driver associated with a block job.
41
+#define S_8KiB 8192
26
+ */
42
+#define S_16KiB 16384
27
+const BlockJobDriver *block_job_driver(BlockJob *job);
43
+#define S_32KiB 32768
44
+#define S_64KiB 65536
45
+#define S_128KiB 131072
46
+#define S_256KiB 262144
47
+#define S_512KiB 524288
48
+#define S_1MiB 1048576
49
+#define S_2MiB 2097152
50
+#define S_4MiB 4194304
51
+#define S_8MiB 8388608
52
+#define S_16MiB 16777216
53
+#define S_32MiB 33554432
54
+#define S_64MiB 67108864
55
+#define S_128MiB 134217728
56
+#define S_256MiB 268435456
57
+#define S_512MiB 536870912
58
+#define S_1GiB 1073741824
59
+#define S_2GiB 2147483648
60
+#define S_4GiB 4294967296
61
+#define S_8GiB 8589934592
62
+#define S_16GiB 17179869184
63
+#define S_32GiB 34359738368
64
+#define S_64GiB 68719476736
65
+#define S_128GiB 137438953472
66
+#define S_256GiB 274877906944
67
+#define S_512GiB 549755813888
68
+#define S_1TiB 1099511627776
69
+#define S_2TiB 2199023255552
70
+#define S_4TiB 4398046511104
71
+#define S_8TiB 8796093022208
72
+#define S_16TiB 17592186044416
73
+#define S_32TiB 35184372088832
74
+#define S_64TiB 70368744177664
75
+#define S_128TiB 140737488355328
76
+#define S_256TiB 281474976710656
77
+#define S_512TiB 562949953421312
78
+#define S_1PiB 1125899906842624
79
+#define S_2PiB 2251799813685248
80
+#define S_4PiB 4503599627370496
81
+#define S_8PiB 9007199254740992
82
+#define S_16PiB 18014398509481984
83
+#define S_32PiB 36028797018963968
84
+#define S_64PiB 72057594037927936
85
+#define S_128PiB 144115188075855872
86
+#define S_256PiB 288230376151711744
87
+#define S_512PiB 576460752303423488
88
+#define S_1EiB 1152921504606846976
89
+#define S_2EiB 2305843009213693952
90
+#define S_4EiB 4611686018427387904
91
+#define S_8EiB 9223372036854775808
28
+
92
+
29
#endif
93
#endif
30
diff --git a/block/backup.c b/block/backup.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/backup.c
33
+++ b/block/backup.c
34
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
35
HBitmap *copy_bitmap;
36
} BackupBlockJob;
37
38
+static const BlockJobDriver backup_job_driver;
39
+
40
/* See if in-flight requests overlap and wait for them to complete */
41
static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
42
int64_t start,
43
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
44
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
45
int64_t len;
46
47
- assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
48
+ assert(block_job_driver(job) == &backup_job_driver);
49
50
if (backup_job->sync_mode != MIRROR_SYNC_MODE_NONE) {
51
error_setg(errp, "The backup job only supports block checkpoint in"
52
@@ -XXX,XX +XXX,XX @@ void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
53
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
54
int64_t start, end;
55
56
- assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
57
+ assert(block_job_driver(job) == &backup_job_driver);
58
59
start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
60
end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
61
@@ -XXX,XX +XXX,XX @@ void backup_cow_request_begin(CowRequest *req, BlockJob *job,
62
BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
63
int64_t start, end;
64
65
- assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
66
+ assert(block_job_driver(job) == &backup_job_driver);
67
68
start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
69
end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
70
diff --git a/blockjob.c b/blockjob.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/blockjob.c
73
+++ b/blockjob.c
74
@@ -XXX,XX +XXX,XX @@ static bool block_job_started(BlockJob *job)
75
return job->co;
76
}
77
78
+const BlockJobDriver *block_job_driver(BlockJob *job)
79
+{
80
+ return job->driver;
81
+}
82
+
83
/**
84
* All jobs must allow a pause point before entering their job proper. This
85
* ensures that jobs can be paused prior to being started, then resumed later.
86
--
94
--
87
2.13.6
95
2.13.6
88
96
89
97
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
4
byte-based. Make the change for the last few sector-based callbacks
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
in the file-win32 driver.
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
7
Note that the driver was already using byte-based calls for
8
performing actual I/O, so this just gets rid of a round trip
9
of scaling; however, as I don't know if Windows is tolerant of
10
non-sector AIO operations, I went with the conservative approach
11
of modifying .bdrv_refresh_limits to override the block layer
12
defaults back to the pre-patch value of 512.
13
14
Signed-off-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
7
---
17
include/block/raw-aio.h | 2 +-
8
block/qcow2.h | 9 +++++----
18
block/file-win32.c | 47 +++++++++++++++++++++++++++++------------------
9
block/qcow2.c | 2 +-
19
block/win32-aio.c | 5 ++---
10
2 files changed, 6 insertions(+), 5 deletions(-)
20
3 files changed, 32 insertions(+), 22 deletions(-)
21
11
22
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
12
diff --git a/block/qcow2.h b/block/qcow2.h
23
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
24
--- a/include/block/raw-aio.h
14
--- a/block/qcow2.h
25
+++ b/include/block/raw-aio.h
15
+++ b/block/qcow2.h
26
@@ -XXX,XX +XXX,XX @@ void win32_aio_cleanup(QEMUWin32AIOState *aio);
16
@@ -XXX,XX +XXX,XX @@
27
int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile);
17
28
BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
18
#include "crypto/block.h"
29
QEMUWin32AIOState *aio, HANDLE hfile,
19
#include "qemu/coroutine.h"
30
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
20
+#include "qemu/units.h"
31
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
21
32
BlockCompletionFunc *cb, void *opaque, int type);
22
//#define DEBUG_ALLOC
33
void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
23
//#define DEBUG_ALLOC2
34
AioContext *old_context);
24
@@ -XXX,XX +XXX,XX @@
35
diff --git a/block/file-win32.c b/block/file-win32.c
25
26
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
27
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
28
-#define QCOW_MAX_REFTABLE_SIZE 0x800000
29
+#define QCOW_MAX_REFTABLE_SIZE S_8MiB
30
31
/* 32 MB L1 table is enough for 2 PB images at 64k cluster size
32
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
33
-#define QCOW_MAX_L1_SIZE 0x2000000
34
+#define QCOW_MAX_L1_SIZE S_32MiB
35
36
/* Allow for an average of 1k per snapshot table entry, should be plenty of
37
* space for snapshot names and IDs */
38
@@ -XXX,XX +XXX,XX @@
39
40
/* Whichever is more */
41
#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
42
-#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
43
+#define DEFAULT_L2_CACHE_SIZE S_1MiB
44
45
-#define DEFAULT_CLUSTER_SIZE 65536
46
+#define DEFAULT_CLUSTER_SIZE S_64KiB
47
48
49
#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts"
50
diff --git a/block/qcow2.c b/block/qcow2.c
36
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
37
--- a/block/file-win32.c
52
--- a/block/qcow2.c
38
+++ b/block/file-win32.c
53
+++ b/block/qcow2.c
39
@@ -XXX,XX +XXX,XX @@ static void raw_probe_alignment(BlockDriverState *bs, Error **errp)
54
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
40
&dg.Geometry.BytesPerSector,
55
}
41
&freeClusters, &totalClusters);
42
bs->bl.request_alignment = dg.Geometry.BytesPerSector;
43
+ return;
44
}
45
+
46
+ /* XXX Does Windows support AIO on less than 512-byte alignment? */
47
+ bs->bl.request_alignment = 512;
48
}
49
50
static void raw_parse_flags(int flags, bool use_aio, int *access_flags,
51
@@ -XXX,XX +XXX,XX @@ fail:
52
return ret;
53
}
54
55
-static BlockAIOCB *raw_aio_readv(BlockDriverState *bs,
56
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
57
- BlockCompletionFunc *cb, void *opaque)
58
+static BlockAIOCB *raw_aio_preadv(BlockDriverState *bs,
59
+ uint64_t offset, uint64_t bytes,
60
+ QEMUIOVector *qiov, int flags,
61
+ BlockCompletionFunc *cb, void *opaque)
62
{
63
BDRVRawState *s = bs->opaque;
64
if (s->aio) {
65
- return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
66
- nb_sectors, cb, opaque, QEMU_AIO_READ);
67
+ return win32_aio_submit(bs, s->aio, s->hfile, offset, bytes, qiov,
68
+ cb, opaque, QEMU_AIO_READ);
69
} else {
56
} else {
70
- return paio_submit(bs, s->hfile, sector_num << BDRV_SECTOR_BITS, qiov,
57
if (!l2_cache_size_set) {
71
- nb_sectors << BDRV_SECTOR_BITS,
58
- *l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
72
+ return paio_submit(bs, s->hfile, offset, qiov, bytes,
59
+ *l2_cache_size = MAX(DEFAULT_L2_CACHE_SIZE,
73
cb, opaque, QEMU_AIO_READ);
60
(uint64_t)DEFAULT_L2_CACHE_CLUSTERS
74
}
61
* s->cluster_size);
75
}
62
}
76
77
-static BlockAIOCB *raw_aio_writev(BlockDriverState *bs,
78
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
79
- BlockCompletionFunc *cb, void *opaque)
80
+static BlockAIOCB *raw_aio_pwritev(BlockDriverState *bs,
81
+ uint64_t offset, uint64_t bytes,
82
+ QEMUIOVector *qiov, int flags,
83
+ BlockCompletionFunc *cb, void *opaque)
84
{
85
BDRVRawState *s = bs->opaque;
86
if (s->aio) {
87
- return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov,
88
- nb_sectors, cb, opaque, QEMU_AIO_WRITE);
89
+ return win32_aio_submit(bs, s->aio, s->hfile, offset, bytes, qiov,
90
+ cb, opaque, QEMU_AIO_WRITE);
91
} else {
92
- return paio_submit(bs, s->hfile, sector_num << BDRV_SECTOR_BITS, qiov,
93
- nb_sectors << BDRV_SECTOR_BITS,
94
+ return paio_submit(bs, s->hfile, offset, qiov, bytes,
95
cb, opaque, QEMU_AIO_WRITE);
96
}
97
}
98
@@ -XXX,XX +XXX,XX @@ BlockDriver bdrv_file = {
99
.bdrv_co_create_opts = raw_co_create_opts,
100
.bdrv_has_zero_init = bdrv_has_zero_init_1,
101
102
- .bdrv_aio_readv = raw_aio_readv,
103
- .bdrv_aio_writev = raw_aio_writev,
104
+ .bdrv_aio_preadv = raw_aio_preadv,
105
+ .bdrv_aio_pwritev = raw_aio_pwritev,
106
.bdrv_aio_flush = raw_aio_flush,
107
108
.bdrv_truncate    = raw_truncate,
109
@@ -XXX,XX +XXX,XX @@ static void hdev_parse_filename(const char *filename, QDict *options,
110
bdrv_parse_filename_strip_prefix(filename, "host_device:", options);
111
}
112
113
+static void hdev_refresh_limits(BlockDriverState *bs, Error **errp)
114
+{
115
+ /* XXX Does Windows support AIO on less than 512-byte alignment? */
116
+ bs->bl.request_alignment = 512;
117
+}
118
+
119
static int hdev_open(BlockDriverState *bs, QDict *options, int flags,
120
Error **errp)
121
{
122
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
123
.bdrv_probe_device    = hdev_probe_device,
124
.bdrv_file_open    = hdev_open,
125
.bdrv_close        = raw_close,
126
+ .bdrv_refresh_limits = hdev_refresh_limits,
127
128
- .bdrv_aio_readv = raw_aio_readv,
129
- .bdrv_aio_writev = raw_aio_writev,
130
+ .bdrv_aio_preadv = raw_aio_preadv,
131
+ .bdrv_aio_pwritev = raw_aio_pwritev,
132
.bdrv_aio_flush = raw_aio_flush,
133
134
.bdrv_detach_aio_context = raw_detach_aio_context,
135
diff --git a/block/win32-aio.c b/block/win32-aio.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/block/win32-aio.c
138
+++ b/block/win32-aio.c
139
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo win32_aiocb_info = {
140
141
BlockAIOCB *win32_aio_submit(BlockDriverState *bs,
142
QEMUWin32AIOState *aio, HANDLE hfile,
143
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
144
+ uint64_t offset, uint64_t bytes, QEMUIOVector *qiov,
145
BlockCompletionFunc *cb, void *opaque, int type)
146
{
147
struct QEMUWin32AIOCB *waiocb;
148
- uint64_t offset = sector_num * 512;
149
DWORD rc;
150
151
waiocb = qemu_aio_get(&win32_aiocb_info, bs, cb, opaque);
152
- waiocb->nbytes = nb_sectors * 512;
153
+ waiocb->nbytes = bytes;
154
waiocb->qiov = qiov;
155
waiocb->is_read = (type == QEMU_AIO_READ);
156
157
--
63
--
158
2.13.6
64
2.13.6
159
65
160
66
diff view generated by jsdifflib
1
From: Eric Blake <eblake@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
We are gradually moving away from sector-based interfaces, towards
3
The refcount cache size does not need to be set to its minimum value in
4
byte-based. Make the change for the last few sector-based callbacks
4
read_cache_sizes(), as it is set to at least its minimum value in
5
in the rbd driver.
5
qcow2_update_options_prepare().
6
6
7
Note that the driver was already using byte-based calls for
7
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
8
performing actual I/O, so this just gets rid of a round trip
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
of scaling; however, as I don't know if RBD is tolerant of
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
non-sector AIO operations, I went with the conservate approach
11
of adding .bdrv_refresh_limits to override the block layer
12
defaults back to the pre-patch value of 512.
13
14
Signed-off-by: Eric Blake <eblake@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
11
---
17
block/rbd.c | 40 ++++++++++++++++++++++------------------
12
block/qcow2.c | 5 ++---
18
1 file changed, 22 insertions(+), 18 deletions(-)
13
1 file changed, 2 insertions(+), 3 deletions(-)
19
14
20
diff --git a/block/rbd.c b/block/rbd.c
15
diff --git a/block/qcow2.c b/block/qcow2.c
21
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
22
--- a/block/rbd.c
17
--- a/block/qcow2.c
23
+++ b/block/rbd.c
18
+++ b/block/qcow2.c
24
@@ -XXX,XX +XXX,XX @@ done:
19
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
25
}
20
(uint64_t)DEFAULT_L2_CACHE_CLUSTERS
26
21
* s->cluster_size);
27
22
}
28
+static void qemu_rbd_refresh_limits(BlockDriverState *bs, Error **errp)
23
- if (!refcount_cache_size_set) {
29
+{
24
- *refcount_cache_size = min_refcount_cache;
30
+ /* XXX Does RBD support AIO on less than 512-byte alignment? */
25
- }
31
+ bs->bl.request_alignment = 512;
26
}
32
+}
27
+ /* l2_cache_size and refcount_cache_size are ensured to have at least
33
+
28
+ * their minimum values in qcow2_update_options_prepare() */
34
+
29
35
static int qemu_rbd_set_auth(rados_t cluster, const char *secretid,
30
if (*l2_cache_entry_size < (1 << MIN_CLUSTER_BITS) ||
36
Error **errp)
31
*l2_cache_entry_size > s->cluster_size ||
37
{
38
@@ -XXX,XX +XXX,XX @@ failed:
39
return NULL;
40
}
41
42
-static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
43
- int64_t sector_num,
44
- QEMUIOVector *qiov,
45
- int nb_sectors,
46
- BlockCompletionFunc *cb,
47
- void *opaque)
48
+static BlockAIOCB *qemu_rbd_aio_preadv(BlockDriverState *bs,
49
+ uint64_t offset, uint64_t bytes,
50
+ QEMUIOVector *qiov, int flags,
51
+ BlockCompletionFunc *cb,
52
+ void *opaque)
53
{
54
- return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
55
- (int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
56
+ return rbd_start_aio(bs, offset, qiov, bytes, cb, opaque,
57
RBD_AIO_READ);
58
}
59
60
-static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
61
- int64_t sector_num,
62
- QEMUIOVector *qiov,
63
- int nb_sectors,
64
- BlockCompletionFunc *cb,
65
- void *opaque)
66
+static BlockAIOCB *qemu_rbd_aio_pwritev(BlockDriverState *bs,
67
+ uint64_t offset, uint64_t bytes,
68
+ QEMUIOVector *qiov, int flags,
69
+ BlockCompletionFunc *cb,
70
+ void *opaque)
71
{
72
- return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
73
- (int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
74
+ return rbd_start_aio(bs, offset, qiov, bytes, cb, opaque,
75
RBD_AIO_WRITE);
76
}
77
78
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
79
.format_name = "rbd",
80
.instance_size = sizeof(BDRVRBDState),
81
.bdrv_parse_filename = qemu_rbd_parse_filename,
82
+ .bdrv_refresh_limits = qemu_rbd_refresh_limits,
83
.bdrv_file_open = qemu_rbd_open,
84
.bdrv_close = qemu_rbd_close,
85
.bdrv_reopen_prepare = qemu_rbd_reopen_prepare,
86
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_rbd = {
87
.bdrv_truncate = qemu_rbd_truncate,
88
.protocol_name = "rbd",
89
90
- .bdrv_aio_readv = qemu_rbd_aio_readv,
91
- .bdrv_aio_writev = qemu_rbd_aio_writev,
92
+ .bdrv_aio_preadv = qemu_rbd_aio_preadv,
93
+ .bdrv_aio_pwritev = qemu_rbd_aio_pwritev,
94
95
#ifdef LIBRBD_SUPPORTS_AIO_FLUSH
96
.bdrv_aio_flush = qemu_rbd_aio_flush,
97
--
32
--
98
2.13.6
33
2.13.6
99
34
100
35
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
The L2 and refcount caches have default sizes that can be overridden
3
Sufficient L2 cache can noticeably improve the performance when using
4
using the l2-cache-size and refcount-cache-size (an additional
4
large images with frequent I/O.
5
parameter named cache-size sets the combined size of both caches).
5
6
6
Previously, unless 'cache-size' was specified and was large enough, the
7
Unless forced by one of the aforementioned parameters, QEMU will set
7
L2 cache was set to a certain size without taking the virtual image size
8
the unspecified sizes so that the L2 cache is 4 times larger than the
8
into account.
9
refcount cache.
9
10
10
Now, the L2 cache assignment is aware of the virtual size of the image,
11
This is based on the premise that the refcount metadata needs to be
11
and will cover the entire image, unless the cache size needed for that is
12
only a fourth of the L2 metadata to cover the same amount of disk
12
larger than a certain maximum. This maximum is set to 1 MB by default
13
space. This is incorrect for two reasons:
13
(enough to cover an 8 GB image with the default cluster size) but can
14
14
be increased or decreased using the 'l2-cache-size' option. This option
15
a) The amount of disk covered by an L2 table depends solely on the
15
was previously documented as the *maximum* L2 cache size, and this patch
16
cluster size, but in the case of a refcount block it depends on
16
makes it behave as such, instead of as a constant size. Also, the
17
the cluster size *and* the width of each refcount entry.
17
existing option 'cache-size' can limit the sum of both L2 and refcount
18
The 4/1 ratio is only valid with 16-bit entries (the default).
18
caches, as previously.
19
19
20
b) When we talk about disk space and L2 tables we are talking about
20
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
21
guest space (L2 tables map guest clusters to host clusters),
21
Reviewed-by: Alberto Garcia <berto@igalia.com>
22
whereas refcount blocks are used for host clusters (including
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
23
L1/L2 tables and the refcount blocks themselves). On a fully
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
24
populated (and uncompressed) qcow2 file, image size > virtual size
25
so there are more refcount entries than L2 entries.
26
27
Problem (a) could be fixed by adjusting the algorithm to take into
28
account the refcount entry width. Problem (b) could be fixed by
29
increasing a bit the refcount cache size to account for the clusters
30
used for qcow2 metadata.
31
32
However this patch takes a completely different approach and instead
33
of keeping a ratio between both cache sizes it assigns as much as
34
possible to the L2 cache and the remainder to the refcount cache.
35
36
The reason is that L2 tables are used for every single I/O request
37
from the guest and the effect of increasing the cache is significant
38
and clearly measurable. Refcount blocks are however only used for
39
cluster allocation and internal snapshots and in practice are accessed
40
sequentially in most cases, so the effect of increasing the cache is
41
negligible (even when doing random writes from the guest).
42
43
So, make the refcount cache as small as possible unless the user
44
explicitly asks for a larger one.
45
46
Signed-off-by: Alberto Garcia <berto@igalia.com>
47
Reviewed-by: Eric Blake <eblake@redhat.com>
48
Reviewed-by: Max Reitz <mreitz@redhat.com>
49
Message-id: 9695182c2eb11b77cb319689a1ebaa4e7c9d6591.1523968389.git.berto@igalia.com
50
Signed-off-by: Max Reitz <mreitz@redhat.com>
51
---
24
---
52
block/qcow2.h | 4 ----
25
docs/qcow2-cache.txt | 15 ++++++++++-----
53
block/qcow2.c | 31 +++++++++++++++++++------------
26
block/qcow2.h | 4 +---
54
tests/qemu-iotests/137.out | 2 +-
27
block/qcow2.c | 21 +++++++++------------
55
3 files changed, 20 insertions(+), 17 deletions(-)
28
qemu-options.hx | 6 +++---
56
29
tests/qemu-iotests/137 | 8 +++++++-
30
tests/qemu-iotests/137.out | 4 +++-
31
6 files changed, 33 insertions(+), 25 deletions(-)
32
33
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
34
index XXXXXXX..XXXXXXX 100644
35
--- a/docs/qcow2-cache.txt
36
+++ b/docs/qcow2-cache.txt
37
@@ -XXX,XX +XXX,XX @@ There are a few things that need to be taken into account:
38
- Both caches must have a size that is a multiple of the cluster size
39
(or the cache entry size: see "Using smaller cache sizes" below).
40
41
- - The default L2 cache size is 8 clusters or 1MB (whichever is more),
42
- and the minimum is 2 clusters (or 2 cache entries, see below).
43
+ - The maximum L2 cache size is 1 MB by default (enough for full coverage
44
+ of 8 GB images, with the default cluster size). This value can be
45
+ modified using the "l2-cache-size" option. QEMU will not use more memory
46
+ than needed to hold all of the image's L2 tables, regardless of this max.
47
+ value. The minimal L2 cache size is 2 clusters (or 2 cache entries, see
48
+ below).
49
50
- The default (and minimum) refcount cache size is 4 clusters.
51
52
@@ -XXX,XX +XXX,XX @@ Some things to take into account:
53
always uses the cluster size as the entry size.
54
55
- If the L2 cache is big enough to hold all of the image's L2 tables
56
- (as explained in the "Choosing the right cache sizes" section
57
- earlier in this document) then none of this is necessary and you
58
- can omit the "l2-cache-entry-size" parameter altogether.
59
+ (as explained in the "Choosing the right cache sizes" and "How to
60
+ configure the cache sizes" sections in this document) then none of
61
+ this is necessary and you can omit the "l2-cache-entry-size"
62
+ parameter altogether.
63
64
65
Reducing the memory usage
57
diff --git a/block/qcow2.h b/block/qcow2.h
66
diff --git a/block/qcow2.h b/block/qcow2.h
58
index XXXXXXX..XXXXXXX 100644
67
index XXXXXXX..XXXXXXX 100644
59
--- a/block/qcow2.h
68
--- a/block/qcow2.h
60
+++ b/block/qcow2.h
69
+++ b/block/qcow2.h
61
@@ -XXX,XX +XXX,XX @@
70
@@ -XXX,XX +XXX,XX @@
62
#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
71
/* Must be at least 4 to cover all cases of refcount table growth */
63
#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
72
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
64
73
65
-/* The refblock cache needs only a fourth of the L2 cache size to cover as many
74
-/* Whichever is more */
66
- * clusters */
75
-#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
67
-#define DEFAULT_L2_REFCOUNT_SIZE_RATIO 4
76
-#define DEFAULT_L2_CACHE_SIZE S_1MiB
68
-
77
+#define DEFAULT_L2_CACHE_MAX_SIZE S_1MiB
69
#define DEFAULT_CLUSTER_SIZE 65536
78
70
79
#define DEFAULT_CLUSTER_SIZE S_64KiB
71
80
72
diff --git a/block/qcow2.c b/block/qcow2.c
81
diff --git a/block/qcow2.c b/block/qcow2.c
73
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
74
--- a/block/qcow2.c
83
--- a/block/qcow2.c
75
+++ b/block/qcow2.c
84
+++ b/block/qcow2.c
85
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
86
uint64_t *refcount_cache_size, Error **errp)
87
{
88
BDRVQcow2State *s = bs->opaque;
89
- uint64_t combined_cache_size;
90
+ uint64_t combined_cache_size, l2_cache_max_setting;
91
bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
92
int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
93
+ uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
94
+ uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
95
96
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
97
l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
98
refcount_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_REFCOUNT_CACHE_SIZE);
99
100
combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
101
- *l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
102
+ l2_cache_max_setting = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE,
103
+ DEFAULT_L2_CACHE_MAX_SIZE);
104
*refcount_cache_size = qemu_opt_get_size(opts,
105
QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
106
107
*l2_cache_entry_size = qemu_opt_get_size(
108
opts, QCOW2_OPT_L2_CACHE_ENTRY_SIZE, s->cluster_size);
109
110
+ *l2_cache_size = MIN(max_l2_cache, l2_cache_max_setting);
111
+
112
if (combined_cache_size_set) {
113
if (l2_cache_size_set && refcount_cache_size_set) {
114
error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
115
" and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
116
"at the same time");
117
return;
118
- } else if (*l2_cache_size > combined_cache_size) {
119
+ } else if (l2_cache_size_set &&
120
+ (l2_cache_max_setting > combined_cache_size)) {
121
error_setg(errp, QCOW2_OPT_L2_CACHE_SIZE " may not exceed "
122
QCOW2_OPT_CACHE_SIZE);
123
return;
76
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
124
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
77
} else if (refcount_cache_size_set) {
125
} else if (refcount_cache_size_set) {
78
*l2_cache_size = combined_cache_size - *refcount_cache_size;
126
*l2_cache_size = combined_cache_size - *refcount_cache_size;
79
} else {
127
} else {
80
- *refcount_cache_size = combined_cache_size
128
- uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
81
- / (DEFAULT_L2_REFCOUNT_SIZE_RATIO + 1);
129
- uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
82
- *l2_cache_size = combined_cache_size - *refcount_cache_size;
130
-
83
+ uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
131
/* Assign as much memory as possible to the L2 cache, and
84
+ uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
132
* use the remainder for the refcount cache */
85
+ uint64_t min_refcount_cache =
133
if (combined_cache_size >= max_l2_cache + min_refcount_cache) {
86
+ (uint64_t) MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
134
@@ -XXX,XX +XXX,XX @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
135
*l2_cache_size = combined_cache_size - *refcount_cache_size;
136
}
137
}
138
- } else {
139
- if (!l2_cache_size_set) {
140
- *l2_cache_size = MAX(DEFAULT_L2_CACHE_SIZE,
141
- (uint64_t)DEFAULT_L2_CACHE_CLUSTERS
142
- * s->cluster_size);
143
- }
144
}
145
/* l2_cache_size and refcount_cache_size are ensured to have at least
146
* their minimum values in qcow2_update_options_prepare() */
147
diff --git a/qemu-options.hx b/qemu-options.hx
148
index XXXXXXX..XXXXXXX 100644
149
--- a/qemu-options.hx
150
+++ b/qemu-options.hx
151
@@ -XXX,XX +XXX,XX @@ The maximum total size of the L2 table and refcount block caches in bytes
152
153
@item l2-cache-size
154
The maximum size of the L2 table cache in bytes
155
-(default: if cache-size is not defined - 1048576 bytes or 8 clusters, whichever
156
-is larger; otherwise, as large as possible or needed within the cache-size,
157
-while permitting the requested or the minimal refcount cache size)
158
+(default: if cache-size is not specified - 1M; otherwise, as large as possible
159
+within the cache-size, while permitting the requested or the minimal refcount
160
+cache size)
161
162
@item refcount-cache-size
163
The maximum size of the refcount block cache in bytes
164
diff --git a/tests/qemu-iotests/137 b/tests/qemu-iotests/137
165
index XXXXXXX..XXXXXXX 100755
166
--- a/tests/qemu-iotests/137
167
+++ b/tests/qemu-iotests/137
168
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
169
-c "reopen -o cache-size=1M,l2-cache-size=64k,refcount-cache-size=64k" \
170
-c "reopen -o cache-size=1M,l2-cache-size=2M" \
171
-c "reopen -o cache-size=1M,refcount-cache-size=2M" \
172
- -c "reopen -o l2-cache-size=256T" \
173
-c "reopen -o l2-cache-entry-size=33k" \
174
-c "reopen -o l2-cache-entry-size=128k" \
175
-c "reopen -o refcount-cache-size=256T" \
176
@@ -XXX,XX +XXX,XX @@ $QEMU_IO \
177
-c "reopen -o cache-clean-interval=-1" \
178
"$TEST_IMG" | _filter_qemu_io
179
180
+IMGOPTS="cluster_size=256k" _make_test_img 32P
181
+$QEMU_IO \
182
+ -c "reopen -o l2-cache-entry-size=512,l2-cache-size=1T" \
183
+ "$TEST_IMG" | _filter_qemu_io
87
+
184
+
88
+ /* Assign as much memory as possible to the L2 cache, and
185
+_make_test_img 64M
89
+ * use the remainder for the refcount cache */
186
+
90
+ if (combined_cache_size >= max_l2_cache + min_refcount_cache) {
187
echo
91
+ *l2_cache_size = max_l2_cache;
188
echo === Test transaction semantics ===
92
+ *refcount_cache_size = combined_cache_size - *l2_cache_size;
189
echo
93
+ } else {
94
+ *refcount_cache_size =
95
+ MIN(combined_cache_size, min_refcount_cache);
96
+ *l2_cache_size = combined_cache_size - *refcount_cache_size;
97
+ }
98
}
99
} else {
100
- if (!l2_cache_size_set && !refcount_cache_size_set) {
101
+ if (!l2_cache_size_set) {
102
*l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
103
(uint64_t)DEFAULT_L2_CACHE_CLUSTERS
104
* s->cluster_size);
105
- *refcount_cache_size = *l2_cache_size
106
- / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
107
- } else if (!l2_cache_size_set) {
108
- *l2_cache_size = *refcount_cache_size
109
- * DEFAULT_L2_REFCOUNT_SIZE_RATIO;
110
- } else if (!refcount_cache_size_set) {
111
- *refcount_cache_size = *l2_cache_size
112
- / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
113
+ }
114
+ if (!refcount_cache_size_set) {
115
+ *refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
116
}
117
}
118
119
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
190
diff --git a/tests/qemu-iotests/137.out b/tests/qemu-iotests/137.out
120
index XXXXXXX..XXXXXXX 100644
191
index XXXXXXX..XXXXXXX 100644
121
--- a/tests/qemu-iotests/137.out
192
--- a/tests/qemu-iotests/137.out
122
+++ b/tests/qemu-iotests/137.out
193
+++ b/tests/qemu-iotests/137.out
123
@@ -XXX,XX +XXX,XX @@ refcount-cache-size may not exceed cache-size
194
@@ -XXX,XX +XXX,XX @@ Parameter 'lazy-refcounts' expects 'on' or 'off'
124
L2 cache size too big
195
cache-size, l2-cache-size and refcount-cache-size may not be set at the same time
196
l2-cache-size may not exceed cache-size
197
refcount-cache-size may not exceed cache-size
198
-L2 cache size too big
125
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
199
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
126
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
200
L2 cache entry size must be a power of two between 512 and the cluster size (65536)
127
-L2 cache size too big
201
Refcount cache size too big
128
+Refcount cache size too big
202
@@ -XXX,XX +XXX,XX @@ Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-c
129
Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-check.template' ('all')
130
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
203
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
131
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
204
Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
205
Cache clean interval too big
206
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=36028797018963968
207
+L2 cache size too big
208
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
209
210
=== Test transaction semantics ===
211
132
--
212
--
133
2.13.6
213
2.13.6
134
214
135
215
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
We have just reduced the refcount cache size to the minimum unless
3
The upper limit on the L2 cache size is increased from 1 MB to 32 MB
4
the user explicitly requests a larger one, so we have to update the
4
on Linux platforms, and to 8 MB on other platforms (this difference is
5
documentation to reflect this change.
5
caused by the ability to set intervals for cache cleaning on Linux
6
platforms only).
6
7
7
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
This is done in order to allow default full coverage with the L2 cache
8
Message-id: c5f0bde23558dd9d33b21fffc76ac9953cc19c56.1523968389.git.berto@igalia.com
9
for images of up to 256 GB in size (was 8 GB). Note, that only the
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
needed amount to cover the full image is allocated. The value which is
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
changed here is just the upper limit on the L2 cache size, beyond which
12
it will not grow, even if the size of the image will require it to.
13
14
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
15
Reviewed-by: Alberto Garcia <berto@igalia.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
18
---
12
docs/qcow2-cache.txt | 33 ++++++++++++++++-----------------
19
docs/qcow2-cache.txt | 15 +++++++++------
13
1 file changed, 16 insertions(+), 17 deletions(-)
20
block/qcow2.h | 6 +++++-
21
qemu-options.hx | 6 +++---
22
3 files changed, 17 insertions(+), 10 deletions(-)
14
23
15
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
24
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
16
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
17
--- a/docs/qcow2-cache.txt
26
--- a/docs/qcow2-cache.txt
18
+++ b/docs/qcow2-cache.txt
27
+++ b/docs/qcow2-cache.txt
19
@@ -XXX,XX +XXX,XX @@ There are three options available, and all of them take bytes:
28
@@ -XXX,XX +XXX,XX @@ There are a few things that need to be taken into account:
20
"refcount-cache-size": maximum size of the refcount block cache
21
"cache-size": maximum size of both caches combined
22
23
-There are two things that need to be taken into account:
24
+There are a few things that need to be taken into account:
25
26
- Both caches must have a size that is a multiple of the cluster size
29
- Both caches must have a size that is a multiple of the cluster size
27
(or the cache entry size: see "Using smaller cache sizes" below).
30
(or the cache entry size: see "Using smaller cache sizes" below).
28
31
29
- - If you only set one of the options above, QEMU will automatically
32
- - The maximum L2 cache size is 1 MB by default (enough for full coverage
30
- adjust the others so that the L2 cache is 4 times bigger than the
33
- of 8 GB images, with the default cluster size). This value can be
31
- refcount cache.
34
- modified using the "l2-cache-size" option. QEMU will not use more memory
32
+ - The default L2 cache size is 8 clusters or 1MB (whichever is more),
35
- than needed to hold all of the image's L2 tables, regardless of this max.
33
+ and the minimum is 2 clusters (or 2 cache entries, see below).
36
- value. The minimal L2 cache size is 2 clusters (or 2 cache entries, see
34
37
- below).
35
-This means that these options are equivalent:
38
+ - The maximum L2 cache size is 32 MB by default on Linux platforms (enough
36
+ - The default (and minimum) refcount cache size is 4 clusters.
39
+ for full coverage of 256 GB images, with the default cluster size). This
37
40
+ value can be modified using the "l2-cache-size" option. QEMU will not use
38
- -drive file=hd.qcow2,l2-cache-size=2097152
41
+ more memory than needed to hold all of the image's L2 tables, regardless
39
- -drive file=hd.qcow2,refcount-cache-size=524288
42
+ of this max. value.
40
- -drive file=hd.qcow2,cache-size=2621440
43
+ On non-Linux platforms the maximal value is smaller by default (8 MB) and
41
+ - If only "cache-size" is specified then QEMU will assign as much
44
+ this difference stems from the fact that on Linux the cache can be cleared
42
+ memory as possible to the L2 cache before increasing the refcount
45
+ periodically if needed, using the "cache-clean-interval" option (see below).
43
+ cache size.
46
+ The minimal L2 cache size is 2 clusters (or 2 cache entries, see below).
44
47
45
-The reason for this 1/4 ratio is to ensure that both caches cover the
48
- The default (and minimum) refcount cache size is 4 clusters.
46
-same amount of disk space. Note however that this is only valid with
49
47
-the default value of refcount_bits (16). If you are using a different
50
diff --git a/block/qcow2.h b/block/qcow2.h
48
-value you might want to calculate both cache sizes yourself since QEMU
51
index XXXXXXX..XXXXXXX 100644
49
-will always use the same 1/4 ratio.
52
--- a/block/qcow2.h
50
+Unlike L2 tables, refcount blocks are not used during normal I/O but
53
+++ b/block/qcow2.h
51
+only during allocations and internal snapshots. In most cases they are
54
@@ -XXX,XX +XXX,XX @@
52
+accessed sequentially (even during random guest I/O) so increasing the
55
/* Must be at least 4 to cover all cases of refcount table growth */
53
+refcount cache size won't have any measurable effect in performance
56
#define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
54
+(this can change if you are using internal snapshots, so you may want
57
55
+to think about increasing the cache size if you use them heavily).
58
-#define DEFAULT_L2_CACHE_MAX_SIZE S_1MiB
56
59
+#ifdef CONFIG_LINUX
57
-It's also worth mentioning that there's no strict need for both caches
60
+#define DEFAULT_L2_CACHE_MAX_SIZE S_32MiB
58
-to cover the same amount of disk space. The refcount cache is used
61
+#else
59
-much less often than the L2 cache, so it's perfectly reasonable to
62
+#define DEFAULT_L2_CACHE_MAX_SIZE S_8MiB
60
-keep it small.
63
+#endif
61
+Before QEMU 2.12 the refcount cache had a default size of 1/4 of the
64
62
+L2 cache size. This resulted in unnecessarily large caches, so now the
65
#define DEFAULT_CLUSTER_SIZE S_64KiB
63
+refcount cache is as small as possible unless overridden by the user.
66
64
67
diff --git a/qemu-options.hx b/qemu-options.hx
65
68
index XXXXXXX..XXXXXXX 100644
66
Using smaller cache entries
69
--- a/qemu-options.hx
70
+++ b/qemu-options.hx
71
@@ -XXX,XX +XXX,XX @@ The maximum total size of the L2 table and refcount block caches in bytes
72
73
@item l2-cache-size
74
The maximum size of the L2 table cache in bytes
75
-(default: if cache-size is not specified - 1M; otherwise, as large as possible
76
-within the cache-size, while permitting the requested or the minimal refcount
77
-cache size)
78
+(default: if cache-size is not specified - 32M on Linux platforms, and 8M on
79
+non-Linux platforms; otherwise, as large as possible within the cache-size,
80
+while permitting the requested or the minimal refcount cache size)
81
82
@item refcount-cache-size
83
The maximum size of the refcount block cache in bytes
67
--
84
--
68
2.13.6
85
2.13.6
69
86
70
87
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
Update the rest of the filter drivers to support
3
The caches are now recalculated upon image resizing. This is done
4
BDRV_REQ_WRITE_UNCHANGED. They already forward write request flags to
4
because the new default behavior of assigning L2 cache relatively to
5
their children, so we just have to announce support for it.
5
the image size, implies that the cache will be adapted accordingly
6
after an image resize.
6
7
7
This patch does not cover the replication driver because that currently
8
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
8
does not support flags at all, and because it just grabs the WRITE
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
permission for its children when it can, so we should be fine just
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
submitting the incoming WRITE_UNCHANGED requests as normal writes.
11
---
12
block/qcow2.c | 11 +++++++++++
13
1 file changed, 11 insertions(+)
11
14
12
It also does not cover format drivers for similar reasons. They all use
15
diff --git a/block/qcow2.c b/block/qcow2.c
13
bdrv_format_default_perms() as their .bdrv_child_perm() implementation
14
so they just always grab the WRITE permission for their file children
15
whenever possible. In addition, it often would be difficult to
16
ascertain whether incoming unchanging writes end up as unchanging writes
17
in their files. So we just leave them as normal potentially changing
18
writes.
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
22
Reviewed-by: Alberto Garcia <berto@igalia.com>
23
Message-id: 20180421132929.21610-7-mreitz@redhat.com
24
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
25
Signed-off-by: Max Reitz <mreitz@redhat.com>
26
---
27
block/blkdebug.c | 9 +++++----
28
block/blkreplay.c | 3 +++
29
block/blkverify.c | 3 +++
30
block/copy-on-read.c | 10 ++++++----
31
block/mirror.c | 2 ++
32
block/raw-format.c | 9 +++++----
33
block/throttle.c | 6 ++++--
34
7 files changed, 28 insertions(+), 14 deletions(-)
35
36
diff --git a/block/blkdebug.c b/block/blkdebug.c
37
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
38
--- a/block/blkdebug.c
17
--- a/block/qcow2.c
39
+++ b/block/blkdebug.c
18
+++ b/block/qcow2.c
40
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
19
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
41
goto out;
20
uint64_t old_length;
21
int64_t new_l1_size;
22
int ret;
23
+ QDict *options;
24
25
if (prealloc != PREALLOC_MODE_OFF && prealloc != PREALLOC_MODE_METADATA &&
26
prealloc != PREALLOC_MODE_FALLOC && prealloc != PREALLOC_MODE_FULL)
27
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
28
}
42
}
29
}
43
30
44
- bs->supported_write_flags = BDRV_REQ_FUA &
31
+ bs->total_sectors = offset / BDRV_SECTOR_SIZE;
45
- bs->file->bs->supported_write_flags;
32
+
46
- bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
33
/* write updated header.size */
47
- bs->file->bs->supported_zero_flags;
34
offset = cpu_to_be64(offset);
48
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
35
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
49
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
36
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
50
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
51
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
52
+ bs->file->bs->supported_zero_flags);
53
ret = -EINVAL;
54
55
/* Set alignment overrides */
56
diff --git a/block/blkreplay.c b/block/blkreplay.c
57
index XXXXXXX..XXXXXXX 100755
58
--- a/block/blkreplay.c
59
+++ b/block/blkreplay.c
60
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
61
goto fail;
62
}
37
}
63
38
64
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
39
s->l1_vm_state_index = new_l1_size;
65
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
66
+
40
+
41
+ /* Update cache sizes */
42
+ options = qdict_clone_shallow(bs->options);
43
+ ret = qcow2_update_options(bs, options, s->flags, errp);
44
+ qobject_unref(options);
45
+ if (ret < 0) {
46
+ goto fail;
47
+ }
67
ret = 0;
48
ret = 0;
68
fail:
49
fail:
69
return ret;
50
qemu_co_mutex_unlock(&s->lock);
70
diff --git a/block/blkverify.c b/block/blkverify.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/block/blkverify.c
73
+++ b/block/blkverify.c
74
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
75
goto fail;
76
}
77
78
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
79
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
80
+
81
ret = 0;
82
fail:
83
qemu_opts_del(opts);
84
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/copy-on-read.c
87
+++ b/block/copy-on-read.c
88
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
89
return -EINVAL;
90
}
91
92
- bs->supported_write_flags = BDRV_REQ_FUA &
93
- bs->file->bs->supported_write_flags;
94
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
95
+ (BDRV_REQ_FUA &
96
+ bs->file->bs->supported_write_flags);
97
98
- bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
99
- bs->file->bs->supported_zero_flags;
100
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
101
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
102
+ bs->file->bs->supported_zero_flags);
103
104
return 0;
105
}
106
diff --git a/block/mirror.c b/block/mirror.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/block/mirror.c
109
+++ b/block/mirror.c
110
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
111
mirror_top_bs->implicit = true;
112
}
113
mirror_top_bs->total_sectors = bs->total_sectors;
114
+ mirror_top_bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
115
+ mirror_top_bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED;
116
bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
117
118
/* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
119
diff --git a/block/raw-format.c b/block/raw-format.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/block/raw-format.c
122
+++ b/block/raw-format.c
123
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
124
}
125
126
bs->sg = bs->file->bs->sg;
127
- bs->supported_write_flags = BDRV_REQ_FUA &
128
- bs->file->bs->supported_write_flags;
129
- bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
130
- bs->file->bs->supported_zero_flags;
131
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED |
132
+ (BDRV_REQ_FUA & bs->file->bs->supported_write_flags);
133
+ bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED |
134
+ ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
135
+ bs->file->bs->supported_zero_flags);
136
137
if (bs->probed && !bdrv_is_read_only(bs)) {
138
fprintf(stderr,
139
diff --git a/block/throttle.c b/block/throttle.c
140
index XXXXXXX..XXXXXXX 100644
141
--- a/block/throttle.c
142
+++ b/block/throttle.c
143
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
144
if (!bs->file) {
145
return -EINVAL;
146
}
147
- bs->supported_write_flags = bs->file->bs->supported_write_flags;
148
- bs->supported_zero_flags = bs->file->bs->supported_zero_flags;
149
+ bs->supported_write_flags = bs->file->bs->supported_write_flags |
150
+ BDRV_REQ_WRITE_UNCHANGED;
151
+ bs->supported_zero_flags = bs->file->bs->supported_zero_flags |
152
+ BDRV_REQ_WRITE_UNCHANGED;
153
154
return throttle_configure_tgm(bs, tgm, options, errp);
155
}
156
--
51
--
157
2.13.6
52
2.13.6
158
53
159
54
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
This adds a simple copy-on-read filter driver. It relies on the already
3
The default cache-clean-interval is set to 10 minutes, in order to lower
4
existing COR functionality in the central block layer code, which may be
4
the overhead of the qcow2 caches (before the default was 0, i.e.
5
moved here once we no longer need it there.
5
disabled).
6
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
* For non-Linux platforms the default is kept at 0, because
8
Message-id: 20180421132929.21610-2-mreitz@redhat.com
8
cache-clean-interval is not supported there yet.
9
10
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
14
---
13
qapi/block-core.json | 5 +-
15
qapi/block-core.json | 3 ++-
14
block/copy-on-read.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++
16
docs/qcow2-cache.txt | 4 ++--
15
block/Makefile.objs | 2 +-
17
block/qcow2.h | 4 +++-
16
3 files changed, 176 insertions(+), 2 deletions(-)
18
block/qcow2.c | 2 +-
17
create mode 100644 block/copy-on-read.c
19
qemu-options.hx | 2 +-
20
5 files changed, 9 insertions(+), 6 deletions(-)
18
21
19
diff --git a/qapi/block-core.json b/qapi/block-core.json
22
diff --git a/qapi/block-core.json b/qapi/block-core.json
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/qapi/block-core.json
24
--- a/qapi/block-core.json
22
+++ b/qapi/block-core.json
25
+++ b/qapi/block-core.json
23
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
24
# @vxhs: Since 2.10
25
# @throttle: Since 2.11
26
# @nvme: Since 2.12
27
+# @copy-on-read: Since 2.13
28
#
27
#
29
# Since: 2.9
28
# @cache-clean-interval: clean unused entries in the L2 and refcount
30
##
29
# caches. The interval is in seconds. The default value
31
{ 'enum': 'BlockdevDriver',
30
-# is 0 and it disables this feature (since 2.5)
32
- 'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop',
31
+# is 600, and 0 disables this feature. (since 2.5)
33
+ 'data': [ 'blkdebug', 'blkverify', 'bochs', 'cloop', 'copy-on-read',
32
+#
34
'dmg', 'file', 'ftp', 'ftps', 'gluster', 'host_cdrom',
33
# @encrypt: Image decryption options. Mandatory for
35
'host_device', 'http', 'https', 'iscsi', 'luks', 'nbd', 'nfs',
34
# encrypted images, except when doing a metadata-only
36
'null-aio', 'null-co', 'nvme', 'parallels', 'qcow', 'qcow2', 'qed',
35
# probe of the image. (since 2.10)
36
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
37
index XXXXXXX..XXXXXXX 100644
38
--- a/docs/qcow2-cache.txt
39
+++ b/docs/qcow2-cache.txt
40
@@ -XXX,XX +XXX,XX @@ This example removes all unused cache entries every 15 minutes:
41
42
-drive file=hd.qcow2,cache-clean-interval=900
43
44
-If unset, the default value for this parameter is 0 and it disables
45
-this feature.
46
+If unset, the default value for this parameter is 600. Setting it to 0
47
+disables this feature.
48
49
Note that this functionality currently relies on the MADV_DONTNEED
50
argument for madvise() to actually free the memory. This is a
51
diff --git a/block/qcow2.h b/block/qcow2.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/qcow2.h
54
+++ b/block/qcow2.h
37
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@
38
'blkverify': 'BlockdevOptionsBlkverify',
56
39
'bochs': 'BlockdevOptionsGenericFormat',
57
#ifdef CONFIG_LINUX
40
'cloop': 'BlockdevOptionsGenericFormat',
58
#define DEFAULT_L2_CACHE_MAX_SIZE S_32MiB
41
+ 'copy-on-read':'BlockdevOptionsGenericFormat',
59
+#define DEFAULT_CACHE_CLEAN_INTERVAL 600 /* seconds */
42
'dmg': 'BlockdevOptionsGenericFormat',
60
#else
43
'file': 'BlockdevOptionsFile',
61
#define DEFAULT_L2_CACHE_MAX_SIZE S_8MiB
44
'ftp': 'BlockdevOptionsCurlFtp',
62
+/* Cache clean interval is currently available only on Linux, so must be 0 */
45
@@ -XXX,XX +XXX,XX @@
63
+#define DEFAULT_CACHE_CLEAN_INTERVAL 0
46
'blkverify': 'BlockdevCreateNotSupported',
64
#endif
47
'bochs': 'BlockdevCreateNotSupported',
65
48
'cloop': 'BlockdevCreateNotSupported',
66
#define DEFAULT_CLUSTER_SIZE S_64KiB
49
+ 'copy-on-read': 'BlockdevCreateNotSupported',
67
50
'dmg': 'BlockdevCreateNotSupported',
68
-
51
'file': 'BlockdevCreateOptionsFile',
69
#define QCOW2_OPT_LAZY_REFCOUNTS "lazy-refcounts"
52
'ftp': 'BlockdevCreateNotSupported',
70
#define QCOW2_OPT_DISCARD_REQUEST "pass-discard-request"
53
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
71
#define QCOW2_OPT_DISCARD_SNAPSHOT "pass-discard-snapshot"
54
new file mode 100644
72
diff --git a/block/qcow2.c b/block/qcow2.c
55
index XXXXXXX..XXXXXXX
56
--- /dev/null
57
+++ b/block/copy-on-read.c
58
@@ -XXX,XX +XXX,XX @@
59
+/*
60
+ * Copy-on-read filter block driver
61
+ *
62
+ * Copyright (c) 2018 Red Hat, Inc.
63
+ *
64
+ * Author:
65
+ * Max Reitz <mreitz@redhat.com>
66
+ *
67
+ * This program is free software; you can redistribute it and/or
68
+ * modify it under the terms of the GNU General Public License as
69
+ * published by the Free Software Foundation; either version 2 or
70
+ * (at your option) version 3 of the License.
71
+ *
72
+ * This program is distributed in the hope that it will be useful,
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
+ * GNU General Public License for more details.
76
+ *
77
+ * You should have received a copy of the GNU General Public License
78
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
79
+ */
80
+
81
+#include "qemu/osdep.h"
82
+#include "block/block_int.h"
83
+
84
+
85
+static int cor_open(BlockDriverState *bs, QDict *options, int flags,
86
+ Error **errp)
87
+{
88
+ bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file, false,
89
+ errp);
90
+ if (!bs->file) {
91
+ return -EINVAL;
92
+ }
93
+
94
+ bs->supported_write_flags = BDRV_REQ_FUA &
95
+ bs->file->bs->supported_write_flags;
96
+
97
+ bs->supported_zero_flags = (BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP) &
98
+ bs->file->bs->supported_zero_flags;
99
+
100
+ return 0;
101
+}
102
+
103
+
104
+static void cor_close(BlockDriverState *bs)
105
+{
106
+}
107
+
108
+
109
+#define PERM_PASSTHROUGH (BLK_PERM_CONSISTENT_READ \
110
+ | BLK_PERM_WRITE \
111
+ | BLK_PERM_RESIZE)
112
+#define PERM_UNCHANGED (BLK_PERM_ALL & ~PERM_PASSTHROUGH)
113
+
114
+static void cor_child_perm(BlockDriverState *bs, BdrvChild *c,
115
+ const BdrvChildRole *role,
116
+ BlockReopenQueue *reopen_queue,
117
+ uint64_t perm, uint64_t shared,
118
+ uint64_t *nperm, uint64_t *nshared)
119
+{
120
+ if (c == NULL) {
121
+ *nperm = (perm & PERM_PASSTHROUGH) | BLK_PERM_WRITE_UNCHANGED;
122
+ *nshared = (shared & PERM_PASSTHROUGH) | PERM_UNCHANGED;
123
+ return;
124
+ }
125
+
126
+ *nperm = (perm & PERM_PASSTHROUGH) |
127
+ (c->perm & PERM_UNCHANGED);
128
+ *nshared = (shared & PERM_PASSTHROUGH) |
129
+ (c->shared_perm & PERM_UNCHANGED);
130
+}
131
+
132
+
133
+static int64_t cor_getlength(BlockDriverState *bs)
134
+{
135
+ return bdrv_getlength(bs->file->bs);
136
+}
137
+
138
+
139
+static int cor_truncate(BlockDriverState *bs, int64_t offset,
140
+ PreallocMode prealloc, Error **errp)
141
+{
142
+ return bdrv_truncate(bs->file, offset, prealloc, errp);
143
+}
144
+
145
+
146
+static int coroutine_fn cor_co_preadv(BlockDriverState *bs,
147
+ uint64_t offset, uint64_t bytes,
148
+ QEMUIOVector *qiov, int flags)
149
+{
150
+ return bdrv_co_preadv(bs->file, offset, bytes, qiov,
151
+ flags | BDRV_REQ_COPY_ON_READ);
152
+}
153
+
154
+
155
+static int coroutine_fn cor_co_pwritev(BlockDriverState *bs,
156
+ uint64_t offset, uint64_t bytes,
157
+ QEMUIOVector *qiov, int flags)
158
+{
159
+
160
+ return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
161
+}
162
+
163
+
164
+static int coroutine_fn cor_co_pwrite_zeroes(BlockDriverState *bs,
165
+ int64_t offset, int bytes,
166
+ BdrvRequestFlags flags)
167
+{
168
+ return bdrv_co_pwrite_zeroes(bs->file, offset, bytes, flags);
169
+}
170
+
171
+
172
+static int coroutine_fn cor_co_pdiscard(BlockDriverState *bs,
173
+ int64_t offset, int bytes)
174
+{
175
+ return bdrv_co_pdiscard(bs->file->bs, offset, bytes);
176
+}
177
+
178
+
179
+static void cor_eject(BlockDriverState *bs, bool eject_flag)
180
+{
181
+ bdrv_eject(bs->file->bs, eject_flag);
182
+}
183
+
184
+
185
+static void cor_lock_medium(BlockDriverState *bs, bool locked)
186
+{
187
+ bdrv_lock_medium(bs->file->bs, locked);
188
+}
189
+
190
+
191
+static bool cor_recurse_is_first_non_filter(BlockDriverState *bs,
192
+ BlockDriverState *candidate)
193
+{
194
+ return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
195
+}
196
+
197
+
198
+BlockDriver bdrv_copy_on_read = {
199
+ .format_name = "copy-on-read",
200
+
201
+ .bdrv_open = cor_open,
202
+ .bdrv_close = cor_close,
203
+ .bdrv_child_perm = cor_child_perm,
204
+
205
+ .bdrv_getlength = cor_getlength,
206
+ .bdrv_truncate = cor_truncate,
207
+
208
+ .bdrv_co_preadv = cor_co_preadv,
209
+ .bdrv_co_pwritev = cor_co_pwritev,
210
+ .bdrv_co_pwrite_zeroes = cor_co_pwrite_zeroes,
211
+ .bdrv_co_pdiscard = cor_co_pdiscard,
212
+
213
+ .bdrv_eject = cor_eject,
214
+ .bdrv_lock_medium = cor_lock_medium,
215
+
216
+ .bdrv_co_block_status = bdrv_co_block_status_from_file,
217
+
218
+ .bdrv_recurse_is_first_non_filter = cor_recurse_is_first_non_filter,
219
+
220
+ .has_variable_length = true,
221
+ .is_filter = true,
222
+};
223
+
224
+static void bdrv_copy_on_read_init(void)
225
+{
226
+ bdrv_register(&bdrv_copy_on_read);
227
+}
228
+
229
+block_init(bdrv_copy_on_read_init);
230
diff --git a/block/Makefile.objs b/block/Makefile.objs
231
index XXXXXXX..XXXXXXX 100644
73
index XXXXXXX..XXXXXXX 100644
232
--- a/block/Makefile.objs
74
--- a/block/qcow2.c
233
+++ b/block/Makefile.objs
75
+++ b/block/qcow2.c
234
@@ -XXX,XX +XXX,XX @@ block-obj-y += accounting.o dirty-bitmap.o
76
@@ -XXX,XX +XXX,XX @@ static int qcow2_update_options_prepare(BlockDriverState *bs,
235
block-obj-y += write-threshold.o
77
/* New interval for cache cleanup timer */
236
block-obj-y += backup.o
78
r->cache_clean_interval =
237
block-obj-$(CONFIG_REPLICATION) += replication.o
79
qemu_opt_get_number(opts, QCOW2_OPT_CACHE_CLEAN_INTERVAL,
238
-block-obj-y += throttle.o
80
- s->cache_clean_interval);
239
+block-obj-y += throttle.o copy-on-read.o
81
+ DEFAULT_CACHE_CLEAN_INTERVAL);
240
82
#ifndef CONFIG_LINUX
241
block-obj-y += crypto.o
83
if (r->cache_clean_interval != 0) {
242
84
error_setg(errp, QCOW2_OPT_CACHE_CLEAN_INTERVAL
85
diff --git a/qemu-options.hx b/qemu-options.hx
86
index XXXXXXX..XXXXXXX 100644
87
--- a/qemu-options.hx
88
+++ b/qemu-options.hx
89
@@ -XXX,XX +XXX,XX @@ it which is not used for the L2 cache)
90
91
@item cache-clean-interval
92
Clean unused entries in the L2 and refcount caches. The interval is in seconds.
93
-The default value is 0 and it disables this feature.
94
+The default value is 600. Setting it to 0 disables this feature.
95
96
@item pass-discard-request
97
Whether discard requests to the qcow2 device should be forwarded to the data
243
--
98
--
244
2.13.6
99
2.13.6
245
100
246
101
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
img_open_opts() takes a QemuOpts and converts them to a QDict, so all
3
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
4
values therein are strings. Then it may try to call qdict_get_bool(),
4
Reviewed-by: Alberto Garcia <berto@igalia.com>
5
however, which will fail with a segmentation fault every time:
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
$ ./qemu-img info -U --image-opts \
8
driver=file,filename=/dev/null,force-share=off
9
[1] 27869 segmentation fault (core dumped) ./qemu-img info -U
10
--image-opts driver=file,filename=/dev/null,force-share=off
11
12
Fix this by using qdict_get_str() and comparing the value as a string.
13
Also, when adding a force-share value to the QDict, add it as a string
14
so it fits the rest of the dict.
15
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
Message-id: 20180502202051.15493-3-mreitz@redhat.com
19
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
---
7
---
22
qemu-img.c | 4 ++--
8
block/qcow2.c | 4 ++--
23
1 file changed, 2 insertions(+), 2 deletions(-)
9
1 file changed, 2 insertions(+), 2 deletions(-)
24
10
25
diff --git a/qemu-img.c b/qemu-img.c
11
diff --git a/block/qcow2.c b/block/qcow2.c
26
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
27
--- a/qemu-img.c
13
--- a/block/qcow2.c
28
+++ b/qemu-img.c
14
+++ b/block/qcow2.c
29
@@ -XXX,XX +XXX,XX @@ static BlockBackend *img_open_opts(const char *optstr,
15
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
30
options = qemu_opts_to_qdict(opts, NULL);
16
/* 2^(s->refcount_order - 3) is the refcount width in bytes */
31
if (force_share) {
17
s->refcount_block_bits = s->cluster_bits - (s->refcount_order - 3);
32
if (qdict_haskey(options, BDRV_OPT_FORCE_SHARE)
18
s->refcount_block_size = 1 << s->refcount_block_bits;
33
- && !qdict_get_bool(options, BDRV_OPT_FORCE_SHARE)) {
19
- bs->total_sectors = header.size / 512;
34
+ && strcmp(qdict_get_str(options, BDRV_OPT_FORCE_SHARE), "on")) {
20
+ bs->total_sectors = header.size / BDRV_SECTOR_SIZE;
35
error_report("--force-share/-U conflicts with image options");
21
s->csize_shift = (62 - (s->cluster_bits - 8));
36
qobject_unref(options);
22
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
37
return NULL;
23
s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
38
}
24
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
39
- qdict_put_bool(options, BDRV_OPT_FORCE_SHARE, true);
25
goto fail;
40
+ qdict_put_str(options, BDRV_OPT_FORCE_SHARE, "on");
41
}
26
}
42
blk = blk_new_open(NULL, NULL, options, flags, &local_err);
27
43
if (!blk) {
28
- old_length = bs->total_sectors * 512;
29
+ old_length = bs->total_sectors * BDRV_SECTOR_SIZE;
30
new_l1_size = size_to_l1(s, offset);
31
32
if (offset < old_length) {
44
--
33
--
45
2.13.6
34
2.13.6
46
35
47
36
diff view generated by jsdifflib
1
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
1
Currently, the default values for werror and rerror have to be set
2
explicitly with blk_set_on_error() by the callers of blk_new(). The only
3
caller actually doing this is blockdev_init(), which is called for
4
BlockBackends created using -drive.
2
5
3
blk_get_aio_context verifies if BlockDriverState bs is not NULL,
6
In particular, anonymous BlockBackends created with
4
return bdrv_get_aio_context(bs) if true or qemu_get_aio_context()
7
-device ...,drive=<node-name> didn't get the correct default set and
5
otherwise. However, bdrv_get_aio_context from block.c already does
8
instead defaulted to the integer value 0 (= BLOCKDEV_ON_ERROR_REPORT).
6
this verification itself, also returning qemu_get_aio_context()
9
This is the intended default for rerror anyway, but the default for
7
if bs is NULL:
10
werror should be BLOCKDEV_ON_ERROR_ENOSPC.
8
11
9
AioContext *bdrv_get_aio_context(BlockDriverState *bs)
12
Set the defaults in blk_new() instead so that they apply no matter what
10
{
13
way the BlockBackend was created.
11
return bs ? bs->aio_context : qemu_get_aio_context();
12
}
13
14
14
This patch simplifies blk_get_aio_context to simply call
15
Cc: qemu-stable@nongnu.org
15
bdrv_get_aio_context instead of replicating the same logic.
16
17
Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
18
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Reviewed-by: Eric Blake <eblake@redhat.com>
18
Reviewed-by: Fam Zheng <famz@redhat.com>
20
---
19
---
21
block/block-backend.c | 8 +-------
20
block/block-backend.c | 3 +++
22
1 file changed, 1 insertion(+), 7 deletions(-)
21
tests/qemu-iotests/067.out | 1 +
22
2 files changed, 4 insertions(+)
23
23
24
diff --git a/block/block-backend.c b/block/block-backend.c
24
diff --git a/block/block-backend.c b/block/block-backend.c
25
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
26
--- a/block/block-backend.c
26
--- a/block/block-backend.c
27
+++ b/block/block-backend.c
27
+++ b/block/block-backend.c
28
@@ -XXX,XX +XXX,XX @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
28
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
29
29
blk->shared_perm = shared_perm;
30
AioContext *blk_get_aio_context(BlockBackend *blk)
30
blk_set_enable_write_cache(blk, true);
31
32
+ blk->on_read_error = BLOCKDEV_ON_ERROR_REPORT;
33
+ blk->on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
34
+
35
block_acct_init(&blk->stats);
36
37
notifier_list_init(&blk->remove_bs_notifiers);
38
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
39
index XXXXXXX..XXXXXXX 100644
40
--- a/tests/qemu-iotests/067.out
41
+++ b/tests/qemu-iotests/067.out
42
@@ -XXX,XX +XXX,XX @@ Testing: -device virtio-scsi -device scsi-cd,id=cd0
31
{
43
{
32
- BlockDriverState *bs = blk_bs(blk);
44
"return": [
33
-
45
{
34
- if (bs) {
46
+ "io-status": "ok",
35
- return bdrv_get_aio_context(bs);
47
"device": "",
36
- } else {
48
"locked": false,
37
- return qemu_get_aio_context();
49
"removable": true,
38
- }
39
+ return bdrv_get_aio_context(blk_bs(blk));
40
}
41
42
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
43
--
50
--
44
2.13.6
51
2.13.6
45
52
46
53
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Leonid Bloch <lbloch@janustech.com>
2
2
3
When we've reached the concluded state, we need to expose the error
3
Fixing cache-clean-interval documentation following the recent change to
4
state if applicable. Add the new field.
4
a default of 600 seconds on supported plarforms (only Linux currently).
5
5
6
This should be sufficient for determining if a job completed
6
Signed-off-by: Leonid Bloch <lbloch@janustech.com>
7
successfully or not after concluding; if we want to discriminate
8
based on how it failed more mechanically, we can always add an
9
explicit return code enumeration later.
10
11
I didn't bother to make it only show up if we are in the concluded
12
state; I don't think it's necessary.
13
14
Cc: qemu-stable@nongnu.org
15
Signed-off-by: John Snow <jsnow@redhat.com>
16
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
17
Reviewed-by: Alberto Garcia <berto@igalia.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
9
---
20
qapi/block-core.json | 6 +++++-
10
qapi/block-core.json | 3 ++-
21
blockjob.c | 2 ++
11
docs/qcow2-cache.txt | 20 ++++++++++----------
22
2 files changed, 7 insertions(+), 1 deletion(-)
12
qemu-options.hx | 3 ++-
13
3 files changed, 14 insertions(+), 12 deletions(-)
23
14
24
diff --git a/qapi/block-core.json b/qapi/block-core.json
15
diff --git a/qapi/block-core.json b/qapi/block-core.json
25
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
26
--- a/qapi/block-core.json
17
--- a/qapi/block-core.json
27
+++ b/qapi/block-core.json
18
+++ b/qapi/block-core.json
28
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
29
# @auto-dismiss: Job will dismiss itself when CONCLUDED, moving to the NULL
30
# state and disappearing from the query list. (since 2.12)
31
#
20
#
32
+# @error: Error information if the job did not complete successfully.
21
# @cache-clean-interval: clean unused entries in the L2 and refcount
33
+# Not set if the job completed successfully. (since 2.12.1)
22
# caches. The interval is in seconds. The default value
34
+#
23
-# is 600, and 0 disables this feature. (since 2.5)
35
# Since: 1.1
24
+# is 600 on supporting platforms, and 0 on other
36
##
25
+# platforms. 0 disables this feature. (since 2.5)
37
{ 'struct': 'BlockJobInfo',
26
#
38
@@ -XXX,XX +XXX,XX @@
27
# @encrypt: Image decryption options. Mandatory for
39
'offset': 'int', 'busy': 'bool', 'paused': 'bool', 'speed': 'int',
28
# encrypted images, except when doing a metadata-only
40
'io-status': 'BlockDeviceIoStatus', 'ready': 'bool',
29
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
41
'status': 'BlockJobStatus',
42
- 'auto-finalize': 'bool', 'auto-dismiss': 'bool' } }
43
+ 'auto-finalize': 'bool', 'auto-dismiss': 'bool',
44
+ '*error': 'str' } }
45
46
##
47
# @query-block-jobs:
48
diff --git a/blockjob.c b/blockjob.c
49
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
50
--- a/blockjob.c
31
--- a/docs/qcow2-cache.txt
51
+++ b/blockjob.c
32
+++ b/docs/qcow2-cache.txt
52
@@ -XXX,XX +XXX,XX @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
33
@@ -XXX,XX +XXX,XX @@ Reducing the memory usage
53
info->status = job->status;
34
It is possible to clean unused cache entries in order to reduce the
54
info->auto_finalize = job->auto_finalize;
35
memory usage during periods of low I/O activity.
55
info->auto_dismiss = job->auto_dismiss;
36
56
+ info->has_error = job->ret != 0;
37
-The parameter "cache-clean-interval" defines an interval (in seconds).
57
+ info->error = job->ret ? g_strdup(strerror(-job->ret)) : NULL;
38
-All cache entries that haven't been accessed during that interval are
58
return info;
39
-removed from memory.
59
}
40
+The parameter "cache-clean-interval" defines an interval (in seconds),
60
41
+after which all the cache entries that haven't been accessed during the
42
+interval are removed from memory. Setting this parameter to 0 disables this
43
+feature.
44
45
-This example removes all unused cache entries every 15 minutes:
46
+The following example removes all unused cache entries every 15 minutes:
47
48
-drive file=hd.qcow2,cache-clean-interval=900
49
50
-If unset, the default value for this parameter is 600. Setting it to 0
51
-disables this feature.
52
+If unset, the default value for this parameter is 600 on platforms which
53
+support this functionality, and is 0 (disabled) on other platforms.
54
55
-Note that this functionality currently relies on the MADV_DONTNEED
56
-argument for madvise() to actually free the memory. This is a
57
-Linux-specific feature, so cache-clean-interval is not supported in
58
-other systems.
59
+This functionality currently relies on the MADV_DONTNEED argument for
60
+madvise() to actually free the memory. This is a Linux-specific feature,
61
+so cache-clean-interval is not supported on other systems.
62
diff --git a/qemu-options.hx b/qemu-options.hx
63
index XXXXXXX..XXXXXXX 100644
64
--- a/qemu-options.hx
65
+++ b/qemu-options.hx
66
@@ -XXX,XX +XXX,XX @@ it which is not used for the L2 cache)
67
68
@item cache-clean-interval
69
Clean unused entries in the L2 and refcount caches. The interval is in seconds.
70
-The default value is 600. Setting it to 0 disables this feature.
71
+The default value is 600 on supporting platforms, and 0 on other platforms.
72
+Setting it to 0 disables this feature.
73
74
@item pass-discard-request
75
Whether discard requests to the qcow2 device should be forwarded to the data
61
--
76
--
62
2.13.6
77
2.13.6
63
78
64
79
diff view generated by jsdifflib
Deleted patch
1
Every job gets a non-NULL job->txn on creation, but it doesn't
2
necessarily keep it until it is decommissioned: Finalising a job removes
3
it from its transaction. Therefore, calling 'blockdev-job-finalize' a
4
second time on an already concluded job causes an assertion failure.
5
1
6
Remove job->txn from the assertion in block_job_finalize() to fix this.
7
block_job_do_finalize() still has the same assertion, but if a job is
8
already removed from its transaction, block_job_apply_verb() will
9
already error out before we run into that assertion.
10
11
Cc: qemu-stable@nongnu.org
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Eric Blake <eblake@redhat.com>
14
Reviewed-by: Max Reitz <mreitz@redhat.com>
15
Reviewed-by: John Snow <jsnow@redhat.com>
16
---
17
blockjob.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/blockjob.c b/blockjob.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/blockjob.c
23
+++ b/blockjob.c
24
@@ -XXX,XX +XXX,XX @@ void block_job_complete(BlockJob *job, Error **errp)
25
26
void block_job_finalize(BlockJob *job, Error **errp)
27
{
28
- assert(job && job->id && job->txn);
29
+ assert(job && job->id);
30
if (block_job_apply_verb(job, BLOCK_JOB_VERB_FINALIZE, errp)) {
31
return;
32
}
33
--
34
2.13.6
35
36
diff view generated by jsdifflib
Deleted patch
1
Block job drivers are not expected to mess with the internals of the
2
BlockJob object, so provide wrapper functions for one of the cases where
3
they still do it: Updating the progress counter.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
---
10
include/block/blockjob.h | 19 +++++++++++++++++++
11
block/backup.c | 22 +++++++++++++---------
12
block/commit.c | 16 ++++++++--------
13
block/mirror.c | 11 +++++------
14
block/stream.c | 14 ++++++++------
15
blockjob.c | 10 ++++++++++
16
6 files changed, 63 insertions(+), 29 deletions(-)
17
18
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/blockjob.h
21
+++ b/include/block/blockjob.h
22
@@ -XXX,XX +XXX,XX @@ void block_job_finalize(BlockJob *job, Error **errp);
23
void block_job_dismiss(BlockJob **job, Error **errp);
24
25
/**
26
+ * block_job_progress_update:
27
+ * @job: The job that has made progress
28
+ * @done: How much progress the job made
29
+ *
30
+ * Updates the progress counter of the job.
31
+ */
32
+void block_job_progress_update(BlockJob *job, uint64_t done);
33
+
34
+/**
35
+ * block_job_progress_set_remaining:
36
+ * @job: The job whose expected progress end value is set
37
+ * @remaining: Expected end value of the progress counter of the job
38
+ *
39
+ * Sets the expected end value of the progress counter of a job so that a
40
+ * completion percentage can be calculated when the progress is updated.
41
+ */
42
+void block_job_progress_set_remaining(BlockJob *job, uint64_t remaining);
43
+
44
+/**
45
* block_job_query:
46
* @job: The job to get information about.
47
*
48
diff --git a/block/backup.c b/block/backup.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/backup.c
51
+++ b/block/backup.c
52
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
53
BlockdevOnError on_source_error;
54
BlockdevOnError on_target_error;
55
CoRwlock flush_rwlock;
56
+ uint64_t len;
57
uint64_t bytes_read;
58
int64_t cluster_size;
59
bool compress;
60
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
61
62
trace_backup_do_cow_process(job, start);
63
64
- n = MIN(job->cluster_size, job->common.len - start);
65
+ n = MIN(job->cluster_size, job->len - start);
66
67
if (!bounce_buffer) {
68
bounce_buffer = blk_blockalign(blk, job->cluster_size);
69
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_do_cow(BackupBlockJob *job,
70
* offset field is an opaque progress value, it is not a disk offset.
71
*/
72
job->bytes_read += n;
73
- job->common.offset += n;
74
+ block_job_progress_update(&job->common, n);
75
}
76
77
out:
78
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
79
return;
80
}
81
82
- len = DIV_ROUND_UP(backup_job->common.len, backup_job->cluster_size);
83
+ len = DIV_ROUND_UP(backup_job->len, backup_job->cluster_size);
84
hbitmap_set(backup_job->copy_bitmap, 0, len);
85
}
86
87
@@ -XXX,XX +XXX,XX @@ static void backup_incremental_init_copy_bitmap(BackupBlockJob *job)
88
bdrv_set_dirty_iter(dbi, next_cluster * job->cluster_size);
89
}
90
91
- job->common.offset = job->common.len -
92
- hbitmap_count(job->copy_bitmap) * job->cluster_size;
93
+ /* TODO block_job_progress_set_remaining() would make more sense */
94
+ block_job_progress_update(&job->common,
95
+ job->len - hbitmap_count(job->copy_bitmap) * job->cluster_size);
96
97
bdrv_dirty_iter_free(dbi);
98
}
99
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
100
QLIST_INIT(&job->inflight_reqs);
101
qemu_co_rwlock_init(&job->flush_rwlock);
102
103
- nb_clusters = DIV_ROUND_UP(job->common.len, job->cluster_size);
104
+ nb_clusters = DIV_ROUND_UP(job->len, job->cluster_size);
105
+ block_job_progress_set_remaining(&job->common, job->len);
106
+
107
job->copy_bitmap = hbitmap_alloc(nb_clusters, 0);
108
if (job->sync_mode == MIRROR_SYNC_MODE_INCREMENTAL) {
109
backup_incremental_init_copy_bitmap(job);
110
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_run(void *opaque)
111
ret = backup_run_incremental(job);
112
} else {
113
/* Both FULL and TOP SYNC_MODE's require copying.. */
114
- for (offset = 0; offset < job->common.len;
115
+ for (offset = 0; offset < job->len;
116
offset += job->cluster_size) {
117
bool error_is_read;
118
int alloced = 0;
119
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
120
goto error;
121
}
122
123
- /* job->common.len is fixed, so we can't allow resize */
124
+ /* job->len is fixed, so we can't allow resize */
125
job = block_job_create(job_id, &backup_job_driver, txn, bs,
126
BLK_PERM_CONSISTENT_READ,
127
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
128
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
129
/* Required permissions are already taken with target's blk_new() */
130
block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL,
131
&error_abort);
132
- job->common.len = len;
133
+ job->len = len;
134
135
return &job->common;
136
137
diff --git a/block/commit.c b/block/commit.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/block/commit.c
140
+++ b/block/commit.c
141
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
142
int64_t n = 0; /* bytes */
143
void *buf = NULL;
144
int bytes_written = 0;
145
- int64_t base_len;
146
+ int64_t len, base_len;
147
148
- ret = s->common.len = blk_getlength(s->top);
149
-
150
- if (s->common.len < 0) {
151
+ ret = len = blk_getlength(s->top);
152
+ if (len < 0) {
153
goto out;
154
}
155
+ block_job_progress_set_remaining(&s->common, len);
156
157
ret = base_len = blk_getlength(s->base);
158
if (base_len < 0) {
159
goto out;
160
}
161
162
- if (base_len < s->common.len) {
163
- ret = blk_truncate(s->base, s->common.len, PREALLOC_MODE_OFF, NULL);
164
+ if (base_len < len) {
165
+ ret = blk_truncate(s->base, len, PREALLOC_MODE_OFF, NULL);
166
if (ret) {
167
goto out;
168
}
169
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
170
171
buf = blk_blockalign(s->top, COMMIT_BUFFER_SIZE);
172
173
- for (offset = 0; offset < s->common.len; offset += n) {
174
+ for (offset = 0; offset < len; offset += n) {
175
bool copy;
176
177
/* Note that even when no rate limit is applied we need to yield
178
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
179
}
180
}
181
/* Publish progress */
182
- s->common.offset += n;
183
+ block_job_progress_update(&s->common, n);
184
185
if (copy && s->common.speed) {
186
delay_ns = ratelimit_calculate_delay(&s->limit, n);
187
diff --git a/block/mirror.c b/block/mirror.c
188
index XXXXXXX..XXXXXXX 100644
189
--- a/block/mirror.c
190
+++ b/block/mirror.c
191
@@ -XXX,XX +XXX,XX @@ static void mirror_iteration_done(MirrorOp *op, int ret)
192
bitmap_set(s->cow_bitmap, chunk_num, nb_chunks);
193
}
194
if (!s->initial_zeroing_ongoing) {
195
- s->common.offset += op->bytes;
196
+ block_job_progress_update(&s->common, op->bytes);
197
}
198
}
199
qemu_iovec_destroy(&op->qiov);
200
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
201
block_job_pause_point(&s->common);
202
203
cnt = bdrv_get_dirty_count(s->dirty_bitmap);
204
- /* s->common.offset contains the number of bytes already processed so
205
- * far, cnt is the number of dirty bytes remaining and
206
- * s->bytes_in_flight is the number of bytes currently being
207
- * processed; together those are the current total operation length */
208
- s->common.len = s->common.offset + s->bytes_in_flight + cnt;
209
+ /* cnt is the number of dirty bytes remaining and s->bytes_in_flight is
210
+ * the number of bytes currently being processed; together those are
211
+ * the current remaining operation length */
212
+ block_job_progress_set_remaining(&s->common, s->bytes_in_flight + cnt);
213
214
/* Note that even when no rate limit is applied we need to yield
215
* periodically with no pending I/O so that bdrv_drain_all() returns.
216
diff --git a/block/stream.c b/block/stream.c
217
index XXXXXXX..XXXXXXX 100644
218
--- a/block/stream.c
219
+++ b/block/stream.c
220
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
221
BlockBackend *blk = s->common.blk;
222
BlockDriverState *bs = blk_bs(blk);
223
BlockDriverState *base = s->base;
224
+ int64_t len;
225
int64_t offset = 0;
226
uint64_t delay_ns = 0;
227
int error = 0;
228
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
229
goto out;
230
}
231
232
- s->common.len = bdrv_getlength(bs);
233
- if (s->common.len < 0) {
234
- ret = s->common.len;
235
+ len = bdrv_getlength(bs);
236
+ if (len < 0) {
237
+ ret = len;
238
goto out;
239
}
240
+ block_job_progress_set_remaining(&s->common, len);
241
242
buf = qemu_blockalign(bs, STREAM_BUFFER_SIZE);
243
244
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
245
bdrv_enable_copy_on_read(bs);
246
}
247
248
- for ( ; offset < s->common.len; offset += n) {
249
+ for ( ; offset < len; offset += n) {
250
bool copy;
251
252
/* Note that even when no rate limit is applied we need to yield
253
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
254
255
/* Finish early if end of backing file has been reached */
256
if (ret == 0 && n == 0) {
257
- n = s->common.len - offset;
258
+ n = len - offset;
259
}
260
261
copy = (ret == 1);
262
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
263
ret = 0;
264
265
/* Publish progress */
266
- s->common.offset += n;
267
+ block_job_progress_update(&s->common, n);
268
if (copy && s->common.speed) {
269
delay_ns = ratelimit_calculate_delay(&s->limit, n);
270
} else {
271
diff --git a/blockjob.c b/blockjob.c
272
index XXXXXXX..XXXXXXX 100644
273
--- a/blockjob.c
274
+++ b/blockjob.c
275
@@ -XXX,XX +XXX,XX @@ int block_job_complete_sync(BlockJob *job, Error **errp)
276
return block_job_finish_sync(job, &block_job_complete, errp);
277
}
278
279
+void block_job_progress_update(BlockJob *job, uint64_t done)
280
+{
281
+ job->offset += done;
282
+}
283
+
284
+void block_job_progress_set_remaining(BlockJob *job, uint64_t remaining)
285
+{
286
+ job->len = job->offset + remaining;
287
+}
288
+
289
BlockJobInfo *block_job_query(BlockJob *job, Error **errp)
290
{
291
BlockJobInfo *info;
292
--
293
2.13.6
294
295
diff view generated by jsdifflib
1
Every block job has a RateLimit, and they all do the exact same thing
1
Recently, the test case has started failing because some job related
2
with it, so it should be common infrastructure. Move the struct field
2
functions want to drop the AioContext lock even though it hasn't been
3
for a start.
3
taken:
4
5
(gdb) bt
6
#0 0x00007f51c067c9fb in raise () from /lib64/libc.so.6
7
#1 0x00007f51c067e77d in abort () from /lib64/libc.so.6
8
#2 0x0000558c9d5dde7b in error_exit (err=<optimized out>, msg=msg@entry=0x558c9d6fe120 <__func__.18373> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36
9
#3 0x0000558c9d6b5263 in qemu_mutex_unlock_impl (mutex=mutex@entry=0x558c9f3999a0, file=file@entry=0x558c9d6fd36f "util/async.c", line=line@entry=516) at util/qemu-thread-posix.c:96
10
#4 0x0000558c9d6b0565 in aio_context_release (ctx=ctx@entry=0x558c9f399940) at util/async.c:516
11
#5 0x0000558c9d5eb3da in job_completed_txn_abort (job=0x558c9f68e640) at job.c:738
12
#6 0x0000558c9d5eb227 in job_finish_sync (job=0x558c9f68e640, finish=finish@entry=0x558c9d5eb8d0 <job_cancel_err>, errp=errp@entry=0x0) at job.c:986
13
#7 0x0000558c9d5eb8ee in job_cancel_sync (job=<optimized out>) at job.c:941
14
#8 0x0000558c9d64d853 in replication_close (bs=<optimized out>) at block/replication.c:148
15
#9 0x0000558c9d5e5c9f in bdrv_close (bs=0x558c9f41b020) at block.c:3420
16
#10 bdrv_delete (bs=0x558c9f41b020) at block.c:3629
17
#11 bdrv_unref (bs=0x558c9f41b020) at block.c:4685
18
#12 0x0000558c9d62a3f3 in blk_remove_bs (blk=blk@entry=0x558c9f42a7c0) at block/block-backend.c:783
19
#13 0x0000558c9d62a667 in blk_delete (blk=0x558c9f42a7c0) at block/block-backend.c:402
20
#14 blk_unref (blk=0x558c9f42a7c0) at block/block-backend.c:457
21
#15 0x0000558c9d5dfcea in test_secondary_stop () at tests/test-replication.c:478
22
#16 0x00007f51c1f13178 in g_test_run_suite_internal () from /lib64/libglib-2.0.so.0
23
#17 0x00007f51c1f1337b in g_test_run_suite_internal () from /lib64/libglib-2.0.so.0
24
#18 0x00007f51c1f1337b in g_test_run_suite_internal () from /lib64/libglib-2.0.so.0
25
#19 0x00007f51c1f13552 in g_test_run_suite () from /lib64/libglib-2.0.so.0
26
#20 0x00007f51c1f13571 in g_test_run () from /lib64/libglib-2.0.so.0
27
#21 0x0000558c9d5de31f in main (argc=<optimized out>, argv=<optimized out>) at tests/test-replication.c:581
28
29
It is yet unclear whether this should really be considered a bug in the
30
test case or whether blk_unref() should work for callers that haven't
31
taken the AioContext lock, but in order to fix the build tests quickly,
32
just take the AioContext lock around blk_unref().
4
33
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
---
35
---
10
include/block/blockjob.h | 4 ++++
36
tests/test-replication.c | 11 +++++++++++
11
block/backup.c | 5 ++---
37
1 file changed, 11 insertions(+)
12
block/commit.c | 5 ++---
13
block/mirror.c | 6 +++---
14
block/stream.c | 5 ++---
15
5 files changed, 13 insertions(+), 12 deletions(-)
16
38
17
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
39
diff --git a/tests/test-replication.c b/tests/test-replication.c
18
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/blockjob.h
41
--- a/tests/test-replication.c
20
+++ b/include/block/blockjob.h
42
+++ b/tests/test-replication.c
21
@@ -XXX,XX +XXX,XX @@
43
@@ -XXX,XX +XXX,XX @@ static BlockBackend *start_primary(void)
22
#define BLOCKJOB_H
44
static void teardown_primary(void)
23
45
{
24
#include "block/block.h"
46
BlockBackend *blk;
25
+#include "qemu/ratelimit.h"
47
+ AioContext *ctx;
26
48
27
typedef struct BlockJobDriver BlockJobDriver;
49
/* remove P_ID */
28
typedef struct BlockJobTxn BlockJobTxn;
50
blk = blk_by_name(P_ID);
29
@@ -XXX,XX +XXX,XX @@ typedef struct BlockJob {
51
assert(blk);
30
/** Speed that was set with @block_job_set_speed. */
52
31
int64_t speed;
53
+ ctx = blk_get_aio_context(blk);
32
54
+ aio_context_acquire(ctx);
33
+ /** Rate limiting data structure for implementing @speed. */
55
monitor_remove_blk(blk);
34
+ RateLimit limit;
56
blk_unref(blk);
35
+
57
+ aio_context_release(ctx);
36
/** The completion function that will be called when the job completes. */
37
BlockCompletionFunc *cb;
38
39
diff --git a/block/backup.c b/block/backup.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/backup.c
42
+++ b/block/backup.c
43
@@ -XXX,XX +XXX,XX @@ typedef struct BackupBlockJob {
44
/* bitmap for sync=incremental */
45
BdrvDirtyBitmap *sync_bitmap;
46
MirrorSyncMode sync_mode;
47
- RateLimit limit;
48
BlockdevOnError on_source_error;
49
BlockdevOnError on_target_error;
50
CoRwlock flush_rwlock;
51
@@ -XXX,XX +XXX,XX @@ static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp)
52
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
53
return;
54
}
55
- ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
56
+ ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
57
}
58
}
58
59
59
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
60
static void test_primary_read(void)
60
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn yield_and_check(BackupBlockJob *job)
61
@@ -XXX,XX +XXX,XX @@ static void teardown_secondary(void)
61
* (without, VM does not reboot)
62
{
62
*/
63
/* only need to destroy two BBs */
63
if (job->common.speed) {
64
BlockBackend *blk;
64
- uint64_t delay_ns = ratelimit_calculate_delay(&job->limit,
65
+ AioContext *ctx;
65
+ uint64_t delay_ns = ratelimit_calculate_delay(&job->common.limit,
66
66
job->bytes_read);
67
/* remove S_LOCAL_DISK_ID */
67
job->bytes_read = 0;
68
blk = blk_by_name(S_LOCAL_DISK_ID);
68
block_job_sleep_ns(&job->common, delay_ns);
69
assert(blk);
69
diff --git a/block/commit.c b/block/commit.c
70
70
index XXXXXXX..XXXXXXX 100644
71
+ ctx = blk_get_aio_context(blk);
71
--- a/block/commit.c
72
+ aio_context_acquire(ctx);
72
+++ b/block/commit.c
73
monitor_remove_blk(blk);
73
@@ -XXX,XX +XXX,XX @@ enum {
74
blk_unref(blk);
74
75
+ aio_context_release(ctx);
75
typedef struct CommitBlockJob {
76
76
BlockJob common;
77
/* remove S_ID */
77
- RateLimit limit;
78
blk = blk_by_name(S_ID);
78
BlockDriverState *commit_top_bs;
79
assert(blk);
79
BlockBackend *top;
80
80
BlockBackend *base;
81
+ ctx = blk_get_aio_context(blk);
81
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn commit_run(void *opaque)
82
+ aio_context_acquire(ctx);
82
block_job_progress_update(&s->common, n);
83
monitor_remove_blk(blk);
83
84
blk_unref(blk);
84
if (copy && s->common.speed) {
85
+ aio_context_release(ctx);
85
- delay_ns = ratelimit_calculate_delay(&s->limit, n);
86
+ delay_ns = ratelimit_calculate_delay(&s->common.limit, n);
87
} else {
88
delay_ns = 0;
89
}
90
@@ -XXX,XX +XXX,XX @@ static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
91
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
92
return;
93
}
94
- ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
95
+ ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
96
}
86
}
97
87
98
static const BlockJobDriver commit_job_driver = {
88
static void test_secondary_read(void)
99
diff --git a/block/mirror.c b/block/mirror.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/mirror.c
102
+++ b/block/mirror.c
103
@@ -XXX,XX +XXX,XX @@ typedef struct MirrorBuffer {
104
105
typedef struct MirrorBlockJob {
106
BlockJob common;
107
- RateLimit limit;
108
BlockBackend *target;
109
BlockDriverState *mirror_top_bs;
110
BlockDriverState *source;
111
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
112
offset += io_bytes;
113
nb_chunks -= DIV_ROUND_UP(io_bytes, s->granularity);
114
if (s->common.speed) {
115
- delay_ns = ratelimit_calculate_delay(&s->limit, io_bytes_acct);
116
+ delay_ns = ratelimit_calculate_delay(&s->common.limit,
117
+ io_bytes_acct);
118
}
119
}
120
return delay_ns;
121
@@ -XXX,XX +XXX,XX @@ static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
122
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
123
return;
124
}
125
- ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
126
+ ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
127
}
128
129
static void mirror_complete(BlockJob *job, Error **errp)
130
diff --git a/block/stream.c b/block/stream.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/block/stream.c
133
+++ b/block/stream.c
134
@@ -XXX,XX +XXX,XX @@ enum {
135
136
typedef struct StreamBlockJob {
137
BlockJob common;
138
- RateLimit limit;
139
BlockDriverState *base;
140
BlockdevOnError on_error;
141
char *backing_file_str;
142
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn stream_run(void *opaque)
143
/* Publish progress */
144
block_job_progress_update(&s->common, n);
145
if (copy && s->common.speed) {
146
- delay_ns = ratelimit_calculate_delay(&s->limit, n);
147
+ delay_ns = ratelimit_calculate_delay(&s->common.limit, n);
148
} else {
149
delay_ns = 0;
150
}
151
@@ -XXX,XX +XXX,XX @@ static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
152
error_setg(errp, QERR_INVALID_PARAMETER, "speed");
153
return;
154
}
155
- ratelimit_set_speed(&s->limit, speed, SLICE_TIME);
156
+ ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
157
}
158
159
static const BlockJobDriver stream_job_driver = {
160
--
89
--
161
2.13.6
90
2.13.6
162
91
163
92
diff view generated by jsdifflib
Deleted patch
1
All block job drivers support .set_speed and all of them duplicate the
2
same code to implement it. Move that code to blockjob.c and remove the
3
now useless callback.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
---
10
include/block/blockjob.h | 2 ++
11
include/block/blockjob_int.h | 3 ---
12
block/backup.c | 13 -------------
13
block/commit.c | 14 --------------
14
block/mirror.c | 26 ++++++--------------------
15
block/stream.c | 14 --------------
16
blockjob.c | 12 ++++--------
17
7 files changed, 12 insertions(+), 72 deletions(-)
18
19
diff --git a/include/block/blockjob.h b/include/block/blockjob.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/blockjob.h
22
+++ b/include/block/blockjob.h
23
@@ -XXX,XX +XXX,XX @@
24
#include "block/block.h"
25
#include "qemu/ratelimit.h"
26
27
+#define BLOCK_JOB_SLICE_TIME 100000000ULL /* ns */
28
+
29
typedef struct BlockJobDriver BlockJobDriver;
30
typedef struct BlockJobTxn BlockJobTxn;
31
32
diff --git a/include/block/blockjob_int.h b/include/block/blockjob_int.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/block/blockjob_int.h
35
+++ b/include/block/blockjob_int.h
36
@@ -XXX,XX +XXX,XX @@ struct BlockJobDriver {
37
/** String describing the operation, part of query-block-jobs QMP API */
38
BlockJobType job_type;
39
40
- /** Optional callback for job types that support setting a speed limit */
41
- void (*set_speed)(BlockJob *job, int64_t speed, Error **errp);
42
-
43
/** Mandatory: Entrypoint for the Coroutine. */
44
CoroutineEntry *start;
45
46
diff --git a/block/backup.c b/block/backup.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/block/backup.c
49
+++ b/block/backup.c
50
@@ -XXX,XX +XXX,XX @@
51
#include "qemu/error-report.h"
52
53
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
54
-#define SLICE_TIME 100000000ULL /* ns */
55
56
typedef struct BackupBlockJob {
57
BlockJob common;
58
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn backup_before_write_notify(
59
return backup_do_cow(job, req->offset, req->bytes, NULL, true);
60
}
61
62
-static void backup_set_speed(BlockJob *job, int64_t speed, Error **errp)
63
-{
64
- BackupBlockJob *s = container_of(job, BackupBlockJob, common);
65
-
66
- if (speed < 0) {
67
- error_setg(errp, QERR_INVALID_PARAMETER, "speed");
68
- return;
69
- }
70
- ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
71
-}
72
-
73
static void backup_cleanup_sync_bitmap(BackupBlockJob *job, int ret)
74
{
75
BdrvDirtyBitmap *bm;
76
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver backup_job_driver = {
77
.instance_size = sizeof(BackupBlockJob),
78
.job_type = BLOCK_JOB_TYPE_BACKUP,
79
.start = backup_run,
80
- .set_speed = backup_set_speed,
81
.commit = backup_commit,
82
.abort = backup_abort,
83
.clean = backup_clean,
84
diff --git a/block/commit.c b/block/commit.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block/commit.c
87
+++ b/block/commit.c
88
@@ -XXX,XX +XXX,XX @@ enum {
89
COMMIT_BUFFER_SIZE = 512 * 1024, /* in bytes */
90
};
91
92
-#define SLICE_TIME 100000000ULL /* ns */
93
-
94
typedef struct CommitBlockJob {
95
BlockJob common;
96
BlockDriverState *commit_top_bs;
97
@@ -XXX,XX +XXX,XX @@ out:
98
block_job_defer_to_main_loop(&s->common, commit_complete, data);
99
}
100
101
-static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp)
102
-{
103
- CommitBlockJob *s = container_of(job, CommitBlockJob, common);
104
-
105
- if (speed < 0) {
106
- error_setg(errp, QERR_INVALID_PARAMETER, "speed");
107
- return;
108
- }
109
- ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
110
-}
111
-
112
static const BlockJobDriver commit_job_driver = {
113
.instance_size = sizeof(CommitBlockJob),
114
.job_type = BLOCK_JOB_TYPE_COMMIT,
115
- .set_speed = commit_set_speed,
116
.start = commit_run,
117
};
118
119
diff --git a/block/mirror.c b/block/mirror.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/block/mirror.c
122
+++ b/block/mirror.c
123
@@ -XXX,XX +XXX,XX @@
124
#include "qemu/ratelimit.h"
125
#include "qemu/bitmap.h"
126
127
-#define SLICE_TIME 100000000ULL /* ns */
128
#define MAX_IN_FLIGHT 16
129
#define MAX_IO_BYTES (1 << 20) /* 1 Mb */
130
#define DEFAULT_MIRROR_BUF_SIZE (MAX_IN_FLIGHT * MAX_IO_BYTES)
131
@@ -XXX,XX +XXX,XX @@ static void mirror_throttle(MirrorBlockJob *s)
132
{
133
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
134
135
- if (now - s->last_pause_ns > SLICE_TIME) {
136
+ if (now - s->last_pause_ns > BLOCK_JOB_SLICE_TIME) {
137
s->last_pause_ns = now;
138
block_job_sleep_ns(&s->common, 0);
139
} else {
140
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
141
142
/* Note that even when no rate limit is applied we need to yield
143
* periodically with no pending I/O so that bdrv_drain_all() returns.
144
- * We do so every SLICE_TIME nanoseconds, or when there is an error,
145
- * or when the source is clean, whichever comes first.
146
- */
147
+ * We do so every BLKOCK_JOB_SLICE_TIME nanoseconds, or when there is
148
+ * an error, or when the source is clean, whichever comes first. */
149
delta = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->last_pause_ns;
150
- if (delta < SLICE_TIME &&
151
+ if (delta < BLOCK_JOB_SLICE_TIME &&
152
s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
153
if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 ||
154
(cnt == 0 && s->in_flight > 0)) {
155
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn mirror_run(void *opaque)
156
ret = 0;
157
158
if (s->synced && !should_complete) {
159
- delay_ns = (s->in_flight == 0 && cnt == 0 ? SLICE_TIME : 0);
160
+ delay_ns = (s->in_flight == 0 &&
161
+ cnt == 0 ? BLOCK_JOB_SLICE_TIME : 0);
162
}
163
trace_mirror_before_sleep(s, cnt, s->synced, delay_ns);
164
block_job_sleep_ns(&s->common, delay_ns);
165
@@ -XXX,XX +XXX,XX @@ immediate_exit:
166
block_job_defer_to_main_loop(&s->common, mirror_exit, data);
167
}
168
169
-static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
170
-{
171
- MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
172
-
173
- if (speed < 0) {
174
- error_setg(errp, QERR_INVALID_PARAMETER, "speed");
175
- return;
176
- }
177
- ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
178
-}
179
-
180
static void mirror_complete(BlockJob *job, Error **errp)
181
{
182
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
183
@@ -XXX,XX +XXX,XX @@ static void mirror_drain(BlockJob *job)
184
static const BlockJobDriver mirror_job_driver = {
185
.instance_size = sizeof(MirrorBlockJob),
186
.job_type = BLOCK_JOB_TYPE_MIRROR,
187
- .set_speed = mirror_set_speed,
188
.start = mirror_run,
189
.complete = mirror_complete,
190
.pause = mirror_pause,
191
@@ -XXX,XX +XXX,XX @@ static const BlockJobDriver mirror_job_driver = {
192
static const BlockJobDriver commit_active_job_driver = {
193
.instance_size = sizeof(MirrorBlockJob),
194
.job_type = BLOCK_JOB_TYPE_COMMIT,
195
- .set_speed = mirror_set_speed,
196
.start = mirror_run,
197
.complete = mirror_complete,
198
.pause = mirror_pause,
199
diff --git a/block/stream.c b/block/stream.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/block/stream.c
202
+++ b/block/stream.c
203
@@ -XXX,XX +XXX,XX @@ enum {
204
STREAM_BUFFER_SIZE = 512 * 1024, /* in bytes */
205
};
206
207
-#define SLICE_TIME 100000000ULL /* ns */
208
-
209
typedef struct StreamBlockJob {
210
BlockJob common;
211
BlockDriverState *base;
212
@@ -XXX,XX +XXX,XX @@ out:
213
block_job_defer_to_main_loop(&s->common, stream_complete, data);
214
}
215
216
-static void stream_set_speed(BlockJob *job, int64_t speed, Error **errp)
217
-{
218
- StreamBlockJob *s = container_of(job, StreamBlockJob, common);
219
-
220
- if (speed < 0) {
221
- error_setg(errp, QERR_INVALID_PARAMETER, "speed");
222
- return;
223
- }
224
- ratelimit_set_speed(&s->common.limit, speed, SLICE_TIME);
225
-}
226
-
227
static const BlockJobDriver stream_job_driver = {
228
.instance_size = sizeof(StreamBlockJob),
229
.job_type = BLOCK_JOB_TYPE_STREAM,
230
- .set_speed = stream_set_speed,
231
.start = stream_run,
232
};
233
234
diff --git a/blockjob.c b/blockjob.c
235
index XXXXXXX..XXXXXXX 100644
236
--- a/blockjob.c
237
+++ b/blockjob.c
238
@@ -XXX,XX +XXX,XX @@ static bool block_job_timer_pending(BlockJob *job)
239
240
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
241
{
242
- Error *local_err = NULL;
243
int64_t old_speed = job->speed;
244
245
- if (!job->driver->set_speed) {
246
- error_setg(errp, QERR_UNSUPPORTED);
247
- return;
248
- }
249
if (block_job_apply_verb(job, BLOCK_JOB_VERB_SET_SPEED, errp)) {
250
return;
251
}
252
- job->driver->set_speed(job, speed, &local_err);
253
- if (local_err) {
254
- error_propagate(errp, local_err);
255
+ if (speed < 0) {
256
+ error_setg(errp, QERR_INVALID_PARAMETER, "speed");
257
return;
258
}
259
260
+ ratelimit_set_speed(&job->limit, speed, BLOCK_JOB_SLICE_TIME);
261
+
262
job->speed = speed;
263
if (speed && speed <= old_speed) {
264
return;
265
--
266
2.13.6
267
268
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Commit abd3622cc03cf41ed542126a540385f30a4c0175 added a case to 122
4
regarding how the qcow2 driver handles an incorrect compressed data
5
length value. This does not really fit into 122, as that file is
6
supposed to contain qemu-img convert test cases, which this case is not.
7
So this patch splits it off into its own file; maybe we will even get
8
more qcow2-only compression tests in the future.
9
10
Also, that test case does not work with refcount_bits=1, so mark that
11
option as unsupported.
12
13
Signed-off-by: Max Reitz <mreitz@redhat.com>
14
Message-id: 20180406164108.26118-1-mreitz@redhat.com
15
Reviewed-by: Eric Blake <eblake@redhat.com>
16
Signed-off-by: Alberto Garcia <berto@igalia.com>
17
Signed-off-by: Max Reitz <mreitz@redhat.com>
18
---
19
tests/qemu-iotests/122 | 47 ----------------------
20
tests/qemu-iotests/122.out | 33 ----------------
21
tests/qemu-iotests/214 | 97 ++++++++++++++++++++++++++++++++++++++++++++++
22
tests/qemu-iotests/214.out | 35 +++++++++++++++++
23
tests/qemu-iotests/group | 1 +
24
5 files changed, 133 insertions(+), 80 deletions(-)
25
create mode 100755 tests/qemu-iotests/214
26
create mode 100644 tests/qemu-iotests/214.out
27
28
diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122
29
index XXXXXXX..XXXXXXX 100755
30
--- a/tests/qemu-iotests/122
31
+++ b/tests/qemu-iotests/122
32
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c "read -P 0 1024k 1022k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _fil
33
34
35
echo
36
-echo "=== Corrupted size field in compressed cluster descriptor ==="
37
-echo
38
-# Create an empty image and fill half of it with compressed data.
39
-# The L2 entries of the two compressed clusters are located at
40
-# 0x800000 and 0x800008, their original values are 0x4008000000a00000
41
-# and 0x4008000000a00802 (5 sectors for compressed data each).
42
-_make_test_img 8M -o cluster_size=2M
43
-$QEMU_IO -c "write -c -P 0x11 0 2M" -c "write -c -P 0x11 2M 2M" "$TEST_IMG" \
44
- 2>&1 | _filter_qemu_io | _filter_testdir
45
-
46
-# Reduce size of compressed data to 4 sectors: this corrupts the image.
47
-poke_file "$TEST_IMG" $((0x800000)) "\x40\x06"
48
-$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
49
-
50
-# 'qemu-img check' however doesn't see anything wrong because it
51
-# doesn't try to decompress the data and the refcounts are consistent.
52
-# TODO: update qemu-img so this can be detected.
53
-_check_test_img
54
-
55
-# Increase size of compressed data to the maximum (8192 sectors).
56
-# This makes QEMU read more data (8192 sectors instead of 5, host
57
-# addresses [0xa00000, 0xdfffff]), but the decompression algorithm
58
-# stops once we have enough to restore the uncompressed cluster, so
59
-# the rest of the data is ignored.
60
-poke_file "$TEST_IMG" $((0x800000)) "\x7f\xfe"
61
-# Do it also for the second compressed cluster (L2 entry at 0x800008).
62
-# In this case the compressed data would span 3 host clusters
63
-# (host addresses: [0xa00802, 0xe00801])
64
-poke_file "$TEST_IMG" $((0x800008)) "\x7f\xfe"
65
-
66
-# Here the image is too small so we're asking QEMU to read beyond the
67
-# end of the image.
68
-$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
69
-# But if we grow the image we won't be reading beyond its end anymore.
70
-$QEMU_IO -c "write -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
71
-$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
72
-
73
-# The refcount data is however wrong because due to the increased size
74
-# of the compressed data it now reaches the following host clusters.
75
-# This can be repaired by qemu-img check by increasing the refcount of
76
-# those clusters.
77
-# TODO: update qemu-img to correct the compressed cluster size instead.
78
-_check_test_img -r all
79
-$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
80
-$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
81
-
82
-echo
83
echo "=== Full allocation with -S 0 ==="
84
echo
85
86
diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out
87
index XXXXXXX..XXXXXXX 100644
88
--- a/tests/qemu-iotests/122.out
89
+++ b/tests/qemu-iotests/122.out
90
@@ -XXX,XX +XXX,XX @@ read 1024/1024 bytes at offset 1047552
91
read 1046528/1046528 bytes at offset 1048576
92
1022 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
93
94
-=== Corrupted size field in compressed cluster descriptor ===
95
-
96
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608
97
-wrote 2097152/2097152 bytes at offset 0
98
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
99
-wrote 2097152/2097152 bytes at offset 2097152
100
-2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
101
-read failed: Input/output error
102
-No errors were found on the image.
103
-read 4194304/4194304 bytes at offset 0
104
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
105
-wrote 4194304/4194304 bytes at offset 4194304
106
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
107
-read 4194304/4194304 bytes at offset 0
108
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
109
-ERROR cluster 6 refcount=1 reference=3
110
-ERROR cluster 7 refcount=1 reference=2
111
-Repairing cluster 6 refcount=1 reference=3
112
-Repairing cluster 7 refcount=1 reference=2
113
-Repairing OFLAG_COPIED data cluster: l2_entry=8000000000c00000 refcount=3
114
-Repairing OFLAG_COPIED data cluster: l2_entry=8000000000e00000 refcount=2
115
-The following inconsistencies were found and repaired:
116
-
117
- 0 leaked clusters
118
- 4 corruptions
119
-
120
-Double checking the fixed image now...
121
-No errors were found on the image.
122
-read 4194304/4194304 bytes at offset 0
123
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
124
-read 4194304/4194304 bytes at offset 4194304
125
-4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
126
-
127
=== Full allocation with -S 0 ===
128
129
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
130
diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214
131
new file mode 100755
132
index XXXXXXX..XXXXXXX
133
--- /dev/null
134
+++ b/tests/qemu-iotests/214
135
@@ -XXX,XX +XXX,XX @@
136
+#!/bin/bash
137
+#
138
+# Test qcow2 image compression
139
+#
140
+# Copyright (C) 2018 Igalia, S.L.
141
+# Author: Alberto Garcia <berto@igalia.com>
142
+#
143
+# This program is free software; you can redistribute it and/or modify
144
+# it under the terms of the GNU General Public License as published by
145
+# the Free Software Foundation; either version 2 of the License, or
146
+# (at your option) any later version.
147
+#
148
+# This program is distributed in the hope that it will be useful,
149
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
150
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151
+# GNU General Public License for more details.
152
+#
153
+# You should have received a copy of the GNU General Public License
154
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
155
+#
156
+
157
+seq=$(basename "$0")
158
+echo "QA output created by $seq"
159
+
160
+here=$PWD
161
+status=1    # failure is the default!
162
+
163
+_cleanup()
164
+{
165
+ _cleanup_test_img
166
+}
167
+trap "_cleanup; exit \$status" 0 1 2 3 15
168
+
169
+# get standard environment, filters and checks
170
+. ./common.rc
171
+. ./common.filter
172
+
173
+_supported_fmt qcow2
174
+_supported_proto file
175
+_supported_os Linux
176
+
177
+# Repairing the corrupted image requires qemu-img check to store a
178
+# refcount up to 3, which requires at least two refcount bits.
179
+_unsupported_imgopts 'refcount_bits=1[^0-9]'
180
+
181
+
182
+echo
183
+echo "=== Corrupted size field in compressed cluster descriptor ==="
184
+echo
185
+# Create an empty image and fill half of it with compressed data.
186
+# The L2 entries of the two compressed clusters are located at
187
+# 0x800000 and 0x800008, their original values are 0x4008000000a00000
188
+# and 0x4008000000a00802 (5 sectors for compressed data each).
189
+_make_test_img 8M -o cluster_size=2M
190
+$QEMU_IO -c "write -c -P 0x11 0 2M" -c "write -c -P 0x11 2M 2M" "$TEST_IMG" \
191
+ 2>&1 | _filter_qemu_io | _filter_testdir
192
+
193
+# Reduce size of compressed data to 4 sectors: this corrupts the image.
194
+poke_file "$TEST_IMG" $((0x800000)) "\x40\x06"
195
+$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
196
+
197
+# 'qemu-img check' however doesn't see anything wrong because it
198
+# doesn't try to decompress the data and the refcounts are consistent.
199
+# TODO: update qemu-img so this can be detected.
200
+_check_test_img
201
+
202
+# Increase size of compressed data to the maximum (8192 sectors).
203
+# This makes QEMU read more data (8192 sectors instead of 5, host
204
+# addresses [0xa00000, 0xdfffff]), but the decompression algorithm
205
+# stops once we have enough to restore the uncompressed cluster, so
206
+# the rest of the data is ignored.
207
+poke_file "$TEST_IMG" $((0x800000)) "\x7f\xfe"
208
+# Do it also for the second compressed cluster (L2 entry at 0x800008).
209
+# In this case the compressed data would span 3 host clusters
210
+# (host addresses: [0xa00802, 0xe00801])
211
+poke_file "$TEST_IMG" $((0x800008)) "\x7f\xfe"
212
+
213
+# Here the image is too small so we're asking QEMU to read beyond the
214
+# end of the image.
215
+$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
216
+# But if we grow the image we won't be reading beyond its end anymore.
217
+$QEMU_IO -c "write -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
218
+$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
219
+
220
+# The refcount data is however wrong because due to the increased size
221
+# of the compressed data it now reaches the following host clusters.
222
+# This can be repaired by qemu-img check by increasing the refcount of
223
+# those clusters.
224
+# TODO: update qemu-img to correct the compressed cluster size instead.
225
+_check_test_img -r all
226
+$QEMU_IO -c "read -P 0x11 0 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
227
+$QEMU_IO -c "read -P 0x22 4M 4M" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir
228
+
229
+# success, all done
230
+echo '*** done'
231
+rm -f $seq.full
232
+status=0
233
diff --git a/tests/qemu-iotests/214.out b/tests/qemu-iotests/214.out
234
new file mode 100644
235
index XXXXXXX..XXXXXXX
236
--- /dev/null
237
+++ b/tests/qemu-iotests/214.out
238
@@ -XXX,XX +XXX,XX @@
239
+QA output created by 214
240
+
241
+=== Corrupted size field in compressed cluster descriptor ===
242
+
243
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=8388608
244
+wrote 2097152/2097152 bytes at offset 0
245
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
246
+wrote 2097152/2097152 bytes at offset 2097152
247
+2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
248
+read failed: Input/output error
249
+No errors were found on the image.
250
+read 4194304/4194304 bytes at offset 0
251
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
252
+wrote 4194304/4194304 bytes at offset 4194304
253
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
254
+read 4194304/4194304 bytes at offset 0
255
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
256
+ERROR cluster 6 refcount=1 reference=3
257
+ERROR cluster 7 refcount=1 reference=2
258
+Repairing cluster 6 refcount=1 reference=3
259
+Repairing cluster 7 refcount=1 reference=2
260
+Repairing OFLAG_COPIED data cluster: l2_entry=8000000000c00000 refcount=3
261
+Repairing OFLAG_COPIED data cluster: l2_entry=8000000000e00000 refcount=2
262
+The following inconsistencies were found and repaired:
263
+
264
+ 0 leaked clusters
265
+ 4 corruptions
266
+
267
+Double checking the fixed image now...
268
+No errors were found on the image.
269
+read 4194304/4194304 bytes at offset 0
270
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
271
+read 4194304/4194304 bytes at offset 4194304
272
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
273
+*** done
274
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
275
index XXXXXXX..XXXXXXX 100644
276
--- a/tests/qemu-iotests/group
277
+++ b/tests/qemu-iotests/group
278
@@ -XXX,XX +XXX,XX @@
279
211 rw auto quick
280
212 rw auto quick
281
213 rw auto quick
282
+214 rw auto
283
218 rw auto quick
284
--
285
2.13.6
286
287
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Currently, common.qemu only allows to match for results indicating
4
success. The only way to fail is by provoking a timeout. However,
5
sometimes we do have a defined failure output and can match for that,
6
which saves us from having to wait for the timeout in case of failure.
7
Because failure can sometimes just result in a _notrun in the test, it
8
is actually important to care about being able to fail quickly.
9
10
Also, sometimes we simply do not get any specific output in case of
11
success. The only way to handle this currently would be to define an
12
error message as the string to look for, which means that actual success
13
results in a timeout. This is really bad because it unnecessarily slows
14
down a succeeding test.
15
16
Therefore, this patch adds a new parameter $success_or_failure to
17
_timed_wait_for and _send_qemu_cmd. Setting this to a non-empty string
18
makes both commands expect two match parameters: If the first matches,
19
the function succeeds. If the second matches, the function fails.
20
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Message-id: 20180406151731.4285-2-mreitz@redhat.com
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
tests/qemu-iotests/common.qemu | 58 +++++++++++++++++++++++++++++++++++++-----
26
1 file changed, 51 insertions(+), 7 deletions(-)
27
28
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
29
index XXXXXXX..XXXXXXX 100644
30
--- a/tests/qemu-iotests/common.qemu
31
+++ b/tests/qemu-iotests/common.qemu
32
@@ -XXX,XX +XXX,XX @@ _in_fd=4
33
# response is not echoed out.
34
# If $mismatch_only is set, only non-matching responses will
35
# be echoed.
36
+#
37
+# If $success_or_failure is set, the meaning of the arguments is
38
+# changed as follows:
39
+# $2: A string to search for in the response; if found, this indicates
40
+# success and ${QEMU_STATUS[$1]} is set to 0.
41
+# $3: A string to search for in the response; if found, this indicates
42
+# failure and the test is either aborted (if $qemu_error_no_exit
43
+# is not set) or ${QEMU_STATUS[$1]} is set to -1 (otherwise).
44
function _timed_wait_for()
45
{
46
local h=${1}
47
shift
48
49
+ if [ -z "${success_or_failure}" ]; then
50
+ success_match=${*}
51
+ failure_match=
52
+ else
53
+ success_match=${1}
54
+ failure_match=${2}
55
+ fi
56
+
57
+ timeout=yes
58
+
59
QEMU_STATUS[$h]=0
60
while IFS= read -t ${QEMU_COMM_TIMEOUT} resp <&${QEMU_OUT[$h]}
61
do
62
@@ -XXX,XX +XXX,XX @@ function _timed_wait_for()
63
echo "${resp}" | _filter_testdir | _filter_qemu \
64
| _filter_qemu_io | _filter_qmp | _filter_hmp
65
fi
66
- grep -q "${*}" < <(echo "${resp}")
67
+ if [ -n "${failure_match}" ]; then
68
+ grep -q "${failure_match}" < <(echo "${resp}")
69
+ if [ $? -eq 0 ]; then
70
+ timeout=
71
+ break
72
+ fi
73
+ fi
74
+ grep -q "${success_match}" < <(echo "${resp}")
75
if [ $? -eq 0 ]; then
76
return
77
- elif [ -z "${silent}" ] && [ -n "${mismatch_only}" ]; then
78
+ fi
79
+ if [ -z "${silent}" ] && [ -n "${mismatch_only}" ]; then
80
echo "${resp}" | _filter_testdir | _filter_qemu \
81
| _filter_qemu_io | _filter_qmp | _filter_hmp
82
fi
83
@@ -XXX,XX +XXX,XX @@ function _timed_wait_for()
84
done
85
QEMU_STATUS[$h]=-1
86
if [ -z "${qemu_error_no_exit}" ]; then
87
- echo "Timeout waiting for ${*} on handle ${h}"
88
- exit 1 # Timeout means the test failed
89
+ if [ -n "${timeout}" ]; then
90
+ echo "Timeout waiting for ${success_match} on handle ${h}"
91
+ else
92
+ echo "Wrong response matching ${failure_match} on handle ${h}"
93
+ fi
94
+ exit 1 # Timeout or wrong match mean the test failed
95
fi
96
}
97
98
@@ -XXX,XX +XXX,XX @@ function _timed_wait_for()
99
# If $qemu_error_no_exit is set, then even if the expected response
100
# is not seen, we will not exit. $QEMU_STATUS[$1] will be set it -1 in
101
# that case.
102
+#
103
+# If $success_or_failure is set, then the last two strings are the
104
+# strings the response will be scanned for. The first of the two
105
+# indicates success, the latter indicates failure. Failure is handled
106
+# like a timeout.
107
function _send_qemu_cmd()
108
{
109
local h=${1}
110
@@ -XXX,XX +XXX,XX @@ function _send_qemu_cmd()
111
use_error="no"
112
fi
113
# This array element extraction is done to accommodate pathnames with spaces
114
- cmd=${@: 1:${#@}-1}
115
- shift $(($# - 1))
116
+ if [ -z "${success_or_failure}" ]; then
117
+ cmd=${@: 1:${#@}-1}
118
+ shift $(($# - 1))
119
+ else
120
+ cmd=${@: 1:${#@}-2}
121
+ shift $(($# - 2))
122
+ fi
123
124
while [ ${count} -gt 0 ]
125
do
126
echo "${cmd}" >&${QEMU_IN[${h}]}
127
if [ -n "${1}" ]; then
128
- qemu_error_no_exit=${use_error} _timed_wait_for ${h} "${1}"
129
+ if [ -z "${success_or_failure}" ]; then
130
+ qemu_error_no_exit=${use_error} _timed_wait_for ${h} "${1}"
131
+ else
132
+ qemu_error_no_exit=${use_error} _timed_wait_for ${h} "${1}" "${2}"
133
+ fi
134
if [ ${QEMU_STATUS[$h]} -eq 0 ]; then
135
return
136
fi
137
--
138
2.13.6
139
140
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
userfaultfd support depends on the host kernel, so it may not be
4
available. If so, 181 and 201 should be skipped.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180406151731.4285-3-mreitz@redhat.com
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/181 | 13 +++++++++++++
11
tests/qemu-iotests/201 | 13 +++++++++++++
12
2 files changed, 26 insertions(+)
13
14
diff --git a/tests/qemu-iotests/181 b/tests/qemu-iotests/181
15
index XXXXXXX..XXXXXXX 100755
16
--- a/tests/qemu-iotests/181
17
+++ b/tests/qemu-iotests/181
18
@@ -XXX,XX +XXX,XX @@ echo
19
# Enable postcopy-ram capability both on source and destination
20
silent=yes
21
_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)"
22
+
23
+qemu_error_no_exit=yes success_or_failure=yes \
24
+ _send_qemu_cmd $dest '' "(qemu)" "Postcopy is not supported"
25
+if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then
26
+ _send_qemu_cmd $dest '' "(qemu)"
27
+
28
+ _send_qemu_cmd $src 'quit' ""
29
+ _send_qemu_cmd $dest 'quit' ""
30
+ wait=1 _cleanup_qemu
31
+
32
+ _notrun 'Postcopy is not supported'
33
+fi
34
+
35
_send_qemu_cmd $src 'migrate_set_speed 4k' "(qemu)"
36
_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
37
_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
38
diff --git a/tests/qemu-iotests/201 b/tests/qemu-iotests/201
39
index XXXXXXX..XXXXXXX 100755
40
--- a/tests/qemu-iotests/201
41
+++ b/tests/qemu-iotests/201
42
@@ -XXX,XX +XXX,XX @@ echo
43
44
silent=yes
45
_send_qemu_cmd $dest 'migrate_set_capability postcopy-ram on' "(qemu)"
46
+
47
+qemu_error_no_exit=yes success_or_failure=yes \
48
+ _send_qemu_cmd $dest '' "(qemu)" "Postcopy is not supported"
49
+if [ ${QEMU_STATUS[$dest]} -lt 0 ]; then
50
+ _send_qemu_cmd $dest '' "(qemu)"
51
+
52
+ _send_qemu_cmd $src 'quit' ""
53
+ _send_qemu_cmd $dest 'quit' ""
54
+ wait=1 _cleanup_qemu
55
+
56
+ _notrun 'Postcopy is not supported'
57
+fi
58
+
59
_send_qemu_cmd $src 'migrate_set_capability postcopy-ram on' "(qemu)"
60
_send_qemu_cmd $src "migrate -d unix:${MIG_SOCKET}" "(qemu)"
61
62
--
63
2.13.6
64
65
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Currently we never actually check whether the WRITE_UNCHANGED
4
permission has been taken for unchanging writes. But the one check that
5
is commented out checks both WRITE and WRITE_UNCHANGED; and considering
6
that WRITE_UNCHANGED is already documented as being weaker than WRITE,
7
we should probably explicitly document WRITE to include WRITE_UNCHANGED.
8
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Message-id: 20180421132929.21610-3-mreitz@redhat.com
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Max Reitz <mreitz@redhat.com>
15
---
16
include/block/block.h | 3 +++
17
1 file changed, 3 insertions(+)
18
19
diff --git a/include/block/block.h b/include/block/block.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block.h
22
+++ b/include/block/block.h
23
@@ -XXX,XX +XXX,XX @@ enum {
24
* This permission (which is weaker than BLK_PERM_WRITE) is both enough and
25
* required for writes to the block node when the caller promises that
26
* the visible disk content doesn't change.
27
+ *
28
+ * As the BLK_PERM_WRITE permission is strictly stronger, either is
29
+ * sufficient to perform an unchanging write.
30
*/
31
BLK_PERM_WRITE_UNCHANGED = 0x04,
32
33
--
34
2.13.6
35
36
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This flag signifies that a write request will not change the visible
4
disk content. With this flag set, it is sufficient to have the
5
BLK_PERM_WRITE_UNCHANGED permission instead of BLK_PERM_WRITE.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20180421132929.21610-4-mreitz@redhat.com
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
include/block/block.h | 6 +++++-
15
block/io.c | 6 +++++-
16
2 files changed, 10 insertions(+), 2 deletions(-)
17
18
diff --git a/include/block/block.h b/include/block/block.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block.h
21
+++ b/include/block/block.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
BDRV_REQ_FUA = 0x10,
24
BDRV_REQ_WRITE_COMPRESSED = 0x20,
25
26
+ /* Signifies that this write request will not change the visible disk
27
+ * content. */
28
+ BDRV_REQ_WRITE_UNCHANGED = 0x40,
29
+
30
/* Mask of valid flags */
31
- BDRV_REQ_MASK = 0x3f,
32
+ BDRV_REQ_MASK = 0x7f,
33
} BdrvRequestFlags;
34
35
typedef struct BlockSizes {
36
diff --git a/block/io.c b/block/io.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/block/io.c
39
+++ b/block/io.c
40
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
41
assert(!waited || !req->serialising);
42
assert(req->overlap_offset <= offset);
43
assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
44
- assert(child->perm & BLK_PERM_WRITE);
45
+ if (flags & BDRV_REQ_WRITE_UNCHANGED) {
46
+ assert(child->perm & (BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE));
47
+ } else {
48
+ assert(child->perm & BLK_PERM_WRITE);
49
+ }
50
assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
51
52
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
53
--
54
2.13.6
55
56
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Message-id: 20180421132929.21610-5-mreitz@redhat.com
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
block/io.c | 6 ++++--
11
1 file changed, 4 insertions(+), 2 deletions(-)
12
13
diff --git a/block/io.c b/block/io.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/io.c
16
+++ b/block/io.c
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BdrvChild *child,
18
/* FIXME: Should we (perhaps conditionally) be setting
19
* BDRV_REQ_MAY_UNMAP, if it will allow for a sparser copy
20
* that still correctly reads as zero? */
21
- ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum, 0);
22
+ ret = bdrv_co_do_pwrite_zeroes(bs, cluster_offset, pnum,
23
+ BDRV_REQ_WRITE_UNCHANGED);
24
} else {
25
/* This does not change the data on the disk, it is not
26
* necessary to flush even in cache=writethrough mode.
27
*/
28
ret = bdrv_driver_pwritev(bs, cluster_offset, pnum,
29
- &local_qiov, 0);
30
+ &local_qiov,
31
+ BDRV_REQ_WRITE_UNCHANGED);
32
}
33
34
if (ret < 0) {
35
--
36
2.13.6
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
We just need to forward it to quorum's children (except in case of a
4
rewrite because of corruption), but for that we first have to support
5
flags in child requests at all.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
10
Message-id: 20180421132929.21610-6-mreitz@redhat.com
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Max Reitz <mreitz@redhat.com>
13
---
14
block/quorum.c | 19 +++++++++++++------
15
1 file changed, 13 insertions(+), 6 deletions(-)
16
17
diff --git a/block/quorum.c b/block/quorum.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/quorum.c
20
+++ b/block/quorum.c
21
@@ -XXX,XX +XXX,XX @@ struct QuorumAIOCB {
22
/* Request metadata */
23
uint64_t offset;
24
uint64_t bytes;
25
+ int flags;
26
27
QEMUIOVector *qiov; /* calling IOV */
28
29
@@ -XXX,XX +XXX,XX @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b)
30
static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
31
QEMUIOVector *qiov,
32
uint64_t offset,
33
- uint64_t bytes)
34
+ uint64_t bytes,
35
+ int flags)
36
{
37
BDRVQuorumState *s = bs->opaque;
38
QuorumAIOCB *acb = g_new(QuorumAIOCB, 1);
39
@@ -XXX,XX +XXX,XX @@ static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
40
.bs = bs,
41
.offset = offset,
42
.bytes = bytes,
43
+ .flags = flags,
44
.qiov = qiov,
45
.votes.compare = quorum_sha256_compare,
46
.votes.vote_list = QLIST_HEAD_INITIALIZER(acb.votes.vote_list),
47
@@ -XXX,XX +XXX,XX @@ static void quorum_rewrite_entry(void *opaque)
48
BDRVQuorumState *s = acb->bs->opaque;
49
50
/* Ignore any errors, it's just a correction attempt for already
51
- * corrupted data. */
52
+ * corrupted data.
53
+ * Mask out BDRV_REQ_WRITE_UNCHANGED because this overwrites the
54
+ * area with different data from the other children. */
55
bdrv_co_pwritev(s->children[co->idx], acb->offset, acb->bytes,
56
- acb->qiov, 0);
57
+ acb->qiov, acb->flags & ~BDRV_REQ_WRITE_UNCHANGED);
58
59
/* Wake up the caller after the last rewrite */
60
acb->rewrite_count--;
61
@@ -XXX,XX +XXX,XX @@ static int quorum_co_preadv(BlockDriverState *bs, uint64_t offset,
62
uint64_t bytes, QEMUIOVector *qiov, int flags)
63
{
64
BDRVQuorumState *s = bs->opaque;
65
- QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
66
+ QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
67
int ret;
68
69
acb->is_read = true;
70
@@ -XXX,XX +XXX,XX @@ static void write_quorum_entry(void *opaque)
71
72
sacb->bs = s->children[i]->bs;
73
sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
74
- acb->qiov, 0);
75
+ acb->qiov, acb->flags);
76
if (sacb->ret == 0) {
77
acb->success_count++;
78
} else {
79
@@ -XXX,XX +XXX,XX @@ static int quorum_co_pwritev(BlockDriverState *bs, uint64_t offset,
80
uint64_t bytes, QEMUIOVector *qiov, int flags)
81
{
82
BDRVQuorumState *s = bs->opaque;
83
- QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
84
+ QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
85
int i, ret;
86
87
for (i = 0; i < s->num_children; i++) {
88
@@ -XXX,XX +XXX,XX @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
89
}
90
s->next_child_index = s->num_children;
91
92
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
93
+
94
g_free(opened);
95
goto exit;
96
97
--
98
2.13.6
99
100
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Signed-off-by: Max Reitz <mreitz@redhat.com>
4
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
5
Reviewed-by: Alberto Garcia <berto@igalia.com>
6
Message-id: 20180421132929.21610-8-mreitz@redhat.com
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Max Reitz <mreitz@redhat.com>
9
---
10
tests/qemu-iotests/197 | 1 +
11
1 file changed, 1 insertion(+)
12
13
diff --git a/tests/qemu-iotests/197 b/tests/qemu-iotests/197
14
index XXXXXXX..XXXXXXX 100755
15
--- a/tests/qemu-iotests/197
16
+++ b/tests/qemu-iotests/197
17
@@ -XXX,XX +XXX,XX @@ esac
18
_cleanup()
19
{
20
_cleanup_test_img
21
+ rm -f "$TEST_WRAP"
22
rm -f "$BLKDBG_CONF"
23
}
24
trap "_cleanup; exit \$status" 0 1 2 3 15
25
--
26
2.13.6
27
28
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
iotest 197 tests copy-on-read using the (now old) copy-on-read flag.
4
Copy it to 215 and modify it to use the COR filter driver instead.
5
6
Signed-off-by: Max Reitz <mreitz@redhat.com>
7
Message-id: 20180421132929.21610-9-mreitz@redhat.com
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Max Reitz <mreitz@redhat.com>
10
---
11
tests/qemu-iotests/215 | 120 +++++++++++++++++++++++++++++++++++++++++++++
12
tests/qemu-iotests/215.out | 26 ++++++++++
13
tests/qemu-iotests/group | 1 +
14
3 files changed, 147 insertions(+)
15
create mode 100755 tests/qemu-iotests/215
16
create mode 100644 tests/qemu-iotests/215.out
17
18
diff --git a/tests/qemu-iotests/215 b/tests/qemu-iotests/215
19
new file mode 100755
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qemu-iotests/215
23
@@ -XXX,XX +XXX,XX @@
24
+#!/bin/bash
25
+#
26
+# Test case for copy-on-read into qcow2, using the COR filter driver
27
+#
28
+# Copyright (C) 2018 Red Hat, Inc.
29
+#
30
+# This program is free software; you can redistribute it and/or modify
31
+# it under the terms of the GNU General Public License as published by
32
+# the Free Software Foundation; either version 2 of the License, or
33
+# (at your option) any later version.
34
+#
35
+# This program is distributed in the hope that it will be useful,
36
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
37
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38
+# GNU General Public License for more details.
39
+#
40
+# You should have received a copy of the GNU General Public License
41
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
42
+#
43
+
44
+seq="$(basename $0)"
45
+echo "QA output created by $seq"
46
+
47
+here="$PWD"
48
+status=1 # failure is the default!
49
+
50
+# get standard environment, filters and checks
51
+. ./common.rc
52
+. ./common.filter
53
+
54
+TEST_WRAP="$TEST_DIR/t.wrap.qcow2"
55
+BLKDBG_CONF="$TEST_DIR/blkdebug.conf"
56
+
57
+# Sanity check: our use of blkdebug fails if $TEST_DIR contains spaces
58
+# or other problems
59
+case "$TEST_DIR" in
60
+ *[^-_a-zA-Z0-9/]*)
61
+ _notrun "Suspicious TEST_DIR='$TEST_DIR', cowardly refusing to run" ;;
62
+esac
63
+
64
+_cleanup()
65
+{
66
+ _cleanup_test_img
67
+ rm -f "$TEST_WRAP"
68
+ rm -f "$BLKDBG_CONF"
69
+}
70
+trap "_cleanup; exit \$status" 0 1 2 3 15
71
+
72
+# Test is supported for any backing file; but we force qcow2 for our wrapper.
73
+_supported_fmt generic
74
+_supported_proto generic
75
+_supported_os Linux
76
+# LUKS support may be possible, but it complicates things.
77
+_unsupported_fmt luks
78
+
79
+echo
80
+echo '=== Copy-on-read ==='
81
+echo
82
+
83
+# Prep the images
84
+# VPC rounds image sizes to a specific geometry, force a specific size.
85
+if [ "$IMGFMT" = "vpc" ]; then
86
+ IMGOPTS=$(_optstr_add "$IMGOPTS" "force_size")
87
+fi
88
+_make_test_img 4G
89
+$QEMU_IO -c "write -P 55 3G 1k" "$TEST_IMG" | _filter_qemu_io
90
+IMGPROTO=file IMGFMT=qcow2 IMGOPTS= TEST_IMG_FILE="$TEST_WRAP" \
91
+ _make_test_img -F "$IMGFMT" -b "$TEST_IMG" | _filter_img_create
92
+$QEMU_IO -f qcow2 -c "write -z -u 1M 64k" "$TEST_WRAP" | _filter_qemu_io
93
+
94
+# Ensure that a read of two clusters, but where one is already allocated,
95
+# does not re-write the allocated cluster
96
+cat > "$BLKDBG_CONF" <<EOF
97
+[inject-error]
98
+event = "cor_write"
99
+sector = "2048"
100
+EOF
101
+$QEMU_IO -c "open \
102
+ -o driver=copy-on-read,file.driver=blkdebug,file.config=$BLKDBG_CONF,file.image.driver=qcow2 $TEST_WRAP" \
103
+ -c "read -P 0 1M 128k" | _filter_qemu_io
104
+
105
+# Read the areas we want copied. A zero-length read should still be a
106
+# no-op. The next read is under 2G, but aligned so that rounding to
107
+# clusters copies more than 2G of zeroes. The final read will pick up
108
+# the non-zero data in the same cluster. Since a 2G read may exhaust
109
+# memory on some machines (particularly 32-bit), we skip the test if
110
+# that fails due to memory pressure.
111
+$QEMU_IO \
112
+ -c "open -o driver=copy-on-read,file.driver=qcow2 $TEST_WRAP" \
113
+ -c "read 0 0" \
114
+ | _filter_qemu_io
115
+output=$($QEMU_IO \
116
+ -c "open -o driver=copy-on-read,file.driver=qcow2 $TEST_WRAP" \
117
+ -c "read -P 0 1k $((2*1024*1024*1024 - 512))" \
118
+ 2>&1 | _filter_qemu_io)
119
+case $output in
120
+ *allocate*)
121
+ _notrun "Insufficent memory to run test" ;;
122
+ *) printf '%s\n' "$output" ;;
123
+esac
124
+$QEMU_IO \
125
+ -c "open -o driver=copy-on-read,file.driver=qcow2 $TEST_WRAP" \
126
+ -c "read -P 0 $((3*1024*1024*1024 + 1024)) 1k" \
127
+ | _filter_qemu_io
128
+
129
+# Copy-on-read is incompatible with read-only
130
+$QEMU_IO \
131
+ -c "open -r -o driver=copy-on-read,file.driver=qcow2 $TEST_WRAP" \
132
+ 2>&1 | _filter_testdir
133
+
134
+# Break the backing chain, and show that images are identical, and that
135
+# we properly copied over explicit zeros.
136
+$QEMU_IMG rebase -u -b "" -f qcow2 "$TEST_WRAP"
137
+$QEMU_IO -f qcow2 -c map "$TEST_WRAP"
138
+_check_test_img
139
+$QEMU_IMG compare -f $IMGFMT -F qcow2 "$TEST_IMG" "$TEST_WRAP"
140
+
141
+# success, all done
142
+echo '*** done'
143
+status=0
144
diff --git a/tests/qemu-iotests/215.out b/tests/qemu-iotests/215.out
145
new file mode 100644
146
index XXXXXXX..XXXXXXX
147
--- /dev/null
148
+++ b/tests/qemu-iotests/215.out
149
@@ -XXX,XX +XXX,XX @@
150
+QA output created by 215
151
+
152
+=== Copy-on-read ===
153
+
154
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296
155
+wrote 1024/1024 bytes at offset 3221225472
156
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
157
+Formatting 'TEST_DIR/t.wrap.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
158
+wrote 65536/65536 bytes at offset 1048576
159
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
160
+read 131072/131072 bytes at offset 1048576
161
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
162
+read 0/0 bytes at offset 0
163
+0 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
164
+read 2147483136/2147483136 bytes at offset 1024
165
+2 GiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
166
+read 1024/1024 bytes at offset 3221226496
167
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
168
+can't open device TEST_DIR/t.wrap.qcow2: Block node is read-only
169
+2 GiB (0x80010000) bytes allocated at offset 0 bytes (0x0)
170
+1023.938 MiB (0x3fff0000) bytes not allocated at offset 2 GiB (0x80010000)
171
+64 KiB (0x10000) bytes allocated at offset 3 GiB (0xc0000000)
172
+1023.938 MiB (0x3fff0000) bytes not allocated at offset 3 GiB (0xc0010000)
173
+No errors were found on the image.
174
+Images are identical.
175
+*** done
176
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
177
index XXXXXXX..XXXXXXX 100644
178
--- a/tests/qemu-iotests/group
179
+++ b/tests/qemu-iotests/group
180
@@ -XXX,XX +XXX,XX @@
181
212 rw auto quick
182
213 rw auto quick
183
214 rw auto
184
+215 rw auto quick
185
218 rw auto quick
186
--
187
2.13.6
188
189
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
COR across nodes (that is, you have some filter node between the
4
actually COR target and the node that performs the COR) cannot reliably
5
work together with the permission system when there is no explicit COR
6
node that can request the WRITE_UNCHANGED permission for its child.
7
This is because COR (currently) sneaks its requests by the usual
8
permission checks, so it can work without a WRITE* permission; but if
9
there is a filter node in between, that will re-issue the request, which
10
then passes through the usual check -- and if nobody has requested a
11
WRITE_UNCHANGED permission, that check will fail.
12
13
There is no real direct fix apart from hoping that there is someone who
14
has requested that permission; in case of just the qemu-io HMP command
15
(and no guest device), however, that is not the case. The real real fix
16
is to implement the copy-on-read flag through an implicitly added COR
17
node. Such a node can request the necessary permissions as shown in
18
this test.
19
20
Signed-off-by: Max Reitz <mreitz@redhat.com>
21
Message-id: 20180421132929.21610-10-mreitz@redhat.com
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Max Reitz <mreitz@redhat.com>
24
---
25
tests/qemu-iotests/216 | 115 +++++++++++++++++++++++++++++++++++++++++++++
26
tests/qemu-iotests/216.out | 28 +++++++++++
27
tests/qemu-iotests/group | 1 +
28
3 files changed, 144 insertions(+)
29
create mode 100755 tests/qemu-iotests/216
30
create mode 100644 tests/qemu-iotests/216.out
31
32
diff --git a/tests/qemu-iotests/216 b/tests/qemu-iotests/216
33
new file mode 100755
34
index XXXXXXX..XXXXXXX
35
--- /dev/null
36
+++ b/tests/qemu-iotests/216
37
@@ -XXX,XX +XXX,XX @@
38
+#!/usr/bin/env python
39
+#
40
+# Copy-on-read tests using a COR filter node
41
+#
42
+# Copyright (C) 2018 Red Hat, Inc.
43
+#
44
+# This program is free software; you can redistribute it and/or modify
45
+# it under the terms of the GNU General Public License as published by
46
+# the Free Software Foundation; either version 2 of the License, or
47
+# (at your option) any later version.
48
+#
49
+# This program is distributed in the hope that it will be useful,
50
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
51
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52
+# GNU General Public License for more details.
53
+#
54
+# You should have received a copy of the GNU General Public License
55
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
56
+#
57
+# Creator/Owner: Max Reitz <mreitz@redhat.com>
58
+
59
+import iotests
60
+from iotests import log, qemu_img_pipe, qemu_io, filter_qemu_io
61
+
62
+# Need backing file support
63
+iotests.verify_image_format(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'])
64
+iotests.verify_platform(['linux'])
65
+
66
+log('')
67
+log('=== Copy-on-read across nodes ===')
68
+log('')
69
+
70
+# The old copy-on-read mechanism without a filter node cannot request
71
+# WRITE_UNCHANGED permissions for its child. Therefore it just tries
72
+# to sneak its write by the usual permission system and holds its
73
+# fingers crossed. However, that sneaking does not work so well when
74
+# there is a filter node in the way: That will receive the write
75
+# request and re-issue a new one to its child, which this time is a
76
+# proper write request that will make the permission system cough --
77
+# unless there is someone at the top (like a guest device) that has
78
+# requested write permissions.
79
+#
80
+# A COR filter node, however, can request the proper permissions for
81
+# its child and therefore is not hit by this issue.
82
+
83
+with iotests.FilePath('base.img') as base_img_path, \
84
+ iotests.FilePath('top.img') as top_img_path, \
85
+ iotests.VM() as vm:
86
+
87
+ log('--- Setting up images ---')
88
+ log('')
89
+
90
+ qemu_img_pipe('create', '-f', iotests.imgfmt, base_img_path, '64M')
91
+
92
+ log(filter_qemu_io(qemu_io(base_img_path, '-c', 'write -P 1 0M 1M')))
93
+
94
+ qemu_img_pipe('create', '-f', iotests.imgfmt, '-b', base_img_path,
95
+ top_img_path)
96
+
97
+ log(filter_qemu_io(qemu_io(top_img_path, '-c', 'write -P 2 1M 1M')))
98
+
99
+ log('')
100
+ log('--- Doing COR ---')
101
+ log('')
102
+
103
+ # Compare with e.g. the following:
104
+ # vm.add_drive_raw('if=none,node-name=node0,copy-on-read=on,driver=raw,' \
105
+ # 'file.driver=%s,file.file.filename=%s' %
106
+ # (iotests.imgfmt, top_img_path))
107
+ # (Remove the blockdev-add instead.)
108
+ # ((Not tested here because it hits an assertion in the permission
109
+ # system.))
110
+
111
+ vm.launch()
112
+
113
+ log(vm.qmp('blockdev-add',
114
+ node_name='node0',
115
+ driver='copy-on-read',
116
+ file={
117
+ 'driver': 'raw',
118
+ 'file': {
119
+ 'driver': 'copy-on-read',
120
+ 'file': {
121
+ 'driver': 'raw',
122
+ 'file': {
123
+ 'driver': iotests.imgfmt,
124
+ 'file': {
125
+ 'driver': 'file',
126
+ 'filename': top_img_path
127
+ },
128
+ 'backing': {
129
+ 'driver': iotests.imgfmt,
130
+ 'file': {
131
+ 'driver': 'file',
132
+ 'filename': base_img_path
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }))
139
+
140
+ # Trigger COR
141
+ log(vm.qmp('human-monitor-command',
142
+ command_line='qemu-io node0 "read 0 64M"'))
143
+
144
+ vm.shutdown()
145
+
146
+ log('')
147
+ log('--- Checking COR result ---')
148
+ log('')
149
+
150
+ log(filter_qemu_io(qemu_io(base_img_path, '-c', 'discard 0 64M')))
151
+ log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 1 0M 1M')))
152
+ log(filter_qemu_io(qemu_io(top_img_path, '-c', 'read -P 2 1M 1M')))
153
diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out
154
new file mode 100644
155
index XXXXXXX..XXXXXXX
156
--- /dev/null
157
+++ b/tests/qemu-iotests/216.out
158
@@ -XXX,XX +XXX,XX @@
159
+
160
+=== Copy-on-read across nodes ===
161
+
162
+--- Setting up images ---
163
+
164
+wrote 1048576/1048576 bytes at offset 0
165
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
166
+
167
+wrote 1048576/1048576 bytes at offset 1048576
168
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
169
+
170
+
171
+--- Doing COR ---
172
+
173
+{u'return': {}}
174
+{u'return': u''}
175
+
176
+--- Checking COR result ---
177
+
178
+discard 67108864/67108864 bytes at offset 0
179
+64 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
180
+
181
+read 1048576/1048576 bytes at offset 0
182
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
183
+
184
+read 1048576/1048576 bytes at offset 1048576
185
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
186
+
187
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
188
index XXXXXXX..XXXXXXX 100644
189
--- a/tests/qemu-iotests/group
190
+++ b/tests/qemu-iotests/group
191
@@ -XXX,XX +XXX,XX @@
192
213 rw auto quick
193
214 rw auto
194
215 rw auto quick
195
+216 rw auto quick
196
218 rw auto quick
197
--
198
2.13.6
199
200
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
Add BDRV_REQ_WRITE_UNCHANGED to the list of flags honored during pwrite
4
and pwrite_zeroes, and also add a note on when you absolutely need to
5
support it.
6
7
Signed-off-by: Max Reitz <mreitz@redhat.com>
8
Message-id: 20180502140359.18222-1-mreitz@redhat.com
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Signed-off-by: Max Reitz <mreitz@redhat.com>
11
---
12
include/block/block_int.h | 18 ++++++++++++++++--
13
1 file changed, 16 insertions(+), 2 deletions(-)
14
15
diff --git a/include/block/block_int.h b/include/block/block_int.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block_int.h
18
+++ b/include/block/block_int.h
19
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
20
/* I/O Limits */
21
BlockLimits bl;
22
23
- /* Flags honored during pwrite (so far: BDRV_REQ_FUA) */
24
+ /* Flags honored during pwrite (so far: BDRV_REQ_FUA,
25
+ * BDRV_REQ_WRITE_UNCHANGED).
26
+ * If a driver does not support BDRV_REQ_WRITE_UNCHANGED, those
27
+ * writes will be issued as normal writes without the flag set.
28
+ * This is important to note for drivers that do not explicitly
29
+ * request a WRITE permission for their children and instead take
30
+ * the same permissions as their parent did (this is commonly what
31
+ * block filters do). Such drivers have to be aware that the
32
+ * parent may have taken a WRITE_UNCHANGED permission only and is
33
+ * issuing such requests. Drivers either must make sure that
34
+ * these requests do not result in plain WRITE accesses (usually
35
+ * by supporting BDRV_REQ_WRITE_UNCHANGED, and then forwarding
36
+ * every incoming write request as-is, including potentially that
37
+ * flag), or they have to explicitly take the WRITE permission for
38
+ * their children. */
39
unsigned int supported_write_flags;
40
/* Flags honored during pwrite_zeroes (so far: BDRV_REQ_FUA,
41
- * BDRV_REQ_MAY_UNMAP) */
42
+ * BDRV_REQ_MAY_UNMAP, BDRV_REQ_WRITE_UNCHANGED) */
43
unsigned int supported_zero_flags;
44
45
/* the following member gives a name to every node on the bs graph. */
46
--
47
2.13.6
48
49
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
qemu_event_reset() must be called before the AIO request in a different
2
iothread is submitted. Otherwise the request could be completed before
3
we do the qemu_event_reset() and the test would hang in
4
qemu_event_wait().
2
5
3
Currently, qemu-io only uses string-valued blockdev options (as all are
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
converted directly from QemuOpts) -- with one exception: -U adds the
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
5
force-share option as a boolean. This in itself is already a bit
8
Tested-by: Max Reitz <mreitz@redhat.com>
6
questionable, but a real issue is that it also assumes the value already
7
existing in the options QDict would be a boolean, which is wrong.
8
9
That has the following effect:
10
11
$ ./qemu-io -r -U --image-opts \
12
driver=file,filename=/dev/null,force-share=off
13
[1] 15200 segmentation fault (core dumped) ./qemu-io -r -U
14
--image-opts driver=file,filename=/dev/null,force-share=off
15
16
Since @opts is converted from QemuOpts, the value must be a string, and
17
we have to compare it as such. Consequently, it makes sense to also set
18
it as a string instead of a boolean.
19
20
Cc: qemu-stable@nongnu.org
21
Signed-off-by: Max Reitz <mreitz@redhat.com>
22
Message-id: 20180502202051.15493-2-mreitz@redhat.com
23
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Signed-off-by: Max Reitz <mreitz@redhat.com>
25
---
9
---
26
qemu-io.c | 4 ++--
10
tests/test-bdrv-drain.c | 4 ++--
27
1 file changed, 2 insertions(+), 2 deletions(-)
11
1 file changed, 2 insertions(+), 2 deletions(-)
28
12
29
diff --git a/qemu-io.c b/qemu-io.c
13
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
30
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
31
--- a/qemu-io.c
15
--- a/tests/test-bdrv-drain.c
32
+++ b/qemu-io.c
16
+++ b/tests/test-bdrv-drain.c
33
@@ -XXX,XX +XXX,XX @@ static int openfile(char *name, int flags, bool writethrough, bool force_share,
17
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
34
opts = qdict_new();
18
s->bh_indirection_ctx = ctx_b;
19
20
aio_ret = -EINPROGRESS;
21
+ qemu_event_reset(&done_event);
22
+
23
if (drain_thread == 0) {
24
acb = blk_aio_preadv(blk, 0, &qiov, 0, test_iothread_aio_cb, &aio_ret);
25
} else {
26
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
27
* but the drain in this thread can continue immediately after
28
* bdrv_dec_in_flight() and aio_ret might be assigned only slightly
29
* later. */
30
- qemu_event_reset(&done_event);
31
do_drain_begin(drain_type, bs);
32
g_assert_cmpint(bs->in_flight, ==, 0);
33
34
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
35
}
35
}
36
if (qdict_haskey(opts, BDRV_OPT_FORCE_SHARE)
36
break;
37
- && !qdict_get_bool(opts, BDRV_OPT_FORCE_SHARE)) {
37
case 1:
38
+ && strcmp(qdict_get_str(opts, BDRV_OPT_FORCE_SHARE), "on")) {
38
- qemu_event_reset(&done_event);
39
error_report("-U conflicts with image options");
39
aio_bh_schedule_oneshot(ctx_a, test_iothread_drain_entry, &data);
40
qobject_unref(opts);
40
qemu_event_wait(&done_event);
41
return 1;
41
break;
42
}
43
- qdict_put_bool(opts, BDRV_OPT_FORCE_SHARE, true);
44
+ qdict_put_str(opts, BDRV_OPT_FORCE_SHARE, "on");
45
}
46
qemuio_blk = blk_new_open(name, NULL, opts, flags, &local_err);
47
if (!qemuio_blk) {
48
--
42
--
49
2.13.6
43
2.13.6
50
44
51
45
diff view generated by jsdifflib