1
The following changes since commit ad88e4252f09c2956b99c90de39e95bab2e8e7af:
1
The following changes since commit e1e44a9916b4318e943aecd669e096222cb3eaeb:
2
2
3
Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jun-1-2019' into staging (2019-06-03 10:25:12 +0100)
3
Merge remote-tracking branch 'remotes/xtensa/tags/20180316-xtensa' into staging (2018-03-17 14:15:03 +0000)
4
4
5
are available in the Git repository at:
5
are available in the git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 9593db8ccd27800ce4a17f1d5b735b9130c541a2:
9
for you to fetch changes up to 63ca8406beac44aa59c389ed8578d0c7b3da3402:
10
10
11
iotests: Fix duplicated diff output on failure (2019-06-03 16:33:20 +0200)
11
iotests: Avoid realpath, for CentOS 6 (2018-03-19 12:01:39 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
16
- block: AioContext management, part 2
17
- Avoid recursive block_status call (i.e. lseek() calls) if possible
18
- linux-aio: Drop unused BlockAIOCB submission method
19
- nvme: add Get/Set Feature Timestamp support
20
- Fix crash on commit job start with active I/O on base node
21
- Fix crash in bdrv_drained_end
22
- Fix integer overflow in qcow2 discard
23
15
24
----------------------------------------------------------------
16
----------------------------------------------------------------
25
John Snow (1):
17
Eric Blake (1):
26
blockdev: fix missed target unref for drive-backup
18
iotests: Avoid realpath, for CentOS 6
27
19
28
Julia Suvorova (1):
20
Fam Zheng (4):
29
block/linux-aio: Drop unused BlockAIOCB submission method
21
block: Fix flags in reopen queue
22
iotests: Add regression test for commit base locking
23
vvfat: Fix inherit_options flags
24
block: Fix leak of ignore_children in error path
30
25
31
Kenneth Heitke (1):
26
Jeff Cody (1):
32
nvme: add Get/Set Feature Timestamp support
27
block: fix iotest 146 output expectations
33
28
34
Kevin Wolf (19):
29
John Snow (21):
35
block: Drain source node in bdrv_replace_node()
30
blockjobs: fix set-speed kick
36
iotests: Test commit job start with concurrent I/O
31
blockjobs: model single jobs as transactions
37
test-block-iothread: Check filter node in test_propagate_mirror
32
Blockjobs: documentation touchup
38
nbd-server: Call blk_set_allow_aio_context_change()
33
blockjobs: add status enum
39
block: Add Error to blk_set_aio_context()
34
blockjobs: add state transition table
40
block: Add BlockBackend.ctx
35
iotests: add pause_wait
41
block: Add qdev_prop_drive_iothread property type
36
blockjobs: add block_job_verb permission table
42
scsi-disk: Use qdev_prop_drive_iothread
37
blockjobs: add ABORTING state
43
block: Adjust AioContexts when attaching nodes
38
blockjobs: add CONCLUDED state
44
test-block-iothread: Test adding parent to iothread node
39
blockjobs: add NULL state
45
test-block-iothread: BlockBackend AioContext across root node change
40
blockjobs: add block_job_dismiss
46
block: Move node without parents to main AioContext
41
blockjobs: ensure abort is called for cancelled jobs
47
blockdev: Use bdrv_try_set_aio_context() for monitor commands
42
blockjobs: add commit, abort, clean helpers
48
block: Remove wrong bdrv_set_aio_context() calls
43
blockjobs: add block_job_txn_apply function
49
virtio-scsi-test: Test attaching new overlay with iothreads
44
blockjobs: add prepare callback
50
iotests: Attach new devices to node in non-default iothread
45
blockjobs: add waiting status
51
test-bdrv-drain: Use bdrv_try_set_aio_context()
46
blockjobs: add PENDING status and event
52
block: Remove bdrv_set_aio_context()
47
blockjobs: add block-job-finalize
53
iotests: Fix duplicated diff output on failure
48
blockjobs: Expose manual property
49
iotests: test manual job dismissal
50
tests/test-blockjob: test cancellations
54
51
55
Max Reitz (2):
52
Kevin Wolf (14):
56
block/io: Delay decrementing the quiesce_counter
53
luks: Separate image file creation from formatting
57
iotests: Test cancelling a job and closing the VM
54
luks: Create block_crypto_co_create_generic()
55
luks: Support .bdrv_co_create
56
luks: Turn invalid assertion into check
57
luks: Catch integer overflow for huge sizes
58
qemu-iotests: Test luks QMP image creation
59
parallels: Support .bdrv_co_create
60
qemu-iotests: Enable write tests for parallels
61
qcow: Support .bdrv_co_create
62
qed: Support .bdrv_co_create
63
vdi: Make comments consistent with other drivers
64
vhdx: Support .bdrv_co_create
65
vpc: Support .bdrv_co_create
66
vpc: Require aligned size in .bdrv_co_create
58
67
59
Vladimir Sementsov-Ogievskiy (4):
68
Liang Li (1):
60
tests/perf: Test lseek influence on qcow2 block-status
69
block/mirror: change the semantic of 'force' of block-job-cancel
61
block: avoid recursive block_status call if possible
62
block/qcow2-refcount: add trace-point to qcow2_process_discards
63
block/io: bdrv_pdiscard: support int64_t bytes parameter
64
70
65
docs/devel/multiple-iothreads.txt | 4 +-
71
Max Reitz (3):
66
block/qcow2.h | 4 +
72
vdi: Pull option parsing from vdi_co_create
67
hw/block/nvme.h | 2 +
73
vdi: Move file creation to vdi_co_create_opts
68
include/block/block.h | 21 ++---
74
vdi: Implement .bdrv_co_create
69
include/block/block_int.h | 1 +
70
include/block/nvme.h | 2 +
71
include/block/raw-aio.h | 3 -
72
include/hw/block/block.h | 7 +-
73
include/hw/qdev-properties.h | 3 +
74
include/hw/scsi/scsi.h | 1 +
75
include/sysemu/block-backend.h | 5 +-
76
tests/libqtest.h | 11 +++
77
block.c | 79 ++++++++++++-----
78
block/backup.c | 3 +-
79
block/block-backend.c | 47 ++++++----
80
block/commit.c | 13 +--
81
block/crypto.c | 3 +-
82
block/io.c | 28 +++---
83
block/linux-aio.c | 72 +++------------
84
block/mirror.c | 4 +-
85
block/parallels.c | 3 +-
86
block/qcow.c | 3 +-
87
block/qcow2-refcount.c | 39 ++++++++-
88
block/qcow2.c | 17 +++-
89
block/qed.c | 3 +-
90
block/sheepdog.c | 3 +-
91
block/vdi.c | 3 +-
92
block/vhdx.c | 3 +-
93
block/vmdk.c | 3 +-
94
block/vpc.c | 3 +-
95
blockdev.c | 61 +++++++------
96
blockjob.c | 12 ++-
97
hmp.c | 3 +-
98
hw/block/dataplane/virtio-blk.c | 12 ++-
99
hw/block/dataplane/xen-block.c | 6 +-
100
hw/block/fdc.c | 2 +-
101
hw/block/nvme.c | 106 +++++++++++++++++++++-
102
hw/block/xen-block.c | 2 +-
103
hw/core/qdev-properties-system.c | 41 ++++++++-
104
hw/ide/qdev.c | 2 +-
105
hw/scsi/scsi-disk.c | 24 +++--
106
hw/scsi/virtio-scsi.c | 25 +++---
107
migration/block.c | 3 +-
108
nbd/server.c | 6 +-
109
qemu-img.c | 6 +-
110
tests/libqtest.c | 19 ++++
111
tests/test-bdrv-drain.c | 50 ++++++-----
112
tests/test-bdrv-graph-mod.c | 5 +-
113
tests/test-block-backend.c | 6 +-
114
tests/test-block-iothread.c | 104 ++++++++++++++++++----
115
tests/test-blockjob.c | 2 +-
116
tests/test-throttle.c | 6 +-
117
tests/virtio-scsi-test.c | 62 +++++++++++++
118
block/trace-events | 3 +
119
hw/block/trace-events | 2 +
120
tests/perf/block/qcow2/convert-blockstatus | 71 +++++++++++++++
121
tests/qemu-iotests/051 | 24 +++++
122
tests/qemu-iotests/051.out | 3 +
123
tests/qemu-iotests/051.pc.out | 27 ++++++
124
tests/qemu-iotests/102 | 2 +-
125
tests/qemu-iotests/102.out | 3 +-
126
tests/qemu-iotests/141.out | 2 +-
127
tests/qemu-iotests/144.out | 2 +-
128
tests/qemu-iotests/240 | 21 +++++
129
tests/qemu-iotests/240.out | 15 +++-
130
tests/qemu-iotests/255 | 135 +++++++++++++++++++++++++++++
131
tests/qemu-iotests/255.out | 40 +++++++++
132
tests/qemu-iotests/check | 1 -
133
tests/qemu-iotests/group | 1 +
134
tests/qemu-iotests/iotests.py | 10 ++-
135
70 files changed, 1048 insertions(+), 272 deletions(-)
136
create mode 100755 tests/perf/block/qcow2/convert-blockstatus
137
create mode 100755 tests/qemu-iotests/255
138
create mode 100644 tests/qemu-iotests/255.out
139
75
76
Paolo Bonzini (1):
77
iscsi: fix iSER compilation
78
79
qapi/block-core.json | 363 ++++++++++++++++++++++++++++++++++++++++--
80
include/block/blockjob.h | 71 ++++++++-
81
include/block/blockjob_int.h | 17 +-
82
block.c | 10 +-
83
block/backup.c | 5 +-
84
block/commit.c | 2 +-
85
block/crypto.c | 150 ++++++++++++-----
86
block/iscsi.c | 2 +-
87
block/mirror.c | 12 +-
88
block/parallels.c | 199 +++++++++++++++++------
89
block/qcow.c | 196 +++++++++++++++--------
90
block/qed.c | 204 ++++++++++++++++--------
91
block/stream.c | 2 +-
92
block/vdi.c | 147 +++++++++++++----
93
block/vhdx.c | 216 +++++++++++++++++++------
94
block/vpc.c | 241 +++++++++++++++++++++-------
95
block/vvfat.c | 2 +-
96
blockdev.c | 71 +++++++--
97
blockjob.c | 358 +++++++++++++++++++++++++++++++++++------
98
tests/test-bdrv-drain.c | 5 +-
99
tests/test-blockjob-txn.c | 27 ++--
100
tests/test-blockjob.c | 233 ++++++++++++++++++++++++++-
101
block/trace-events | 7 +
102
hmp-commands.hx | 3 +-
103
tests/qemu-iotests/030 | 6 +-
104
tests/qemu-iotests/055 | 17 +-
105
tests/qemu-iotests/056 | 187 ++++++++++++++++++++++
106
tests/qemu-iotests/056.out | 4 +-
107
tests/qemu-iotests/109.out | 24 +--
108
tests/qemu-iotests/146.out | 2 +-
109
tests/qemu-iotests/153 | 12 ++
110
tests/qemu-iotests/153.out | 5 +
111
tests/qemu-iotests/181 | 2 +-
112
tests/qemu-iotests/210 | 210 ++++++++++++++++++++++++
113
tests/qemu-iotests/210.out | 136 ++++++++++++++++
114
tests/qemu-iotests/check | 13 +-
115
tests/qemu-iotests/common.rc | 2 +-
116
tests/qemu-iotests/group | 1 +
117
tests/qemu-iotests/iotests.py | 12 +-
118
39 files changed, 2652 insertions(+), 524 deletions(-)
119
create mode 100755 tests/qemu-iotests/210
120
create mode 100644 tests/qemu-iotests/210.out
121
diff view generated by jsdifflib
Deleted patch
1
Instead of just asserting that no requests are in flight in
2
bdrv_replace_node(), which is a requirement that most callers ignore, we
3
can just drain the source node right there. This fixes at least starting
4
a commit job while I/O is active on the backing chain, but probably
5
other callers, too.
6
1
7
Having requests in flight on the target node isn't a problem because the
8
target just gets new parents, but the call path of running requests
9
isn't modified. So we can just drop this assertion without a replacement.
10
11
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1711643
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Reviewed-by: Max Reitz <mreitz@redhat.com>
14
---
15
block.c | 7 ++++---
16
1 file changed, 4 insertions(+), 3 deletions(-)
17
18
diff --git a/block.c b/block.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block.c
21
+++ b/block.c
22
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
23
uint64_t perm = 0, shared = BLK_PERM_ALL;
24
int ret;
25
26
- assert(!atomic_read(&from->in_flight));
27
- assert(!atomic_read(&to->in_flight));
28
-
29
/* Make sure that @from doesn't go away until we have successfully attached
30
* all of its parents to @to. */
31
bdrv_ref(from);
32
33
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
34
+ bdrv_drained_begin(from);
35
+
36
/* Put all parents into @list and calculate their cumulative permissions */
37
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
38
assert(c->bs == from);
39
@@ -XXX,XX +XXX,XX @@ void bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
40
41
out:
42
g_slist_free(list);
43
+ bdrv_drained_end(from);
44
bdrv_unref(from);
45
}
46
47
--
48
2.20.1
49
50
diff view generated by jsdifflib
Deleted patch
1
This tests that concurrent requests are correctly drained before making
2
graph modifications instead of running into assertions in
3
bdrv_replace_node().
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
---
8
tests/qemu-iotests/255 | 83 +++++++++++++++++++++++++++++++++++
9
tests/qemu-iotests/255.out | 16 +++++++
10
tests/qemu-iotests/group | 1 +
11
tests/qemu-iotests/iotests.py | 10 ++++-
12
4 files changed, 109 insertions(+), 1 deletion(-)
13
create mode 100755 tests/qemu-iotests/255
14
create mode 100644 tests/qemu-iotests/255.out
15
16
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
17
new file mode 100755
18
index XXXXXXX..XXXXXXX
19
--- /dev/null
20
+++ b/tests/qemu-iotests/255
21
@@ -XXX,XX +XXX,XX @@
22
+#!/usr/bin/env python
23
+#
24
+# Test commit job graph modifications while requests are active
25
+#
26
+# Copyright (C) 2019 Red Hat, Inc.
27
+#
28
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
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
+import iotests
45
+from iotests import imgfmt
46
+
47
+iotests.verify_image_format(supported_fmts=['qcow2'])
48
+
49
+def blockdev_create(vm, options):
50
+ result = vm.qmp_log('blockdev-create',
51
+ filters=[iotests.filter_qmp_testfiles],
52
+ job_id='job0', options=options)
53
+
54
+ if 'return' in result:
55
+ assert result['return'] == {}
56
+ vm.run_job('job0')
57
+ iotests.log("")
58
+
59
+with iotests.FilePath('t.qcow2') as disk_path, \
60
+ iotests.FilePath('t.qcow2.mid') as mid_path, \
61
+ iotests.FilePath('t.qcow2.base') as base_path, \
62
+ iotests.VM() as vm:
63
+
64
+ iotests.log("=== Create backing chain and start VM ===")
65
+ iotests.log("")
66
+
67
+ size = 128 * 1024 * 1024
68
+ size_str = str(size)
69
+
70
+ iotests.create_image(base_path, size)
71
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, mid_path, size_str)
72
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, disk_path, size_str)
73
+
74
+ # Create a backing chain like this:
75
+ # base <- [throttled: bps-read=4096] <- mid <- overlay
76
+
77
+ vm.add_object('throttle-group,x-bps-read=4096,id=throttle0')
78
+ vm.add_blockdev('file,filename=%s,node-name=base' % (base_path))
79
+ vm.add_blockdev('throttle,throttle-group=throttle0,file=base,node-name=throttled')
80
+ vm.add_blockdev('file,filename=%s,node-name=mid-file' % (mid_path))
81
+ vm.add_blockdev('qcow2,file=mid-file,node-name=mid,backing=throttled')
82
+ vm.add_drive_raw('if=none,id=overlay,driver=qcow2,file=%s,backing=mid' % (disk_path))
83
+
84
+ vm.launch()
85
+
86
+ iotests.log("=== Start background read requests ===")
87
+ iotests.log("")
88
+
89
+ def start_requests():
90
+ vm.hmp_qemu_io('overlay', 'aio_read 0 4k')
91
+ vm.hmp_qemu_io('overlay', 'aio_read 0 4k')
92
+
93
+ start_requests()
94
+
95
+ iotests.log("=== Run a commit job ===")
96
+ iotests.log("")
97
+
98
+ result = vm.qmp_log('block-commit', job_id='job0', auto_finalize=False,
99
+ device='overlay', top_node='mid')
100
+
101
+ vm.run_job('job0', auto_finalize=False, pre_finalize=start_requests,
102
+ auto_dismiss=True)
103
+
104
+ vm.shutdown()
105
diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/tests/qemu-iotests/255.out
110
@@ -XXX,XX +XXX,XX @@
111
+=== Create backing chain and start VM ===
112
+
113
+Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
114
+
115
+Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
116
+
117
+=== Start background read requests ===
118
+
119
+=== Run a commit job ===
120
+
121
+{"execute": "block-commit", "arguments": {"auto-finalize": false, "device": "overlay", "job-id": "job0", "top-node": "mid"}}
122
+{"return": {}}
123
+{"execute": "job-finalize", "arguments": {"id": "job0"}}
124
+{"return": {}}
125
+{"data": {"id": "job0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
126
+{"data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
127
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
128
index XXXXXXX..XXXXXXX 100644
129
--- a/tests/qemu-iotests/group
130
+++ b/tests/qemu-iotests/group
131
@@ -XXX,XX +XXX,XX @@
132
252 rw auto backing quick
133
253 rw auto quick
134
254 rw auto backing quick
135
+255 rw auto quick
136
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
137
index XXXXXXX..XXXXXXX 100644
138
--- a/tests/qemu-iotests/iotests.py
139
+++ b/tests/qemu-iotests/iotests.py
140
@@ -XXX,XX +XXX,XX @@ def qemu_img_pipe(*args):
141
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
142
return subp.communicate()[0]
143
144
+def qemu_img_log(*args):
145
+ result = qemu_img_pipe(*args)
146
+ log(result, filters=[filter_testfiles])
147
+ return result
148
+
149
def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
150
args = [ 'info' ]
151
if imgopts:
152
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
153
return result
154
155
# Returns None on success, and an error string on failure
156
- def run_job(self, job, auto_finalize=True, auto_dismiss=False):
157
+ def run_job(self, job, auto_finalize=True, auto_dismiss=False,
158
+ pre_finalize=None):
159
error = None
160
while True:
161
for ev in self.get_qmp_events_filtered(wait=True):
162
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
163
error = j['error']
164
log('Job failed: %s' % (j['error']))
165
elif status == 'pending' and not auto_finalize:
166
+ if pre_finalize:
167
+ pre_finalize()
168
self.qmp_log('job-finalize', id=job)
169
elif status == 'concluded' and not auto_dismiss:
170
self.qmp_log('job-dismiss', id=job)
171
--
172
2.20.1
173
174
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
If the bitmap can't be used for whatever reason, we skip putting down
4
the reference. Fix that.
5
6
In practice, this means that if you attempt to gracefully exit QEMU
7
after a backup command being rejected, bdrv_close_all will fail and
8
tell you some unpleasant things via assert().
9
10
Reported-by: aihua liang <aliang@redhat.com>
11
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1703916
12
Signed-off-by: John Snow <jsnow@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
blockdev.c | 13 ++++++-------
17
1 file changed, 6 insertions(+), 7 deletions(-)
18
19
diff --git a/blockdev.c b/blockdev.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/blockdev.c
22
+++ b/blockdev.c
23
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
24
if (set_backing_hd) {
25
bdrv_set_backing_hd(target_bs, source, &local_err);
26
if (local_err) {
27
- bdrv_unref(target_bs);
28
- goto out;
29
+ goto unref;
30
}
31
}
32
33
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
34
bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
35
if (!bmap) {
36
error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
37
- bdrv_unref(target_bs);
38
- goto out;
39
+ goto unref;
40
}
41
if (bdrv_dirty_bitmap_check(bmap, BDRV_BITMAP_DEFAULT, errp)) {
42
- goto out;
43
+ goto unref;
44
}
45
}
46
if (!backup->auto_finalize) {
47
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
48
backup->sync, bmap, backup->compress,
49
backup->on_source_error, backup->on_target_error,
50
job_flags, NULL, NULL, txn, &local_err);
51
- bdrv_unref(target_bs);
52
if (local_err != NULL) {
53
error_propagate(errp, local_err);
54
- goto out;
55
+ goto unref;
56
}
57
58
+unref:
59
+ bdrv_unref(target_bs);
60
out:
61
aio_context_release(aio_context);
62
return job;
63
--
64
2.20.1
65
66
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Block layer may recursively check block_status in file child of qcow2,
4
if qcow2 driver returned DATA. There are several test cases to check
5
influence of lseek on block_status performance. To see real difference
6
run on tmpfs.
7
8
Tests originally created by Kevin, I just refactored and put them
9
together into one executable file with simple output.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
tests/perf/block/qcow2/convert-blockstatus | 71 ++++++++++++++++++++++
15
1 file changed, 71 insertions(+)
16
create mode 100755 tests/perf/block/qcow2/convert-blockstatus
17
18
diff --git a/tests/perf/block/qcow2/convert-blockstatus b/tests/perf/block/qcow2/convert-blockstatus
19
new file mode 100755
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/perf/block/qcow2/convert-blockstatus
23
@@ -XXX,XX +XXX,XX @@
24
+#!/bin/bash
25
+#
26
+# Test lseek influence on qcow2 block-status
27
+#
28
+# Block layer may recursively check block_status in file child of qcow2, if
29
+# qcow2 driver returned DATA. There are several test cases to check influence
30
+# of lseek on block_status performance. To see real difference run on tmpfs.
31
+#
32
+# Copyright (c) 2019 Virtuozzo International GmbH. All rights reserved.
33
+#
34
+# Tests originally written by Kevin Wolf
35
+#
36
+# This program is free software; you can redistribute it and/or modify
37
+# it under the terms of the GNU General Public License as published by
38
+# the Free Software Foundation; either version 2 of the License, or
39
+# (at your option) any later version.
40
+#
41
+# This program is distributed in the hope that it will be useful,
42
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+# GNU General Public License for more details.
45
+#
46
+# You should have received a copy of the GNU General Public License
47
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
48
+#
49
+
50
+if [ "$#" -lt 1 ]; then
51
+ echo "Usage: $0 SOURCE_FILE"
52
+ exit 1
53
+fi
54
+
55
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../../../.." >/dev/null 2>&1 && pwd )"
56
+QEMU_IMG="$ROOT_DIR/qemu-img"
57
+QEMU_IO="$ROOT_DIR/qemu-io"
58
+
59
+size=1G
60
+src="$1"
61
+
62
+# test-case plain
63
+
64
+(
65
+$QEMU_IMG create -f qcow2 "$src" $size
66
+for i in $(seq 16384 -1 0); do
67
+ echo "write $((i * 65536)) 64k"
68
+done | $QEMU_IO "$src"
69
+) > /dev/null
70
+
71
+echo -n "plain: "
72
+/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co://
73
+
74
+# test-case forward
75
+
76
+(
77
+$QEMU_IMG create -f qcow2 "$src" $size
78
+for i in $(seq 0 2 16384); do
79
+ echo "write $((i * 65536)) 64k"
80
+done | $QEMU_IO "$src"
81
+for i in $(seq 1 2 16384); do
82
+ echo "write $((i * 65536)) 64k"
83
+done | $QEMU_IO "$src"
84
+) > /dev/null
85
+
86
+echo -n "forward: "
87
+/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co://
88
+
89
+# test-case prealloc
90
+
91
+$QEMU_IMG create -f qcow2 -o preallocation=metadata "$src" $size > /dev/null
92
+
93
+echo -n "prealloc: "
94
+/usr/bin/time -f %e $QEMU_IMG convert -n "$src" null-co://
95
--
96
2.20.1
97
98
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
drv_co_block_status digs bs->file for additional, more accurate search
4
for hole inside region, reported as DATA by bs since 5daa74a6ebc.
5
6
This accuracy is not free: assume we have qcow2 disk. Actually, qcow2
7
knows, where are holes and where is data. But every block_status
8
request calls lseek additionally. Assume a big disk, full of
9
data, in any iterative copying block job (or img convert) we'll call
10
lseek(HOLE) on every iteration, and each of these lseeks will have to
11
iterate through all metadata up to the end of file. It's obviously
12
ineffective behavior. And for many scenarios we don't need this lseek
13
at all.
14
15
However, lseek is needed when we have metadata-preallocated image.
16
17
So, let's detect metadata-preallocation case and don't dig qcow2's
18
protocol file in other cases.
19
20
The idea is to compare allocation size in POV of filesystem with
21
allocations size in POV of Qcow2 (by refcounts). If allocation in fs is
22
significantly lower, consider it as metadata-preallocation case.
23
24
102 iotest changed, as our detector can't detect shrinked file as
25
metadata-preallocation, which don't seem to be wrong, as with metadata
26
preallocation we always have valid file length.
27
28
Two other iotests have a slight change in their QMP output sequence:
29
Active 'block-commit' returns earlier because the job coroutine yields
30
earlier on a blocking operation. This operation is loading the refcount
31
blocks in qcow2_detect_metadata_preallocation().
32
33
Suggested-by: Denis V. Lunev <den@openvz.org>
34
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
35
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
36
---
37
block/qcow2.h | 4 ++++
38
include/block/block.h | 8 +++++++-
39
block/io.c | 9 ++++++++-
40
block/qcow2-refcount.c | 32 ++++++++++++++++++++++++++++++++
41
block/qcow2.c | 11 +++++++++++
42
tests/qemu-iotests/102 | 2 +-
43
tests/qemu-iotests/102.out | 3 ++-
44
tests/qemu-iotests/141.out | 2 +-
45
tests/qemu-iotests/144.out | 2 +-
46
9 files changed, 67 insertions(+), 6 deletions(-)
47
48
diff --git a/block/qcow2.h b/block/qcow2.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/qcow2.h
51
+++ b/block/qcow2.h
52
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
53
int nb_threads;
54
55
BdrvChild *data_file;
56
+
57
+ bool metadata_preallocation_checked;
58
+ bool metadata_preallocation;
59
} BDRVQcow2State;
60
61
typedef struct Qcow2COWRegion {
62
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
63
void *cb_opaque, Error **errp);
64
int qcow2_shrink_reftable(BlockDriverState *bs);
65
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
66
+int qcow2_detect_metadata_preallocation(BlockDriverState *bs);
67
68
/* qcow2-cluster.c functions */
69
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
70
diff --git a/include/block/block.h b/include/block/block.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/block/block.h
73
+++ b/include/block/block.h
74
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
75
* BDRV_BLOCK_EOF: the returned pnum covers through end of file for this
76
* layer, set by block layer
77
*
78
- * Internal flag:
79
+ * Internal flags:
80
* BDRV_BLOCK_RAW: for use by passthrough drivers, such as raw, to request
81
* that the block layer recompute the answer from the returned
82
* BDS; must be accompanied by just BDRV_BLOCK_OFFSET_VALID.
83
+ * BDRV_BLOCK_RECURSE: request that the block layer will recursively search for
84
+ * zeroes in file child of current block node inside
85
+ * returned region. Only valid together with both
86
+ * BDRV_BLOCK_DATA and BDRV_BLOCK_OFFSET_VALID. Should not
87
+ * appear with BDRV_BLOCK_ZERO.
88
*
89
* If BDRV_BLOCK_OFFSET_VALID is set, the map parameter represents the
90
* host offset within the returned BDS that is allocated for the
91
@@ -XXX,XX +XXX,XX @@ typedef struct HDGeometry {
92
#define BDRV_BLOCK_RAW 0x08
93
#define BDRV_BLOCK_ALLOCATED 0x10
94
#define BDRV_BLOCK_EOF 0x20
95
+#define BDRV_BLOCK_RECURSE 0x40
96
#define BDRV_BLOCK_OFFSET_MASK BDRV_SECTOR_MASK
97
98
typedef QSIMPLEQ_HEAD(BlockReopenQueue, BlockReopenQueueEntry) BlockReopenQueue;
99
diff --git a/block/io.c b/block/io.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/io.c
102
+++ b/block/io.c
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
104
*/
105
assert(*pnum && QEMU_IS_ALIGNED(*pnum, align) &&
106
align > offset - aligned_offset);
107
+ if (ret & BDRV_BLOCK_RECURSE) {
108
+ assert(ret & BDRV_BLOCK_DATA);
109
+ assert(ret & BDRV_BLOCK_OFFSET_VALID);
110
+ assert(!(ret & BDRV_BLOCK_ZERO));
111
+ }
112
+
113
*pnum -= offset - aligned_offset;
114
if (*pnum > bytes) {
115
*pnum = bytes;
116
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_co_block_status(BlockDriverState *bs,
117
}
118
}
119
120
- if (want_zero && local_file && local_file != bs &&
121
+ if (want_zero && ret & BDRV_BLOCK_RECURSE &&
122
+ local_file && local_file != bs &&
123
(ret & BDRV_BLOCK_DATA) && !(ret & BDRV_BLOCK_ZERO) &&
124
(ret & BDRV_BLOCK_OFFSET_VALID)) {
125
int64_t file_pnum;
126
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/block/qcow2-refcount.c
129
+++ b/block/qcow2-refcount.c
130
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size)
131
"There are no references in the refcount table.");
132
return -EIO;
133
}
134
+
135
+int qcow2_detect_metadata_preallocation(BlockDriverState *bs)
136
+{
137
+ BDRVQcow2State *s = bs->opaque;
138
+ int64_t i, end_cluster, cluster_count = 0, threshold;
139
+ int64_t file_length, real_allocation, real_clusters;
140
+
141
+ file_length = bdrv_getlength(bs->file->bs);
142
+ if (file_length < 0) {
143
+ return file_length;
144
+ }
145
+
146
+ real_allocation = bdrv_get_allocated_file_size(bs->file->bs);
147
+ if (real_allocation < 0) {
148
+ return real_allocation;
149
+ }
150
+
151
+ real_clusters = real_allocation / s->cluster_size;
152
+ threshold = MAX(real_clusters * 10 / 9, real_clusters + 2);
153
+
154
+ end_cluster = size_to_clusters(s, file_length);
155
+ for (i = 0; i < end_cluster && cluster_count < threshold; i++) {
156
+ uint64_t refcount;
157
+ int ret = qcow2_get_refcount(bs, i, &refcount);
158
+ if (ret < 0) {
159
+ return ret;
160
+ }
161
+ cluster_count += !!refcount;
162
+ }
163
+
164
+ return cluster_count >= threshold;
165
+}
166
diff --git a/block/qcow2.c b/block/qcow2.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/block/qcow2.c
169
+++ b/block/qcow2.c
170
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
171
unsigned int bytes;
172
int status = 0;
173
174
+ if (!s->metadata_preallocation_checked) {
175
+ ret = qcow2_detect_metadata_preallocation(bs);
176
+ s->metadata_preallocation = (ret == 1);
177
+ s->metadata_preallocation_checked = true;
178
+ }
179
+
180
bytes = MIN(INT_MAX, count);
181
qemu_co_mutex_lock(&s->lock);
182
ret = qcow2_get_cluster_offset(bs, offset, &bytes, &cluster_offset);
183
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
184
} else if (ret != QCOW2_CLUSTER_UNALLOCATED) {
185
status |= BDRV_BLOCK_DATA;
186
}
187
+ if (s->metadata_preallocation && (status & BDRV_BLOCK_DATA) &&
188
+ (status & BDRV_BLOCK_OFFSET_VALID))
189
+ {
190
+ status |= BDRV_BLOCK_RECURSE;
191
+ }
192
return status;
193
}
194
195
diff --git a/tests/qemu-iotests/102 b/tests/qemu-iotests/102
196
index XXXXXXX..XXXXXXX 100755
197
--- a/tests/qemu-iotests/102
198
+++ b/tests/qemu-iotests/102
199
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
200
$QEMU_IMG resize -f raw --shrink "$TEST_IMG" $((5 * 64 * 1024))
201
202
$QEMU_IO -c map "$TEST_IMG"
203
-$QEMU_IMG map "$TEST_IMG"
204
+$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map
205
206
echo
207
echo '=== Testing map on an image file truncated outside of qemu ==='
208
diff --git a/tests/qemu-iotests/102.out b/tests/qemu-iotests/102.out
209
index XXXXXXX..XXXXXXX 100644
210
--- a/tests/qemu-iotests/102.out
211
+++ b/tests/qemu-iotests/102.out
212
@@ -XXX,XX +XXX,XX @@ wrote 65536/65536 bytes at offset 0
213
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
214
Image resized.
215
64 KiB (0x10000) bytes allocated at offset 0 bytes (0x0)
216
-Offset Length Mapped to File
217
+Offset Length File
218
+0 0x10000 TEST_DIR/t.IMGFMT
219
220
=== Testing map on an image file truncated outside of qemu ===
221
222
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
223
index XXXXXXX..XXXXXXX 100644
224
--- a/tests/qemu-iotests/141.out
225
+++ b/tests/qemu-iotests/141.out
226
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.
227
{"return": {}}
228
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
229
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
230
+{"return": {}}
231
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
232
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
233
-{"return": {}}
234
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
235
{"return": {}}
236
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
237
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
238
index XXXXXXX..XXXXXXX 100644
239
--- a/tests/qemu-iotests/144.out
240
+++ b/tests/qemu-iotests/144.out
241
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/
242
243
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
244
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
245
+{"return": {}}
246
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
247
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
248
{"return": {}}
249
-{"return": {}}
250
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}}
251
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}}
252
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
253
--
254
2.20.1
255
256
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
When ending a drained section, bdrv_do_drained_end() currently first
4
decrements the quiesce_counter, and only then actually ends the drain.
5
6
The bdrv_drain_invoke(bs, false) call may cause graph changes. Say the
7
graph change involves replacing an existing BB's ("blk") BDS
8
(blk_bs(blk)) by @bs. Let us introducing the following values:
9
- bs_oqc = old_quiesce_counter
10
(so bs->quiesce_counter == bs_oqc - 1)
11
- obs_qc = blk_bs(blk)->quiesce_counter (before bdrv_drain_invoke())
12
13
Let us assume there is no blk_pread_unthrottled() involved, so
14
blk->quiesce_counter == obs_qc (before bdrv_drain_invoke()).
15
16
Now replacing blk_bs(blk) by @bs will reduce blk->quiesce_counter by
17
obs_qc (making it 0) and increase it by bs_oqc-1 (making it bs_oqc-1).
18
19
bdrv_drain_invoke() returns and we invoke bdrv_parent_drained_end().
20
This will decrement blk->quiesce_counter by one, so it would be -1 --
21
were there not an assertion against that in blk_root_drained_end().
22
23
We therefore have to keep the quiesce_counter up at least until
24
bdrv_drain_invoke() returns, so that bdrv_parent_drained_end() does the
25
right thing for the parents @bs got during bdrv_drain_invoke().
26
27
But let us delay it even further, namely until bdrv_parent_drained_end()
28
returns, because then it mirrors bdrv_do_drained_begin(): There, we
29
first increment the quiesce_counter, then begin draining the parents,
30
and then call bdrv_drain_invoke(). It makes sense to let
31
bdrv_do_drained_end() unravel this exactly in reverse.
32
33
Signed-off-by: Max Reitz <mreitz@redhat.com>
34
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
35
---
36
block/io.c | 3 ++-
37
1 file changed, 2 insertions(+), 1 deletion(-)
38
39
diff --git a/block/io.c b/block/io.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/io.c
42
+++ b/block/io.c
43
@@ -XXX,XX +XXX,XX @@ static void bdrv_do_drained_end(BlockDriverState *bs, bool recursive,
44
return;
45
}
46
assert(bs->quiesce_counter > 0);
47
- old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
48
49
/* Re-enable things in child-to-parent order */
50
bdrv_drain_invoke(bs, false);
51
bdrv_parent_drained_end(bs, parent, ignore_bds_parents);
52
+
53
+ old_quiesce_counter = atomic_fetch_dec(&bs->quiesce_counter);
54
if (old_quiesce_counter == 1) {
55
aio_enable_external(bdrv_get_aio_context(bs));
56
}
57
--
58
2.20.1
59
60
diff view generated by jsdifflib
Deleted patch
1
From: Max Reitz <mreitz@redhat.com>
2
1
3
This patch adds a test where we cancel a throttled mirror job and
4
immediately close the VM before it can be cancelled. Doing so will
5
invoke bdrv_drain_all() while the mirror job tries to drain the
6
throttled node. When bdrv_drain_all_end() tries to lift its drain on
7
the throttle node, the job will exit and replace the current root node
8
of the BB drive0 (which is the job's filter node) by the throttle node.
9
Before the previous patch, this replacement did not increase drive0's
10
quiesce_counter by a sufficient amount, so when
11
bdrv_parent_drained_end() (invoked by bdrv_do_drained_end(), invoked by
12
bdrv_drain_all_end()) tried to end the drain on all of the throttle
13
node's parents, it decreased drive0's quiesce_counter below 0 -- which
14
fails an assertion.
15
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
tests/qemu-iotests/255 | 52 ++++++++++++++++++++++++++++++++++++++
20
tests/qemu-iotests/255.out | 24 ++++++++++++++++++
21
2 files changed, 76 insertions(+)
22
23
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
24
index XXXXXXX..XXXXXXX 100755
25
--- a/tests/qemu-iotests/255
26
+++ b/tests/qemu-iotests/255
27
@@ -XXX,XX +XXX,XX @@ def blockdev_create(vm, options):
28
vm.run_job('job0')
29
iotests.log("")
30
31
+iotests.log('Finishing a commit job with background reads')
32
+iotests.log('============================================')
33
+iotests.log('')
34
+
35
with iotests.FilePath('t.qcow2') as disk_path, \
36
iotests.FilePath('t.qcow2.mid') as mid_path, \
37
iotests.FilePath('t.qcow2.base') as base_path, \
38
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('t.qcow2') as disk_path, \
39
auto_dismiss=True)
40
41
vm.shutdown()
42
+
43
+iotests.log('')
44
+iotests.log('Closing the VM while a job is being cancelled')
45
+iotests.log('=============================================')
46
+iotests.log('')
47
+
48
+with iotests.FilePath('src.qcow2') as src_path, \
49
+ iotests.FilePath('dst.qcow2') as dst_path, \
50
+ iotests.VM() as vm:
51
+
52
+ iotests.log('=== Create images and start VM ===')
53
+ iotests.log('')
54
+
55
+ size = 128 * 1024 * 1024
56
+ size_str = str(size)
57
+
58
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, src_path, size_str)
59
+ iotests.qemu_img_log('create', '-f', iotests.imgfmt, dst_path, size_str)
60
+
61
+ iotests.log(iotests.qemu_io('-f', iotests.imgfmt, '-c', 'write 0 1M',
62
+ src_path),
63
+ filters=[iotests.filter_test_dir, iotests.filter_qemu_io])
64
+
65
+ vm.add_object('throttle-group,x-bps-read=4096,id=throttle0')
66
+
67
+ vm.add_blockdev('file,node-name=src-file,filename=%s' % (src_path))
68
+ vm.add_blockdev('%s,node-name=src,file=src-file' % (iotests.imgfmt))
69
+
70
+ vm.add_blockdev('file,node-name=dst-file,filename=%s' % (dst_path))
71
+ vm.add_blockdev('%s,node-name=dst,file=dst-file' % (iotests.imgfmt))
72
+
73
+ vm.add_blockdev('throttle,node-name=src-throttled,' +
74
+ 'throttle-group=throttle0,file=src')
75
+
76
+ vm.add_device('virtio-blk,drive=src-throttled')
77
+
78
+ vm.launch()
79
+
80
+ iotests.log('=== Start a mirror job ===')
81
+ iotests.log('')
82
+
83
+ vm.qmp_log('blockdev-mirror', job_id='job0', device='src-throttled',
84
+ target='dst', sync='full')
85
+
86
+ vm.qmp_log('block-job-cancel', device='job0')
87
+ vm.qmp_log('quit')
88
+
89
+ vm.shutdown()
90
diff --git a/tests/qemu-iotests/255.out b/tests/qemu-iotests/255.out
91
index XXXXXXX..XXXXXXX 100644
92
--- a/tests/qemu-iotests/255.out
93
+++ b/tests/qemu-iotests/255.out
94
@@ -XXX,XX +XXX,XX @@
95
+Finishing a commit job with background reads
96
+============================================
97
+
98
=== Create backing chain and start VM ===
99
100
Formatting 'TEST_DIR/PID-t.qcow2.mid', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
101
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/PID-t.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 l
102
{"return": {}}
103
{"data": {"id": "job0", "type": "commit"}, "event": "BLOCK_JOB_PENDING", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
104
{"data": {"device": "job0", "len": 134217728, "offset": 134217728, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
105
+
106
+Closing the VM while a job is being cancelled
107
+=============================================
108
+
109
+=== Create images and start VM ===
110
+
111
+Formatting 'TEST_DIR/PID-src.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
112
+
113
+Formatting 'TEST_DIR/PID-dst.qcow2', fmt=qcow2 size=134217728 cluster_size=65536 lazy_refcounts=off refcount_bits=16
114
+
115
+wrote 1048576/1048576 bytes at offset 0
116
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
117
+
118
+=== Start a mirror job ===
119
+
120
+{"execute": "blockdev-mirror", "arguments": {"device": "src-throttled", "job-id": "job0", "sync": "full", "target": "dst"}}
121
+{"return": {}}
122
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
123
+{"return": {}}
124
+{"execute": "quit", "arguments": {}}
125
+{"return": {}}
126
--
127
2.20.1
128
129
diff view generated by jsdifflib
Deleted patch
1
From: Julia Suvorova <jusual@mail.ru>
2
1
3
Callback-based laio_submit() and laio_cancel() were left after
4
rewriting Linux AIO backend to coroutines in hope that they would be
5
used in other code that could bypass coroutines. They can be safely
6
removed because they have not been used since that time.
7
8
Signed-off-by: Julia Suvorova <jusual@mail.ru>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/raw-aio.h | 3 --
13
block/linux-aio.c | 72 ++++++-----------------------------------
14
2 files changed, 10 insertions(+), 65 deletions(-)
15
16
diff --git a/include/block/raw-aio.h b/include/block/raw-aio.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/raw-aio.h
19
+++ b/include/block/raw-aio.h
20
@@ -XXX,XX +XXX,XX @@ LinuxAioState *laio_init(Error **errp);
21
void laio_cleanup(LinuxAioState *s);
22
int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
23
uint64_t offset, QEMUIOVector *qiov, int type);
24
-BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
25
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
26
- BlockCompletionFunc *cb, void *opaque, int type);
27
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context);
28
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context);
29
void laio_io_plug(BlockDriverState *bs, LinuxAioState *s);
30
diff --git a/block/linux-aio.c b/block/linux-aio.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/linux-aio.c
33
+++ b/block/linux-aio.c
34
@@ -XXX,XX +XXX,XX @@
35
#define MAX_EVENTS 128
36
37
struct qemu_laiocb {
38
- BlockAIOCB common;
39
Coroutine *co;
40
LinuxAioState *ctx;
41
struct iocb iocb;
42
@@ -XXX,XX +XXX,XX @@ static inline ssize_t io_event_ret(struct io_event *ev)
43
}
44
45
/*
46
- * Completes an AIO request (calls the callback and frees the ACB).
47
+ * Completes an AIO request.
48
*/
49
static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
50
{
51
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
52
}
53
54
laiocb->ret = ret;
55
- if (laiocb->co) {
56
- /* If the coroutine is already entered it must be in ioq_submit() and
57
- * will notice laio->ret has been filled in when it eventually runs
58
- * later. Coroutines cannot be entered recursively so avoid doing
59
- * that!
60
- */
61
- if (!qemu_coroutine_entered(laiocb->co)) {
62
- aio_co_wake(laiocb->co);
63
- }
64
- } else {
65
- laiocb->common.cb(laiocb->common.opaque, ret);
66
- qemu_aio_unref(laiocb);
67
+
68
+ /*
69
+ * If the coroutine is already entered it must be in ioq_submit() and
70
+ * will notice laio->ret has been filled in when it eventually runs
71
+ * later. Coroutines cannot be entered recursively so avoid doing
72
+ * that!
73
+ */
74
+ if (!qemu_coroutine_entered(laiocb->co)) {
75
+ aio_co_wake(laiocb->co);
76
}
77
}
78
79
@@ -XXX,XX +XXX,XX @@ static bool qemu_laio_poll_cb(void *opaque)
80
return true;
81
}
82
83
-static void laio_cancel(BlockAIOCB *blockacb)
84
-{
85
- struct qemu_laiocb *laiocb = (struct qemu_laiocb *)blockacb;
86
- struct io_event event;
87
- int ret;
88
-
89
- if (laiocb->ret != -EINPROGRESS) {
90
- return;
91
- }
92
- ret = io_cancel(laiocb->ctx->ctx, &laiocb->iocb, &event);
93
- laiocb->ret = -ECANCELED;
94
- if (ret != 0) {
95
- /* iocb is not cancelled, cb will be called by the event loop later */
96
- return;
97
- }
98
-
99
- laiocb->common.cb(laiocb->common.opaque, laiocb->ret);
100
-}
101
-
102
-static const AIOCBInfo laio_aiocb_info = {
103
- .aiocb_size = sizeof(struct qemu_laiocb),
104
- .cancel_async = laio_cancel,
105
-};
106
-
107
static void ioq_init(LaioQueue *io_q)
108
{
109
QSIMPLEQ_INIT(&io_q->pending);
110
@@ -XXX,XX +XXX,XX @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
111
return laiocb.ret;
112
}
113
114
-BlockAIOCB *laio_submit(BlockDriverState *bs, LinuxAioState *s, int fd,
115
- int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
116
- BlockCompletionFunc *cb, void *opaque, int type)
117
-{
118
- struct qemu_laiocb *laiocb;
119
- off_t offset = sector_num * BDRV_SECTOR_SIZE;
120
- int ret;
121
-
122
- laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque);
123
- laiocb->nbytes = nb_sectors * BDRV_SECTOR_SIZE;
124
- laiocb->ctx = s;
125
- laiocb->ret = -EINPROGRESS;
126
- laiocb->is_read = (type == QEMU_AIO_READ);
127
- laiocb->qiov = qiov;
128
-
129
- ret = laio_do_submit(fd, laiocb, offset, type);
130
- if (ret < 0) {
131
- qemu_aio_unref(laiocb);
132
- return NULL;
133
- }
134
-
135
- return &laiocb->common;
136
-}
137
-
138
void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
139
{
140
aio_set_event_notifier(old_context, &s->e, false, NULL, NULL);
141
--
142
2.20.1
143
144
diff view generated by jsdifflib
Deleted patch
1
From: Kenneth Heitke <kenneth.heitke@intel.com>
2
1
3
Signed-off-by: Kenneth Heitke <kenneth.heitke@intel.com>
4
Reviewed-by: Klaus Birkelund Jensen <klaus.jensen@cnexlabs.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
hw/block/nvme.h | 2 +
8
include/block/nvme.h | 2 +
9
hw/block/nvme.c | 106 +++++++++++++++++++++++++++++++++++++++++-
10
hw/block/trace-events | 2 +
11
4 files changed, 110 insertions(+), 2 deletions(-)
12
13
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/block/nvme.h
16
+++ b/hw/block/nvme.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct NvmeCtrl {
18
uint32_t cmbloc;
19
uint8_t *cmbuf;
20
uint64_t irq_status;
21
+ uint64_t host_timestamp; /* Timestamp sent by the host */
22
+ uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
23
24
char *serial;
25
NvmeNamespace *namespaces;
26
diff --git a/include/block/nvme.h b/include/block/nvme.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/block/nvme.h
29
+++ b/include/block/nvme.h
30
@@ -XXX,XX +XXX,XX @@ enum NvmeIdCtrlOncs {
31
NVME_ONCS_WRITE_ZEROS = 1 << 3,
32
NVME_ONCS_FEATURES = 1 << 4,
33
NVME_ONCS_RESRVATIONS = 1 << 5,
34
+ NVME_ONCS_TIMESTAMP = 1 << 6,
35
};
36
37
#define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf)
38
@@ -XXX,XX +XXX,XX @@ enum NvmeFeatureIds {
39
NVME_INTERRUPT_VECTOR_CONF = 0x9,
40
NVME_WRITE_ATOMICITY = 0xa,
41
NVME_ASYNCHRONOUS_EVENT_CONF = 0xb,
42
+ NVME_TIMESTAMP = 0xe,
43
NVME_SOFTWARE_PROGRESS_MARKER = 0x80
44
};
45
46
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/block/nvme.c
49
+++ b/hw/block/nvme.c
50
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_map_prp(QEMUSGList *qsg, QEMUIOVector *iov, uint64_t prp1,
51
return NVME_INVALID_FIELD | NVME_DNR;
52
}
53
54
+static uint16_t nvme_dma_write_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
55
+ uint64_t prp1, uint64_t prp2)
56
+{
57
+ QEMUSGList qsg;
58
+ QEMUIOVector iov;
59
+ uint16_t status = NVME_SUCCESS;
60
+
61
+ if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) {
62
+ return NVME_INVALID_FIELD | NVME_DNR;
63
+ }
64
+ if (qsg.nsg > 0) {
65
+ if (dma_buf_write(ptr, len, &qsg)) {
66
+ status = NVME_INVALID_FIELD | NVME_DNR;
67
+ }
68
+ qemu_sglist_destroy(&qsg);
69
+ } else {
70
+ if (qemu_iovec_to_buf(&iov, 0, ptr, len) != len) {
71
+ status = NVME_INVALID_FIELD | NVME_DNR;
72
+ }
73
+ qemu_iovec_destroy(&iov);
74
+ }
75
+ return status;
76
+}
77
+
78
static uint16_t nvme_dma_read_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
79
uint64_t prp1, uint64_t prp2)
80
{
81
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c)
82
return ret;
83
}
84
85
-
86
static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
87
{
88
NvmeIdentify *c = (NvmeIdentify *)cmd;
89
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
90
}
91
}
92
93
+static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts)
94
+{
95
+ trace_nvme_setfeat_timestamp(ts);
96
+
97
+ n->host_timestamp = le64_to_cpu(ts);
98
+ n->timestamp_set_qemu_clock_ms = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
99
+}
100
+
101
+static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n)
102
+{
103
+ uint64_t current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
104
+ uint64_t elapsed_time = current_time - n->timestamp_set_qemu_clock_ms;
105
+
106
+ union nvme_timestamp {
107
+ struct {
108
+ uint64_t timestamp:48;
109
+ uint64_t sync:1;
110
+ uint64_t origin:3;
111
+ uint64_t rsvd1:12;
112
+ };
113
+ uint64_t all;
114
+ };
115
+
116
+ union nvme_timestamp ts;
117
+ ts.all = 0;
118
+
119
+ /*
120
+ * If the sum of the Timestamp value set by the host and the elapsed
121
+ * time exceeds 2^48, the value returned should be reduced modulo 2^48.
122
+ */
123
+ ts.timestamp = (n->host_timestamp + elapsed_time) & 0xffffffffffff;
124
+
125
+ /* If the host timestamp is non-zero, set the timestamp origin */
126
+ ts.origin = n->host_timestamp ? 0x01 : 0x00;
127
+
128
+ trace_nvme_getfeat_timestamp(ts.all);
129
+
130
+ return cpu_to_le64(ts.all);
131
+}
132
+
133
+static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd)
134
+{
135
+ uint64_t prp1 = le64_to_cpu(cmd->prp1);
136
+ uint64_t prp2 = le64_to_cpu(cmd->prp2);
137
+
138
+ uint64_t timestamp = nvme_get_timestamp(n);
139
+
140
+ return nvme_dma_read_prp(n, (uint8_t *)&timestamp,
141
+ sizeof(timestamp), prp1, prp2);
142
+}
143
+
144
static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
145
{
146
uint32_t dw10 = le32_to_cpu(cmd->cdw10);
147
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
148
result = cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16));
149
trace_nvme_getfeat_numq(result);
150
break;
151
+ case NVME_TIMESTAMP:
152
+ return nvme_get_feature_timestamp(n, cmd);
153
+ break;
154
default:
155
trace_nvme_err_invalid_getfeat(dw10);
156
return NVME_INVALID_FIELD | NVME_DNR;
157
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
158
return NVME_SUCCESS;
159
}
160
161
+static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd)
162
+{
163
+ uint16_t ret;
164
+ uint64_t timestamp;
165
+ uint64_t prp1 = le64_to_cpu(cmd->prp1);
166
+ uint64_t prp2 = le64_to_cpu(cmd->prp2);
167
+
168
+ ret = nvme_dma_write_prp(n, (uint8_t *)&timestamp,
169
+ sizeof(timestamp), prp1, prp2);
170
+ if (ret != NVME_SUCCESS) {
171
+ return ret;
172
+ }
173
+
174
+ nvme_set_timestamp(n, timestamp);
175
+
176
+ return NVME_SUCCESS;
177
+}
178
+
179
static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
180
{
181
uint32_t dw10 = le32_to_cpu(cmd->cdw10);
182
@@ -XXX,XX +XXX,XX @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
183
req->cqe.result =
184
cpu_to_le32((n->num_queues - 2) | ((n->num_queues - 2) << 16));
185
break;
186
+
187
+ case NVME_TIMESTAMP:
188
+ return nvme_set_feature_timestamp(n, cmd);
189
+ break;
190
+
191
default:
192
trace_nvme_err_invalid_setfeat(dw10);
193
return NVME_INVALID_FIELD | NVME_DNR;
194
@@ -XXX,XX +XXX,XX @@ static int nvme_start_ctrl(NvmeCtrl *n)
195
nvme_init_sq(&n->admin_sq, n, n->bar.asq, 0, 0,
196
NVME_AQA_ASQS(n->bar.aqa) + 1);
197
198
+ nvme_set_timestamp(n, 0ULL);
199
+
200
return 0;
201
}
202
203
@@ -XXX,XX +XXX,XX @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
204
id->sqes = (0x6 << 4) | 0x6;
205
id->cqes = (0x4 << 4) | 0x4;
206
id->nn = cpu_to_le32(n->num_namespaces);
207
- id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS);
208
+ id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP);
209
id->psd[0].mp = cpu_to_le16(0x9c4);
210
id->psd[0].enlat = cpu_to_le32(0x10);
211
id->psd[0].exlat = cpu_to_le32(0x4);
212
diff --git a/hw/block/trace-events b/hw/block/trace-events
213
index XXXXXXX..XXXXXXX 100644
214
--- a/hw/block/trace-events
215
+++ b/hw/block/trace-events
216
@@ -XXX,XX +XXX,XX @@ nvme_identify_nslist(uint16_t ns) "identify namespace list, nsid=%"PRIu16""
217
nvme_getfeat_vwcache(const char* result) "get feature volatile write cache, result=%s"
218
nvme_getfeat_numq(int result) "get feature number of queues, result=%d"
219
nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d"
220
+nvme_setfeat_timestamp(uint64_t ts) "set feature timestamp = 0x%"PRIx64""
221
+nvme_getfeat_timestamp(uint64_t ts) "get feature timestamp = 0x%"PRIx64""
222
nvme_mmio_intm_set(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask set, data=0x%"PRIx64", new_mask=0x%"PRIx64""
223
nvme_mmio_intm_clr(uint64_t data, uint64_t new_mask) "wrote MMIO, interrupt mask clr, data=0x%"PRIx64", new_mask=0x%"PRIx64""
224
nvme_mmio_cfg(uint64_t data) "wrote MMIO, config controller config=0x%"PRIx64""
225
--
226
2.20.1
227
228
diff view generated by jsdifflib
Deleted patch
1
Just make the test cover the AioContext of the filter node as well.
2
1
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
Reviewed-by: Eric Blake <eblake@redhat.com>
5
---
6
tests/test-block-iothread.c | 7 ++++++-
7
1 file changed, 6 insertions(+), 1 deletion(-)
8
9
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/tests/test-block-iothread.c
12
+++ b/tests/test-block-iothread.c
13
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
14
IOThread *iothread = iothread_new();
15
AioContext *ctx = iothread_get_aio_context(iothread);
16
AioContext *main_ctx = qemu_get_aio_context();
17
- BlockDriverState *src, *target;
18
+ BlockDriverState *src, *target, *filter;
19
BlockBackend *blk;
20
Job *job;
21
Error *local_err = NULL;
22
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
23
false, "filter_node", MIRROR_COPY_MODE_BACKGROUND,
24
&error_abort);
25
job = job_get("job0");
26
+ filter = bdrv_find_node("filter_node");
27
28
/* Change the AioContext of src */
29
bdrv_try_set_aio_context(src, ctx, &error_abort);
30
g_assert(bdrv_get_aio_context(src) == ctx);
31
g_assert(bdrv_get_aio_context(target) == ctx);
32
+ g_assert(bdrv_get_aio_context(filter) == ctx);
33
g_assert(job->aio_context == ctx);
34
35
/* Change the AioContext of target */
36
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
37
aio_context_release(ctx);
38
g_assert(bdrv_get_aio_context(src) == main_ctx);
39
g_assert(bdrv_get_aio_context(target) == main_ctx);
40
+ g_assert(bdrv_get_aio_context(filter) == main_ctx);
41
42
/* With a BlockBackend on src, changing target must fail */
43
blk = blk_new(0, BLK_PERM_ALL);
44
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
45
g_assert(blk_get_aio_context(blk) == main_ctx);
46
g_assert(bdrv_get_aio_context(src) == main_ctx);
47
g_assert(bdrv_get_aio_context(target) == main_ctx);
48
+ g_assert(bdrv_get_aio_context(filter) == main_ctx);
49
50
/* ...unless we explicitly allow it */
51
aio_context_acquire(ctx);
52
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
53
g_assert(blk_get_aio_context(blk) == ctx);
54
g_assert(bdrv_get_aio_context(src) == ctx);
55
g_assert(bdrv_get_aio_context(target) == ctx);
56
+ g_assert(bdrv_get_aio_context(filter) == ctx);
57
58
job_cancel_sync_all();
59
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
Deleted patch
1
The NBD server uses an AioContext notifier, so it can tolerate that its
2
BlockBackend is switched to a different AioContext. Before we start
3
actually calling bdrv_try_set_aio_context(), which checks for
4
consistency, outside of test cases, we need to make sure that the NBD
5
server actually allows this.
6
1
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
---
10
nbd/server.c | 1 +
11
tests/qemu-iotests/240 | 21 +++++++++++++++++++++
12
tests/qemu-iotests/240.out | 13 +++++++++++++
13
3 files changed, 35 insertions(+)
14
15
diff --git a/nbd/server.c b/nbd/server.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/nbd/server.c
18
+++ b/nbd/server.c
19
@@ -XXX,XX +XXX,XX @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
20
goto fail;
21
}
22
blk_set_enable_write_cache(blk, !writethrough);
23
+ blk_set_allow_aio_context_change(blk, true);
24
25
exp->refcount = 1;
26
QTAILQ_INIT(&exp->clients);
27
diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240
28
index XXXXXXX..XXXXXXX 100755
29
--- a/tests/qemu-iotests/240
30
+++ b/tests/qemu-iotests/240
31
@@ -XXX,XX +XXX,XX @@ echo "QA output created by $seq"
32
33
status=1    # failure is the default!
34
35
+_cleanup()
36
+{
37
+ rm -f "$TEST_DIR/nbd"
38
+}
39
+trap "_cleanup; exit \$status" 0 1 2 3 15
40
+
41
# get standard environment, filters and checks
42
. ./common.rc
43
. ./common.filter
44
@@ -XXX,XX +XXX,XX @@ run_qemu <<EOF
45
{ "execute": "quit"}
46
EOF
47
48
+echo
49
+echo === Attach a SCSI disks using the same block device as a NBD server ===
50
+echo
51
+
52
+run_qemu <<EOF
53
+{ "execute": "qmp_capabilities" }
54
+{ "execute": "blockdev-add", "arguments": {"driver": "null-co", "node-name": "hd0", "read-only": true}}
55
+{ "execute": "nbd-server-start", "arguments": {"addr":{"type":"unix","data":{"path":"$TEST_DIR/nbd"}}}}
56
+{ "execute": "nbd-server-add", "arguments": {"device":"hd0"}}
57
+{ "execute": "object-add", "arguments": {"qom-type": "iothread", "id": "iothread0"}}
58
+{ "execute": "device_add", "arguments": {"id": "scsi0", "driver": "${virtio_scsi}", "iothread": "iothread0"}}
59
+{ "execute": "device_add", "arguments": {"id": "scsi-hd0", "driver": "scsi-hd", "drive": "hd0", "bus": "scsi0.0"}}
60
+{ "execute": "quit"}
61
+EOF
62
+
63
# success, all done
64
echo "*** done"
65
rm -f $seq.full
66
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
67
index XXXXXXX..XXXXXXX 100644
68
--- a/tests/qemu-iotests/240.out
69
+++ b/tests/qemu-iotests/240.out
70
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
71
{"return": {}}
72
{"return": {}}
73
{"return": {}}
74
+
75
+=== Attach a SCSI disks using the same block device as a NBD server ===
76
+
77
+Testing:
78
+QMP_VERSION
79
+{"return": {}}
80
+{"return": {}}
81
+{"return": {}}
82
+{"return": {}}
83
+{"return": {}}
84
+{"return": {}}
85
+{"return": {}}
86
+{"return": {}}
87
*** done
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
Deleted patch
1
Add an Error parameter to blk_set_aio_context() and use
2
bdrv_child_try_set_aio_context() internally to check whether all
3
involved nodes can actually support the AioContext switch.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
include/sysemu/block-backend.h | 3 ++-
8
block/block-backend.c | 26 ++++++++++++++++----------
9
hw/block/dataplane/virtio-blk.c | 12 +++++++++---
10
hw/block/dataplane/xen-block.c | 6 ++++--
11
hw/scsi/virtio-scsi.c | 10 +++++++---
12
tests/test-bdrv-drain.c | 8 ++++----
13
tests/test-block-iothread.c | 22 +++++++++++-----------
14
7 files changed, 53 insertions(+), 34 deletions(-)
15
16
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/block-backend.h
19
+++ b/include/sysemu/block-backend.h
20
@@ -XXX,XX +XXX,XX @@ void blk_op_unblock(BlockBackend *blk, BlockOpType op, Error *reason);
21
void blk_op_block_all(BlockBackend *blk, Error *reason);
22
void blk_op_unblock_all(BlockBackend *blk, Error *reason);
23
AioContext *blk_get_aio_context(BlockBackend *blk);
24
-void blk_set_aio_context(BlockBackend *blk, AioContext *new_context);
25
+int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
26
+ Error **errp);
27
void blk_add_aio_context_notifier(BlockBackend *blk,
28
void (*attached_aio_context)(AioContext *new_context, void *opaque),
29
void (*detach_aio_context)(void *opaque), void *opaque);
30
diff --git a/block/block-backend.c b/block/block-backend.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block/block-backend.c
33
+++ b/block/block-backend.c
34
@@ -XXX,XX +XXX,XX @@ static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
35
return blk_get_aio_context(blk_acb->blk);
36
}
37
38
-static void blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
39
- bool update_root_node)
40
+static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
41
+ bool update_root_node, Error **errp)
42
{
43
BlockDriverState *bs = blk_bs(blk);
44
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
45
+ int ret;
46
47
if (bs) {
48
+ if (update_root_node) {
49
+ ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
50
+ errp);
51
+ if (ret < 0) {
52
+ return ret;
53
+ }
54
+ }
55
if (tgm->throttle_state) {
56
bdrv_drained_begin(bs);
57
throttle_group_detach_aio_context(tgm);
58
throttle_group_attach_aio_context(tgm, new_context);
59
bdrv_drained_end(bs);
60
}
61
- if (update_root_node) {
62
- GSList *ignore = g_slist_prepend(NULL, blk->root);
63
- bdrv_set_aio_context_ignore(bs, new_context, &ignore);
64
- g_slist_free(ignore);
65
- }
66
}
67
+
68
+ return 0;
69
}
70
71
-void blk_set_aio_context(BlockBackend *blk, AioContext *new_context)
72
+int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
73
+ Error **errp)
74
{
75
- blk_do_set_aio_context(blk, new_context, true);
76
+ return blk_do_set_aio_context(blk, new_context, true, errp);
77
}
78
79
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
80
@@ -XXX,XX +XXX,XX @@ static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
81
GSList **ignore)
82
{
83
BlockBackend *blk = child->opaque;
84
- blk_do_set_aio_context(blk, ctx, false);
85
+ blk_do_set_aio_context(blk, ctx, false, &error_abort);
86
}
87
88
void blk_add_aio_context_notifier(BlockBackend *blk,
89
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/hw/block/dataplane/virtio-blk.c
92
+++ b/hw/block/dataplane/virtio-blk.c
93
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
94
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
95
unsigned i;
96
unsigned nvqs = s->conf->num_queues;
97
+ Error *local_err = NULL;
98
int r;
99
100
if (vblk->dataplane_started || s->starting) {
101
@@ -XXX,XX +XXX,XX @@ int virtio_blk_data_plane_start(VirtIODevice *vdev)
102
vblk->dataplane_started = true;
103
trace_virtio_blk_data_plane_start(s);
104
105
- blk_set_aio_context(s->conf->conf.blk, s->ctx);
106
+ r = blk_set_aio_context(s->conf->conf.blk, s->ctx, &local_err);
107
+ if (r < 0) {
108
+ error_report_err(local_err);
109
+ goto fail_guest_notifiers;
110
+ }
111
112
/* Kick right away to begin processing requests already in vring */
113
for (i = 0; i < nvqs; i++) {
114
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
115
aio_context_acquire(s->ctx);
116
aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s);
117
118
- /* Drain and switch bs back to the QEMU main loop */
119
- blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context());
120
+ /* Drain and try to switch bs back to the QEMU main loop. If other users
121
+ * keep the BlockBackend in the iothread, that's ok */
122
+ blk_set_aio_context(s->conf->conf.blk, qemu_get_aio_context(), NULL);
123
124
aio_context_release(s->ctx);
125
126
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/hw/block/dataplane/xen-block.c
129
+++ b/hw/block/dataplane/xen-block.c
130
@@ -XXX,XX +XXX,XX @@ void xen_block_dataplane_stop(XenBlockDataPlane *dataplane)
131
}
132
133
aio_context_acquire(dataplane->ctx);
134
- blk_set_aio_context(dataplane->blk, qemu_get_aio_context());
135
+ /* Xen doesn't have multiple users for nodes, so this can't fail */
136
+ blk_set_aio_context(dataplane->blk, qemu_get_aio_context(), &error_abort);
137
aio_context_release(dataplane->ctx);
138
139
xendev = dataplane->xendev;
140
@@ -XXX,XX +XXX,XX @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane,
141
}
142
143
aio_context_acquire(dataplane->ctx);
144
- blk_set_aio_context(dataplane->blk, dataplane->ctx);
145
+ /* If other users keep the BlockBackend in the iothread, that's ok */
146
+ blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL);
147
aio_context_release(dataplane->ctx);
148
return;
149
150
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
151
index XXXXXXX..XXXXXXX 100644
152
--- a/hw/scsi/virtio-scsi.c
153
+++ b/hw/scsi/virtio-scsi.c
154
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
155
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
156
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
157
SCSIDevice *sd = SCSI_DEVICE(dev);
158
+ int ret;
159
160
if (s->ctx && !s->dataplane_fenced) {
161
AioContext *ctx;
162
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
163
return;
164
}
165
virtio_scsi_acquire(s);
166
- blk_set_aio_context(sd->conf.blk, s->ctx);
167
+ ret = blk_set_aio_context(sd->conf.blk, s->ctx, errp);
168
virtio_scsi_release(s);
169
-
170
+ if (ret < 0) {
171
+ return;
172
+ }
173
}
174
175
if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
176
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
177
178
if (s->ctx) {
179
virtio_scsi_acquire(s);
180
- blk_set_aio_context(sd->conf.blk, qemu_get_aio_context());
181
+ /* If other users keep the BlockBackend in the iothread, that's ok */
182
+ blk_set_aio_context(sd->conf.blk, qemu_get_aio_context(), NULL);
183
virtio_scsi_release(s);
184
}
185
186
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/tests/test-bdrv-drain.c
189
+++ b/tests/test-bdrv-drain.c
190
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
191
s = bs->opaque;
192
blk_insert_bs(blk, bs, &error_abort);
193
194
- blk_set_aio_context(blk, ctx_a);
195
+ blk_set_aio_context(blk, ctx_a, &error_abort);
196
aio_context_acquire(ctx_a);
197
198
s->bh_indirection_ctx = ctx_b;
199
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
200
}
201
202
aio_context_acquire(ctx_a);
203
- blk_set_aio_context(blk, qemu_get_aio_context());
204
+ blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
205
aio_context_release(ctx_a);
206
207
bdrv_unref(bs);
208
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
209
if (use_iothread) {
210
iothread = iothread_new();
211
ctx = iothread_get_aio_context(iothread);
212
- blk_set_aio_context(blk_src, ctx);
213
+ blk_set_aio_context(blk_src, ctx, &error_abort);
214
} else {
215
ctx = qemu_get_aio_context();
216
}
217
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
218
g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO));
219
220
if (use_iothread) {
221
- blk_set_aio_context(blk_src, qemu_get_aio_context());
222
+ blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort);
223
}
224
aio_context_release(ctx);
225
226
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/tests/test-block-iothread.c
229
+++ b/tests/test-block-iothread.c
230
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
231
blk_insert_bs(blk, bs, &error_abort);
232
c = QLIST_FIRST(&bs->parents);
233
234
- blk_set_aio_context(blk, ctx);
235
+ blk_set_aio_context(blk, ctx, &error_abort);
236
aio_context_acquire(ctx);
237
t->fn(c);
238
if (t->blkfn) {
239
t->blkfn(blk);
240
}
241
aio_context_release(ctx);
242
- blk_set_aio_context(blk, qemu_get_aio_context());
243
+ blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
244
245
bdrv_unref(bs);
246
blk_unref(blk);
247
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
248
aio_poll(qemu_get_aio_context(), false);
249
}
250
251
- blk_set_aio_context(blk, ctx);
252
+ blk_set_aio_context(blk, ctx, &error_abort);
253
254
tjob->n = 0;
255
while (tjob->n == 0) {
256
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
257
}
258
259
aio_context_acquire(ctx);
260
- blk_set_aio_context(blk, qemu_get_aio_context());
261
+ blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
262
aio_context_release(ctx);
263
264
tjob->n = 0;
265
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
266
aio_poll(qemu_get_aio_context(), false);
267
}
268
269
- blk_set_aio_context(blk, ctx);
270
+ blk_set_aio_context(blk, ctx, &error_abort);
271
272
tjob->n = 0;
273
while (tjob->n == 0) {
274
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
275
276
aio_context_acquire(ctx);
277
job_complete_sync(&tjob->common.job, &error_abort);
278
- blk_set_aio_context(blk, qemu_get_aio_context());
279
+ blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
280
aio_context_release(ctx);
281
282
bdrv_unref(bs);
283
@@ -XXX,XX +XXX,XX @@ static void test_propagate_basic(void)
284
bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
285
286
/* Switch the AioContext */
287
- blk_set_aio_context(blk, ctx);
288
+ blk_set_aio_context(blk, ctx, &error_abort);
289
g_assert(blk_get_aio_context(blk) == ctx);
290
g_assert(bdrv_get_aio_context(bs_a) == ctx);
291
g_assert(bdrv_get_aio_context(bs_verify) == ctx);
292
@@ -XXX,XX +XXX,XX @@ static void test_propagate_basic(void)
293
294
/* Switch the AioContext back */
295
ctx = qemu_get_aio_context();
296
- blk_set_aio_context(blk, ctx);
297
+ blk_set_aio_context(blk, ctx, &error_abort);
298
g_assert(blk_get_aio_context(blk) == ctx);
299
g_assert(bdrv_get_aio_context(bs_a) == ctx);
300
g_assert(bdrv_get_aio_context(bs_verify) == ctx);
301
@@ -XXX,XX +XXX,XX @@ static void test_propagate_diamond(void)
302
blk_insert_bs(blk, bs_verify, &error_abort);
303
304
/* Switch the AioContext */
305
- blk_set_aio_context(blk, ctx);
306
+ blk_set_aio_context(blk, ctx, &error_abort);
307
g_assert(blk_get_aio_context(blk) == ctx);
308
g_assert(bdrv_get_aio_context(bs_verify) == ctx);
309
g_assert(bdrv_get_aio_context(bs_a) == ctx);
310
@@ -XXX,XX +XXX,XX @@ static void test_propagate_diamond(void)
311
312
/* Switch the AioContext back */
313
ctx = qemu_get_aio_context();
314
- blk_set_aio_context(blk, ctx);
315
+ blk_set_aio_context(blk, ctx, &error_abort);
316
g_assert(blk_get_aio_context(blk) == ctx);
317
g_assert(bdrv_get_aio_context(bs_verify) == ctx);
318
g_assert(bdrv_get_aio_context(bs_a) == ctx);
319
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
320
job_cancel_sync_all();
321
322
aio_context_acquire(ctx);
323
- blk_set_aio_context(blk, main_ctx);
324
+ blk_set_aio_context(blk, main_ctx, &error_abort);
325
bdrv_try_set_aio_context(target, main_ctx, &error_abort);
326
aio_context_release(ctx);
327
328
--
329
2.20.1
330
331
diff view generated by jsdifflib
Deleted patch
1
This adds a new parameter to blk_new() which requires its callers to
2
declare from which AioContext this BlockBackend is going to be used (or
3
the locks of which AioContext need to be taken anyway).
4
1
5
The given context is only stored and kept up to date when changing
6
AioContexts. Actually applying the stored AioContext to the root node
7
is saved for another commit.
8
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/sysemu/block-backend.h | 2 +-
12
block.c | 2 +-
13
block/backup.c | 3 ++-
14
block/block-backend.c | 18 +++++++++++++++---
15
block/commit.c | 11 +++++++----
16
block/crypto.c | 3 ++-
17
block/mirror.c | 3 ++-
18
block/parallels.c | 3 ++-
19
block/qcow.c | 3 ++-
20
block/qcow2.c | 6 ++++--
21
block/qed.c | 3 ++-
22
block/sheepdog.c | 3 ++-
23
block/vdi.c | 3 ++-
24
block/vhdx.c | 3 ++-
25
block/vmdk.c | 3 ++-
26
block/vpc.c | 3 ++-
27
blockdev.c | 4 ++--
28
blockjob.c | 2 +-
29
hmp.c | 3 ++-
30
hw/block/fdc.c | 2 +-
31
hw/block/xen-block.c | 2 +-
32
hw/core/qdev-properties-system.c | 4 +++-
33
hw/ide/qdev.c | 2 +-
34
hw/scsi/scsi-disk.c | 2 +-
35
migration/block.c | 3 ++-
36
nbd/server.c | 5 +++--
37
qemu-img.c | 6 ++++--
38
tests/test-bdrv-drain.c | 30 +++++++++++++++---------------
39
tests/test-bdrv-graph-mod.c | 5 +++--
40
tests/test-block-backend.c | 6 ++++--
41
tests/test-block-iothread.c | 10 +++++-----
42
tests/test-blockjob.c | 2 +-
43
tests/test-throttle.c | 6 +++---
44
33 files changed, 102 insertions(+), 64 deletions(-)
45
46
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/sysemu/block-backend.h
49
+++ b/include/sysemu/block-backend.h
50
@@ -XXX,XX +XXX,XX @@ typedef struct BlockBackendPublic {
51
ThrottleGroupMember throttle_group_member;
52
} BlockBackendPublic;
53
54
-BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm);
55
+BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm);
56
BlockBackend *blk_new_open(const char *filename, const char *reference,
57
QDict *options, int flags, Error **errp);
58
int blk_get_refcnt(BlockBackend *blk);
59
diff --git a/block.c b/block.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/block.c
62
+++ b/block.c
63
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
64
/* Not requesting BLK_PERM_CONSISTENT_READ because we're only
65
* looking at the header to guess the image format. This works even
66
* in cases where a guest would not see a consistent state. */
67
- file = blk_new(0, BLK_PERM_ALL);
68
+ file = blk_new(bdrv_get_aio_context(file_bs), 0, BLK_PERM_ALL);
69
blk_insert_bs(file, file_bs, &local_err);
70
bdrv_unref(file_bs);
71
if (local_err) {
72
diff --git a/block/backup.c b/block/backup.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/block/backup.c
75
+++ b/block/backup.c
76
@@ -XXX,XX +XXX,XX @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs,
77
}
78
79
/* The target must match the source in size, so no resize here either */
80
- job->target = blk_new(BLK_PERM_WRITE,
81
+ job->target = blk_new(job->common.job.aio_context,
82
+ BLK_PERM_WRITE,
83
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE |
84
BLK_PERM_WRITE_UNCHANGED | BLK_PERM_GRAPH_MOD);
85
ret = blk_insert_bs(job->target, target, errp);
86
diff --git a/block/block-backend.c b/block/block-backend.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/block/block-backend.c
89
+++ b/block/block-backend.c
90
@@ -XXX,XX +XXX,XX @@ struct BlockBackend {
91
char *name;
92
int refcnt;
93
BdrvChild *root;
94
+ AioContext *ctx;
95
DriveInfo *legacy_dinfo; /* null unless created by drive_new() */
96
QTAILQ_ENTRY(BlockBackend) link; /* for block_backends */
97
QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
98
@@ -XXX,XX +XXX,XX @@ static const BdrvChildRole child_root = {
99
*
100
* Return the new BlockBackend on success, null on failure.
101
*/
102
-BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
103
+BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
104
{
105
BlockBackend *blk;
106
107
blk = g_new0(BlockBackend, 1);
108
blk->refcnt = 1;
109
+ blk->ctx = ctx;
110
blk->perm = perm;
111
blk->shared_perm = shared_perm;
112
blk_set_enable_write_cache(blk, true);
113
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
114
115
/*
116
* Creates a new BlockBackend, opens a new BlockDriverState, and connects both.
117
+ * The new BlockBackend is in the main AioContext.
118
*
119
* Just as with bdrv_open(), after having called this function the reference to
120
* @options belongs to the block layer (even on failure).
121
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
122
perm |= BLK_PERM_RESIZE;
123
}
124
125
- blk = blk_new(perm, BLK_PERM_ALL);
126
+ blk = blk_new(qemu_get_aio_context(), perm, BLK_PERM_ALL);
127
bs = bdrv_open(filename, reference, options, flags, errp);
128
if (!bs) {
129
blk_unref(blk);
130
@@ -XXX,XX +XXX,XX @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
131
132
AioContext *blk_get_aio_context(BlockBackend *blk)
133
{
134
- return bdrv_get_aio_context(blk_bs(blk));
135
+ BlockDriverState *bs = blk_bs(blk);
136
+
137
+ /* FIXME The AioContext of bs and blk can be inconsistent. For the moment,
138
+ * we prefer the one of bs for compatibility. */
139
+ if (bs) {
140
+ return bdrv_get_aio_context(blk_bs(blk));
141
+ }
142
+
143
+ return blk->ctx;
144
}
145
146
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb)
147
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
148
}
149
}
150
151
+ blk->ctx = new_context;
152
return 0;
153
}
154
155
diff --git a/block/commit.c b/block/commit.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/block/commit.c
158
+++ b/block/commit.c
159
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
160
goto fail;
161
}
162
163
- s->base = blk_new(BLK_PERM_CONSISTENT_READ
164
+ s->base = blk_new(s->common.job.aio_context,
165
+ BLK_PERM_CONSISTENT_READ
166
| BLK_PERM_WRITE
167
| BLK_PERM_RESIZE,
168
BLK_PERM_CONSISTENT_READ
169
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
170
s->base_bs = base;
171
172
/* Required permissions are already taken with block_job_add_bdrv() */
173
- s->top = blk_new(0, BLK_PERM_ALL);
174
+ s->top = blk_new(s->common.job.aio_context, 0, BLK_PERM_ALL);
175
ret = blk_insert_bs(s->top, top, errp);
176
if (ret < 0) {
177
goto fail;
178
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
179
BlockDriverState *backing_file_bs = NULL;
180
BlockDriverState *commit_top_bs = NULL;
181
BlockDriver *drv = bs->drv;
182
+ AioContext *ctx;
183
int64_t offset, length, backing_length;
184
int ro;
185
int64_t n;
186
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
187
}
188
}
189
190
- src = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
191
- backing = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
192
+ ctx = bdrv_get_aio_context(bs);
193
+ src = blk_new(ctx, BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
194
+ backing = blk_new(ctx, BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
195
196
ret = blk_insert_bs(src, bs, &local_err);
197
if (ret < 0) {
198
diff --git a/block/crypto.c b/block/crypto.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/block/crypto.c
201
+++ b/block/crypto.c
202
@@ -XXX,XX +XXX,XX @@ static int block_crypto_co_create_generic(BlockDriverState *bs,
203
QCryptoBlock *crypto = NULL;
204
struct BlockCryptoCreateData data;
205
206
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
207
+ blk = blk_new(bdrv_get_aio_context(bs),
208
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
209
210
ret = blk_insert_bs(blk, bs, errp);
211
if (ret < 0) {
212
diff --git a/block/mirror.c b/block/mirror.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/mirror.c
215
+++ b/block/mirror.c
216
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
217
* We can allow anything except resize there.*/
218
target_is_backing = bdrv_chain_contains(bs, target);
219
target_graph_mod = (backing_mode != MIRROR_LEAVE_BACKING_CHAIN);
220
- s->target = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE |
221
+ s->target = blk_new(s->common.job.aio_context,
222
+ BLK_PERM_WRITE | BLK_PERM_RESIZE |
223
(target_graph_mod ? BLK_PERM_GRAPH_MOD : 0),
224
BLK_PERM_WRITE_UNCHANGED |
225
(target_is_backing ? BLK_PERM_CONSISTENT_READ |
226
diff --git a/block/parallels.c b/block/parallels.c
227
index XXXXXXX..XXXXXXX 100644
228
--- a/block/parallels.c
229
+++ b/block/parallels.c
230
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
231
return -EIO;
232
}
233
234
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
235
+ blk = blk_new(bdrv_get_aio_context(bs),
236
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
237
ret = blk_insert_bs(blk, bs, errp);
238
if (ret < 0) {
239
goto out;
240
diff --git a/block/qcow.c b/block/qcow.c
241
index XXXXXXX..XXXXXXX 100644
242
--- a/block/qcow.c
243
+++ b/block/qcow.c
244
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
245
return -EIO;
246
}
247
248
- qcow_blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
249
+ qcow_blk = blk_new(bdrv_get_aio_context(bs),
250
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
251
ret = blk_insert_bs(qcow_blk, bs, errp);
252
if (ret < 0) {
253
goto exit;
254
diff --git a/block/qcow2.c b/block/qcow2.c
255
index XXXXXXX..XXXXXXX 100644
256
--- a/block/qcow2.c
257
+++ b/block/qcow2.c
258
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
259
}
260
261
/* Create BlockBackend to write to the image */
262
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
263
+ blk = blk_new(bdrv_get_aio_context(bs),
264
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
265
ret = blk_insert_bs(blk, bs, errp);
266
if (ret < 0) {
267
goto out;
268
@@ -XXX,XX +XXX,XX @@ static int qcow2_amend_options(BlockDriverState *bs, QemuOpts *opts,
269
}
270
271
if (new_size) {
272
- BlockBackend *blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
273
+ BlockBackend *blk = blk_new(bdrv_get_aio_context(bs),
274
+ BLK_PERM_RESIZE, BLK_PERM_ALL);
275
ret = blk_insert_bs(blk, bs, errp);
276
if (ret < 0) {
277
blk_unref(blk);
278
diff --git a/block/qed.c b/block/qed.c
279
index XXXXXXX..XXXXXXX 100644
280
--- a/block/qed.c
281
+++ b/block/qed.c
282
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
283
return -EIO;
284
}
285
286
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
287
+ blk = blk_new(bdrv_get_aio_context(bs),
288
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
289
ret = blk_insert_bs(blk, bs, errp);
290
if (ret < 0) {
291
goto out;
292
diff --git a/block/sheepdog.c b/block/sheepdog.c
293
index XXXXXXX..XXXXXXX 100644
294
--- a/block/sheepdog.c
295
+++ b/block/sheepdog.c
296
@@ -XXX,XX +XXX,XX @@ static int sd_prealloc(BlockDriverState *bs, int64_t old_size, int64_t new_size,
297
void *buf = NULL;
298
int ret;
299
300
- blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
301
+ blk = blk_new(bdrv_get_aio_context(bs),
302
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
303
BLK_PERM_ALL);
304
305
ret = blk_insert_bs(blk, bs, errp);
306
diff --git a/block/vdi.c b/block/vdi.c
307
index XXXXXXX..XXXXXXX 100644
308
--- a/block/vdi.c
309
+++ b/block/vdi.c
310
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
311
goto exit;
312
}
313
314
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
315
+ blk = blk_new(bdrv_get_aio_context(bs_file),
316
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
317
ret = blk_insert_bs(blk, bs_file, errp);
318
if (ret < 0) {
319
goto exit;
320
diff --git a/block/vhdx.c b/block/vhdx.c
321
index XXXXXXX..XXXXXXX 100644
322
--- a/block/vhdx.c
323
+++ b/block/vhdx.c
324
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
325
return -EIO;
326
}
327
328
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
329
+ blk = blk_new(bdrv_get_aio_context(bs),
330
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
331
ret = blk_insert_bs(blk, bs, errp);
332
if (ret < 0) {
333
goto delete_and_exit;
334
diff --git a/block/vmdk.c b/block/vmdk.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/block/vmdk.c
337
+++ b/block/vmdk.c
338
@@ -XXX,XX +XXX,XX @@ static BlockBackend *vmdk_co_create_cb(int64_t size, int idx,
339
if (!bs) {
340
return NULL;
341
}
342
- blk = blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
343
+ blk = blk_new(bdrv_get_aio_context(bs),
344
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_RESIZE,
345
BLK_PERM_ALL);
346
if (blk_insert_bs(blk, bs, errp)) {
347
bdrv_unref(bs);
348
diff --git a/block/vpc.c b/block/vpc.c
349
index XXXXXXX..XXXXXXX 100644
350
--- a/block/vpc.c
351
+++ b/block/vpc.c
352
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
353
return -EIO;
354
}
355
356
- blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
357
+ blk = blk_new(bdrv_get_aio_context(bs),
358
+ BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);
359
ret = blk_insert_bs(blk, bs, errp);
360
if (ret < 0) {
361
goto out;
362
diff --git a/blockdev.c b/blockdev.c
363
index XXXXXXX..XXXXXXX 100644
364
--- a/blockdev.c
365
+++ b/blockdev.c
366
@@ -XXX,XX +XXX,XX @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
367
if ((!file || !*file) && !qdict_size(bs_opts)) {
368
BlockBackendRootState *blk_rs;
369
370
- blk = blk_new(0, BLK_PERM_ALL);
371
+ blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
372
blk_rs = blk_get_root_state(blk);
373
blk_rs->open_flags = bdrv_flags;
374
blk_rs->read_only = read_only;
375
@@ -XXX,XX +XXX,XX @@ void qmp_block_resize(bool has_device, const char *device,
376
goto out;
377
}
378
379
- blk = blk_new(BLK_PERM_RESIZE, BLK_PERM_ALL);
380
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_RESIZE, BLK_PERM_ALL);
381
ret = blk_insert_bs(blk, bs, errp);
382
if (ret < 0) {
383
goto out;
384
diff --git a/blockjob.c b/blockjob.c
385
index XXXXXXX..XXXXXXX 100644
386
--- a/blockjob.c
387
+++ b/blockjob.c
388
@@ -XXX,XX +XXX,XX @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver,
389
job_id = bdrv_get_device_name(bs);
390
}
391
392
- blk = blk_new(perm, shared_perm);
393
+ blk = blk_new(bdrv_get_aio_context(bs), perm, shared_perm);
394
ret = blk_insert_bs(blk, bs, errp);
395
if (ret < 0) {
396
blk_unref(blk);
397
diff --git a/hmp.c b/hmp.c
398
index XXXXXXX..XXXXXXX 100644
399
--- a/hmp.c
400
+++ b/hmp.c
401
@@ -XXX,XX +XXX,XX @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict)
402
if (!blk) {
403
BlockDriverState *bs = bdrv_lookup_bs(NULL, device, &err);
404
if (bs) {
405
- blk = local_blk = blk_new(0, BLK_PERM_ALL);
406
+ blk = local_blk = blk_new(bdrv_get_aio_context(bs),
407
+ 0, BLK_PERM_ALL);
408
ret = blk_insert_bs(blk, bs, &err);
409
if (ret < 0) {
410
goto fail;
411
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
412
index XXXXXXX..XXXXXXX 100644
413
--- a/hw/block/fdc.c
414
+++ b/hw/block/fdc.c
415
@@ -XXX,XX +XXX,XX @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
416
417
if (!dev->conf.blk) {
418
/* Anonymous BlockBackend for an empty drive */
419
- dev->conf.blk = blk_new(0, BLK_PERM_ALL);
420
+ dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
421
ret = blk_attach_dev(dev->conf.blk, qdev);
422
assert(ret == 0);
423
}
424
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
425
index XXXXXXX..XXXXXXX 100644
426
--- a/hw/block/xen-block.c
427
+++ b/hw/block/xen-block.c
428
@@ -XXX,XX +XXX,XX @@ static void xen_cdrom_realize(XenBlockDevice *blockdev, Error **errp)
429
int rc;
430
431
/* Set up an empty drive */
432
- conf->blk = blk_new(0, BLK_PERM_ALL);
433
+ conf->blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
434
435
rc = blk_attach_dev(conf->blk, DEVICE(blockdev));
436
if (!rc) {
437
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
438
index XXXXXXX..XXXXXXX 100644
439
--- a/hw/core/qdev-properties-system.c
440
+++ b/hw/core/qdev-properties-system.c
441
@@ -XXX,XX +XXX,XX @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
442
if (!blk) {
443
BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
444
if (bs) {
445
- blk = blk_new(0, BLK_PERM_ALL);
446
+ /* BlockBackends of devices start in the main context and are only
447
+ * later moved into another context if the device supports that. */
448
+ blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
449
blk_created = true;
450
451
ret = blk_insert_bs(blk, bs, errp);
452
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
453
index XXXXXXX..XXXXXXX 100644
454
--- a/hw/ide/qdev.c
455
+++ b/hw/ide/qdev.c
456
@@ -XXX,XX +XXX,XX @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind, Error **errp)
457
return;
458
} else {
459
/* Anonymous BlockBackend for an empty drive */
460
- dev->conf.blk = blk_new(0, BLK_PERM_ALL);
461
+ dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
462
ret = blk_attach_dev(dev->conf.blk, &dev->qdev);
463
assert(ret == 0);
464
}
465
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
466
index XXXXXXX..XXXXXXX 100644
467
--- a/hw/scsi/scsi-disk.c
468
+++ b/hw/scsi/scsi-disk.c
469
@@ -XXX,XX +XXX,XX @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp)
470
if (!dev->conf.blk) {
471
/* Anonymous BlockBackend for an empty drive. As we put it into
472
* dev->conf, qdev takes care of detaching on unplug. */
473
- dev->conf.blk = blk_new(0, BLK_PERM_ALL);
474
+ dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
475
ret = blk_attach_dev(dev->conf.blk, &dev->qdev);
476
assert(ret == 0);
477
}
478
diff --git a/migration/block.c b/migration/block.c
479
index XXXXXXX..XXXXXXX 100644
480
--- a/migration/block.c
481
+++ b/migration/block.c
482
@@ -XXX,XX +XXX,XX @@ static int init_blk_migration(QEMUFile *f)
483
}
484
485
bmds = g_new0(BlkMigDevState, 1);
486
- bmds->blk = blk_new(BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
487
+ bmds->blk = blk_new(qemu_get_aio_context(),
488
+ BLK_PERM_CONSISTENT_READ, BLK_PERM_ALL);
489
bmds->blk_name = g_strdup(bdrv_get_device_name(bs));
490
bmds->bulk_completed = 0;
491
bmds->total_sectors = sectors;
492
diff --git a/nbd/server.c b/nbd/server.c
493
index XXXXXXX..XXXXXXX 100644
494
--- a/nbd/server.c
495
+++ b/nbd/server.c
496
@@ -XXX,XX +XXX,XX @@ NBDExport *nbd_export_new(BlockDriverState *bs, uint64_t dev_offset,
497
if ((nbdflags & NBD_FLAG_READ_ONLY) == 0) {
498
perm |= BLK_PERM_WRITE;
499
}
500
- blk = blk_new(perm, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
501
- BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
502
+ blk = blk_new(bdrv_get_aio_context(bs), perm,
503
+ BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED |
504
+ BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD);
505
ret = blk_insert_bs(blk, bs, errp);
506
if (ret < 0) {
507
goto fail;
508
diff --git a/qemu-img.c b/qemu-img.c
509
index XXXXXXX..XXXXXXX 100644
510
--- a/qemu-img.c
511
+++ b/qemu-img.c
512
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
513
BlockDriverState *base_bs = backing_bs(bs);
514
515
if (base_bs) {
516
- blk_old_backing = blk_new(BLK_PERM_CONSISTENT_READ,
517
+ blk_old_backing = blk_new(qemu_get_aio_context(),
518
+ BLK_PERM_CONSISTENT_READ,
519
BLK_PERM_ALL);
520
ret = blk_insert_bs(blk_old_backing, base_bs,
521
&local_err);
522
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
523
prefix_chain_bs = bdrv_find_backing_image(bs, out_real_path);
524
if (prefix_chain_bs) {
525
g_free(out_real_path);
526
- blk_new_backing = blk_new(BLK_PERM_CONSISTENT_READ,
527
+ blk_new_backing = blk_new(qemu_get_aio_context(),
528
+ BLK_PERM_CONSISTENT_READ,
529
BLK_PERM_ALL);
530
ret = blk_insert_bs(blk_new_backing, prefix_chain_bs,
531
&local_err);
532
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
533
index XXXXXXX..XXXXXXX 100644
534
--- a/tests/test-bdrv-drain.c
535
+++ b/tests/test-bdrv-drain.c
536
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_common(enum drain_type drain_type, bool recursive)
537
538
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
539
540
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
541
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
542
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
543
&error_abort);
544
s = bs->opaque;
545
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_common(enum drain_type drain_type, bool recursive)
546
BlockBackend *blk;
547
BlockDriverState *bs, *backing;
548
549
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
550
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
551
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
552
&error_abort);
553
blk_insert_bs(blk, bs, &error_abort);
554
@@ -XXX,XX +XXX,XX @@ static void test_nested(void)
555
BDRVTestState *s, *backing_s;
556
enum drain_type outer, inner;
557
558
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
559
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
560
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
561
&error_abort);
562
s = bs->opaque;
563
@@ -XXX,XX +XXX,XX @@ static void test_multiparent(void)
564
BlockDriverState *bs_a, *bs_b, *backing;
565
BDRVTestState *a_s, *b_s, *backing_s;
566
567
- blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
568
+ blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
569
bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
570
&error_abort);
571
a_s = bs_a->opaque;
572
blk_insert_bs(blk_a, bs_a, &error_abort);
573
574
- blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
575
+ blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
576
bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
577
&error_abort);
578
b_s = bs_b->opaque;
579
@@ -XXX,XX +XXX,XX @@ static void test_graph_change_drain_subtree(void)
580
BlockDriverState *bs_a, *bs_b, *backing;
581
BDRVTestState *a_s, *b_s, *backing_s;
582
583
- blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
584
+ blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
585
bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
586
&error_abort);
587
a_s = bs_a->opaque;
588
blk_insert_bs(blk_a, bs_a, &error_abort);
589
590
- blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
591
+ blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
592
bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
593
&error_abort);
594
b_s = bs_b->opaque;
595
@@ -XXX,XX +XXX,XX @@ static void test_graph_change_drain_all(void)
596
BDRVTestState *a_s, *b_s;
597
598
/* Create node A with a BlockBackend */
599
- blk_a = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
600
+ blk_a = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
601
bs_a = bdrv_new_open_driver(&bdrv_test, "test-node-a", BDRV_O_RDWR,
602
&error_abort);
603
a_s = bs_a->opaque;
604
@@ -XXX,XX +XXX,XX @@ static void test_graph_change_drain_all(void)
605
g_assert_cmpint(a_s->drain_count, ==, 1);
606
607
/* Create node B with a BlockBackend */
608
- blk_b = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
609
+ blk_b = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
610
bs_b = bdrv_new_open_driver(&bdrv_test, "test-node-b", BDRV_O_RDWR,
611
&error_abort);
612
b_s = bs_b->opaque;
613
@@ -XXX,XX +XXX,XX @@ static void test_iothread_common(enum drain_type drain_type, int drain_thread)
614
goto out;
615
}
616
617
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
618
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
619
bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
620
&error_abort);
621
s = bs->opaque;
622
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
623
bdrv_set_backing_hd(src, src_backing, &error_abort);
624
bdrv_unref(src_backing);
625
626
- blk_src = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
627
+ blk_src = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
628
blk_insert_bs(blk_src, src_overlay, &error_abort);
629
630
switch (drain_node) {
631
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
632
633
target = bdrv_new_open_driver(&bdrv_test, "target", BDRV_O_RDWR,
634
&error_abort);
635
- blk_target = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
636
+ blk_target = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
637
blk_insert_bs(blk_target, target, &error_abort);
638
639
aio_context_acquire(ctx);
640
@@ -XXX,XX +XXX,XX @@ static void do_test_delete_by_drain(bool detach_instead_of_delete,
641
&error_abort);
642
bdrv_attach_child(bs, null_bs, "null-child", &child_file, &error_abort);
643
644
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
645
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
646
blk_insert_bs(blk, bs, &error_abort);
647
648
/* Referenced by blk now */
649
@@ -XXX,XX +XXX,XX @@ static void test_detach_indirect(bool by_parent_cb)
650
c = bdrv_new_open_driver(&bdrv_test, "c", BDRV_O_RDWR, &error_abort);
651
652
/* blk is a BB for parent-a */
653
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
654
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
655
blk_insert_bs(blk, parent_a, &error_abort);
656
bdrv_unref(parent_a);
657
658
@@ -XXX,XX +XXX,XX @@ static void test_append_to_drained(void)
659
BlockDriverState *base, *overlay;
660
BDRVTestState *base_s, *overlay_s;
661
662
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
663
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
664
base = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
665
base_s = base->opaque;
666
blk_insert_bs(blk, base, &error_abort);
667
diff --git a/tests/test-bdrv-graph-mod.c b/tests/test-bdrv-graph-mod.c
668
index XXXXXXX..XXXXXXX 100644
669
--- a/tests/test-bdrv-graph-mod.c
670
+++ b/tests/test-bdrv-graph-mod.c
671
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
672
{
673
Error *local_err = NULL;
674
675
- BlockBackend *root = blk_new(BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
676
+ BlockBackend *root = blk_new(qemu_get_aio_context(),
677
+ BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ,
678
BLK_PERM_ALL & ~BLK_PERM_WRITE);
679
BlockDriverState *bs = no_perm_node("node");
680
BlockDriverState *filter = pass_through_node("filter");
681
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
682
*/
683
static void test_should_update_child(void)
684
{
685
- BlockBackend *root = blk_new(0, BLK_PERM_ALL);
686
+ BlockBackend *root = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
687
BlockDriverState *bs = no_perm_node("node");
688
BlockDriverState *filter = no_perm_node("filter");
689
BlockDriverState *target = no_perm_node("target");
690
diff --git a/tests/test-block-backend.c b/tests/test-block-backend.c
691
index XXXXXXX..XXXXXXX 100644
692
--- a/tests/test-block-backend.c
693
+++ b/tests/test-block-backend.c
694
@@ -XXX,XX +XXX,XX @@ static void test_drain_aio_error_flush_cb(void *opaque, int ret)
695
696
static void test_drain_aio_error(void)
697
{
698
- BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
699
+ BlockBackend *blk = blk_new(qemu_get_aio_context(),
700
+ BLK_PERM_ALL, BLK_PERM_ALL);
701
BlockAIOCB *acb;
702
bool completed = false;
703
704
@@ -XXX,XX +XXX,XX @@ static void test_drain_aio_error(void)
705
706
static void test_drain_all_aio_error(void)
707
{
708
- BlockBackend *blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
709
+ BlockBackend *blk = blk_new(qemu_get_aio_context(),
710
+ BLK_PERM_ALL, BLK_PERM_ALL);
711
BlockAIOCB *acb;
712
bool completed = false;
713
714
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
715
index XXXXXXX..XXXXXXX 100644
716
--- a/tests/test-block-iothread.c
717
+++ b/tests/test-block-iothread.c
718
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
719
BlockDriverState *bs;
720
BdrvChild *c;
721
722
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
723
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
724
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
725
bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
726
blk_insert_bs(blk, bs, &error_abort);
727
@@ -XXX,XX +XXX,XX @@ static void test_attach_blockjob(void)
728
BlockDriverState *bs;
729
TestBlockJob *tjob;
730
731
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
732
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
733
bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
734
blk_insert_bs(blk, bs, &error_abort);
735
736
@@ -XXX,XX +XXX,XX @@ static void test_propagate_basic(void)
737
QDict *options;
738
739
/* Create bs_a and its BlockBackend */
740
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
741
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
742
bs_a = bdrv_new_open_driver(&bdrv_test, "bs_a", BDRV_O_RDWR, &error_abort);
743
blk_insert_bs(blk, bs_a, &error_abort);
744
745
@@ -XXX,XX +XXX,XX @@ static void test_propagate_diamond(void)
746
qdict_put_str(options, "raw", "bs_c");
747
748
bs_verify = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
749
- blk = blk_new(BLK_PERM_ALL, BLK_PERM_ALL);
750
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
751
blk_insert_bs(blk, bs_verify, &error_abort);
752
753
/* Switch the AioContext */
754
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
755
g_assert(bdrv_get_aio_context(filter) == main_ctx);
756
757
/* With a BlockBackend on src, changing target must fail */
758
- blk = blk_new(0, BLK_PERM_ALL);
759
+ blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
760
blk_insert_bs(blk, src, &error_abort);
761
762
bdrv_try_set_aio_context(target, ctx, &local_err);
763
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
764
index XXXXXXX..XXXXXXX 100644
765
--- a/tests/test-blockjob.c
766
+++ b/tests/test-blockjob.c
767
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_test_id(BlockBackend *blk, const char *id,
768
static BlockBackend *create_blk(const char *name)
769
{
770
/* No I/O is performed on this device */
771
- BlockBackend *blk = blk_new(0, BLK_PERM_ALL);
772
+ BlockBackend *blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
773
BlockDriverState *bs;
774
775
bs = bdrv_open("null-co://", NULL, NULL, 0, &error_abort);
776
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
777
index XXXXXXX..XXXXXXX 100644
778
--- a/tests/test-throttle.c
779
+++ b/tests/test-throttle.c
780
@@ -XXX,XX +XXX,XX @@ static void test_groups(void)
781
ThrottleGroupMember *tgm1, *tgm2, *tgm3;
782
783
/* No actual I/O is performed on these devices */
784
- blk1 = blk_new(0, BLK_PERM_ALL);
785
- blk2 = blk_new(0, BLK_PERM_ALL);
786
- blk3 = blk_new(0, BLK_PERM_ALL);
787
+ blk1 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
788
+ blk2 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
789
+ blk3 = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
790
791
blkp1 = blk_get_public(blk1);
792
blkp2 = blk_get_public(blk2);
793
--
794
2.20.1
795
796
diff view generated by jsdifflib
Deleted patch
1
Some qdev block devices have support for iothreads and take care of the
2
AioContext they are running in, but most devices don't know about any of
3
this. For the latter category, the qdev drive property must make sure
4
that their BlockBackend is in the main AioContext.
5
1
6
Unfortunately, while the current code just does the same thing for
7
devices that do support iothreads, this is not correct and it would show
8
as soon as we actually try to keep a consistent AioContext assignment
9
across all nodes and users of a block graph subtree: If a node is
10
already in a non-default AioContext because of one of its users,
11
attaching a new device should still be possible if that device can work
12
in the same AioContext. Switching the node back to the main context
13
first and only then into the device AioContext causes failure (because
14
the existing user wouldn't allow the switch to the main context).
15
16
So devices that support iothreads need a different kind of drive
17
property that leaves the node in its current AioContext, but by using
18
this type, the device promises to check later that it can work with this
19
context.
20
21
This patch adds the qdev infrastructure that allows devices to signal
22
that they handle iothreads and qdev should leave the AioContext alone.
23
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
26
include/hw/block/block.h | 7 ++++--
27
include/hw/qdev-properties.h | 3 +++
28
hw/core/qdev-properties-system.c | 43 ++++++++++++++++++++++++++++----
29
3 files changed, 46 insertions(+), 7 deletions(-)
30
31
diff --git a/include/hw/block/block.h b/include/hw/block/block.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/block/block.h
34
+++ b/include/hw/block/block.h
35
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
36
return exp;
37
}
38
39
-#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
40
- DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
41
+#define DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf) \
42
DEFINE_PROP_BLOCKSIZE("logical_block_size", _state, \
43
_conf.logical_block_size), \
44
DEFINE_PROP_BLOCKSIZE("physical_block_size", _state, \
45
@@ -XXX,XX +XXX,XX @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
46
ON_OFF_AUTO_AUTO), \
47
DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false)
48
49
+#define DEFINE_BLOCK_PROPERTIES(_state, _conf) \
50
+ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \
51
+ DEFINE_BLOCK_PROPERTIES_BASE(_state, _conf)
52
+
53
#define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf) \
54
DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0), \
55
DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
56
diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
57
index XXXXXXX..XXXXXXX 100644
58
--- a/include/hw/qdev-properties.h
59
+++ b/include/hw/qdev-properties.h
60
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_blockdev_on_error;
61
extern const PropertyInfo qdev_prop_bios_chs_trans;
62
extern const PropertyInfo qdev_prop_fdc_drive_type;
63
extern const PropertyInfo qdev_prop_drive;
64
+extern const PropertyInfo qdev_prop_drive_iothread;
65
extern const PropertyInfo qdev_prop_netdev;
66
extern const PropertyInfo qdev_prop_pci_devfn;
67
extern const PropertyInfo qdev_prop_blocksize;
68
@@ -XXX,XX +XXX,XX @@ extern const PropertyInfo qdev_prop_pcie_link_width;
69
DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers)
70
#define DEFINE_PROP_DRIVE(_n, _s, _f) \
71
DEFINE_PROP(_n, _s, _f, qdev_prop_drive, BlockBackend *)
72
+#define DEFINE_PROP_DRIVE_IOTHREAD(_n, _s, _f) \
73
+ DEFINE_PROP(_n, _s, _f, qdev_prop_drive_iothread, BlockBackend *)
74
#define DEFINE_PROP_MACADDR(_n, _s, _f) \
75
DEFINE_PROP(_n, _s, _f, qdev_prop_macaddr, MACAddr)
76
#define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \
77
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/core/qdev-properties-system.c
80
+++ b/hw/core/qdev-properties-system.c
81
@@ -XXX,XX +XXX,XX @@ static void set_pointer(Object *obj, Visitor *v, Property *prop,
82
83
/* --- drive --- */
84
85
-static void parse_drive(DeviceState *dev, const char *str, void **ptr,
86
- const char *propname, Error **errp)
87
+static void do_parse_drive(DeviceState *dev, const char *str, void **ptr,
88
+ const char *propname, bool iothread, Error **errp)
89
{
90
BlockBackend *blk;
91
bool blk_created = false;
92
@@ -XXX,XX +XXX,XX @@ static void parse_drive(DeviceState *dev, const char *str, void **ptr,
93
if (!blk) {
94
BlockDriverState *bs = bdrv_lookup_bs(NULL, str, NULL);
95
if (bs) {
96
- /* BlockBackends of devices start in the main context and are only
97
- * later moved into another context if the device supports that. */
98
- blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
99
+ /*
100
+ * If the device supports iothreads, it will make sure to move the
101
+ * block node to the right AioContext if necessary (or fail if this
102
+ * isn't possible because of other users). Devices that are not
103
+ * aware of iothreads require their BlockBackends to be in the main
104
+ * AioContext.
105
+ */
106
+ AioContext *ctx = iothread ? bdrv_get_aio_context(bs) :
107
+ qemu_get_aio_context();
108
+ blk = blk_new(ctx, 0, BLK_PERM_ALL);
109
blk_created = true;
110
111
ret = blk_insert_bs(blk, bs, errp);
112
@@ -XXX,XX +XXX,XX @@ fail:
113
}
114
}
115
116
+static void parse_drive(DeviceState *dev, const char *str, void **ptr,
117
+ const char *propname, Error **errp)
118
+{
119
+ do_parse_drive(dev, str, ptr, propname, false, errp);
120
+}
121
+
122
+static void parse_drive_iothread(DeviceState *dev, const char *str, void **ptr,
123
+ const char *propname, Error **errp)
124
+{
125
+ do_parse_drive(dev, str, ptr, propname, true, errp);
126
+}
127
+
128
static void release_drive(Object *obj, const char *name, void *opaque)
129
{
130
DeviceState *dev = DEVICE(obj);
131
@@ -XXX,XX +XXX,XX @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
132
set_pointer(obj, v, opaque, parse_drive, name, errp);
133
}
134
135
+static void set_drive_iothread(Object *obj, Visitor *v, const char *name,
136
+ void *opaque, Error **errp)
137
+{
138
+ set_pointer(obj, v, opaque, parse_drive_iothread, name, errp);
139
+}
140
+
141
const PropertyInfo qdev_prop_drive = {
142
.name = "str",
143
.description = "Node name or ID of a block device to use as a backend",
144
@@ -XXX,XX +XXX,XX @@ const PropertyInfo qdev_prop_drive = {
145
.release = release_drive,
146
};
147
148
+const PropertyInfo qdev_prop_drive_iothread = {
149
+ .name = "str",
150
+ .description = "Node name or ID of a block device to use as a backend",
151
+ .get = get_drive,
152
+ .set = set_drive_iothread,
153
+ .release = release_drive,
154
+};
155
+
156
/* --- character device --- */
157
158
static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
159
--
160
2.20.1
161
162
diff view generated by jsdifflib
Deleted patch
1
This makes use of qdev_prop_drive_iothread for scsi-disk so that the
2
disk can be attached to a node that is already in the target AioContext.
3
We need to check that the HBA actually supports iothreads, otherwise
4
scsi-disk must make sure that the node is already in the main
5
AioContext.
6
1
7
This changes the error message for conflicting iothread settings.
8
Previously, virtio-scsi produced the error message, now it comes from
9
blk_set_aio_context(). Update a test case accordingly.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
include/hw/scsi/scsi.h | 1 +
14
hw/scsi/scsi-disk.c | 22 +++++++++++++++-------
15
hw/scsi/virtio-scsi.c | 15 ++++++++-------
16
tests/qemu-iotests/240.out | 2 +-
17
4 files changed, 25 insertions(+), 15 deletions(-)
18
19
diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/scsi/scsi.h
22
+++ b/include/hw/scsi/scsi.h
23
@@ -XXX,XX +XXX,XX @@ struct SCSIDevice
24
int scsi_version;
25
int default_scsi_version;
26
bool needs_vpd_bl_emulation;
27
+ bool hba_supports_iothread;
28
};
29
30
extern const VMStateDescription vmstate_scsi_device;
31
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/scsi/scsi-disk.c
34
+++ b/hw/scsi/scsi-disk.c
35
@@ -XXX,XX +XXX,XX @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
36
return;
37
}
38
39
+ if (blk_get_aio_context(s->qdev.conf.blk) != qemu_get_aio_context() &&
40
+ !s->qdev.hba_supports_iothread)
41
+ {
42
+ error_setg(errp, "HBA does not support iothreads");
43
+ return;
44
+ }
45
+
46
if (dev->type == TYPE_DISK) {
47
if (!blkconf_geometry(&dev->conf, NULL, 65535, 255, 255, errp)) {
48
return;
49
@@ -XXX,XX +XXX,XX @@ static const TypeInfo scsi_disk_base_info = {
50
.abstract = true,
51
};
52
53
-#define DEFINE_SCSI_DISK_PROPERTIES() \
54
- DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \
55
- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
56
- DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
57
- DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
58
- DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
59
- DEFINE_PROP_STRING("product", SCSIDiskState, product), \
60
+#define DEFINE_SCSI_DISK_PROPERTIES() \
61
+ DEFINE_PROP_DRIVE_IOTHREAD("drive", SCSIDiskState, qdev.conf.blk), \
62
+ DEFINE_BLOCK_PROPERTIES_BASE(SCSIDiskState, qdev.conf), \
63
+ DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
64
+ DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
65
+ DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
66
+ DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
67
+ DEFINE_PROP_STRING("product", SCSIDiskState, product), \
68
DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id)
69
70
71
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/scsi/virtio-scsi.c
74
+++ b/hw/scsi/virtio-scsi.c
75
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
76
}
77
}
78
79
+static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev,
80
+ DeviceState *dev, Error **errp)
81
+{
82
+ SCSIDevice *sd = SCSI_DEVICE(dev);
83
+ sd->hba_supports_iothread = true;
84
+}
85
+
86
static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
87
Error **errp)
88
{
89
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
90
int ret;
91
92
if (s->ctx && !s->dataplane_fenced) {
93
- AioContext *ctx;
94
if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
95
return;
96
}
97
- ctx = blk_get_aio_context(sd->conf.blk);
98
- if (ctx != s->ctx && ctx != qemu_get_aio_context()) {
99
- error_setg(errp, "Cannot attach a blockdev that is using "
100
- "a different iothread");
101
- return;
102
- }
103
virtio_scsi_acquire(s);
104
ret = blk_set_aio_context(sd->conf.blk, s->ctx, errp);
105
virtio_scsi_release(s);
106
@@ -XXX,XX +XXX,XX @@ static void virtio_scsi_class_init(ObjectClass *klass, void *data)
107
vdc->reset = virtio_scsi_reset;
108
vdc->start_ioeventfd = virtio_scsi_dataplane_start;
109
vdc->stop_ioeventfd = virtio_scsi_dataplane_stop;
110
+ hc->pre_plug = virtio_scsi_pre_hotplug;
111
hc->plug = virtio_scsi_hotplug;
112
hc->unplug = virtio_scsi_hotunplug;
113
}
114
diff --git a/tests/qemu-iotests/240.out b/tests/qemu-iotests/240.out
115
index XXXXXXX..XXXXXXX 100644
116
--- a/tests/qemu-iotests/240.out
117
+++ b/tests/qemu-iotests/240.out
118
@@ -XXX,XX +XXX,XX @@ QMP_VERSION
119
{"return": {}}
120
{"return": {}}
121
{"return": {}}
122
-{"error": {"class": "GenericError", "desc": "Cannot attach a blockdev that is using a different iothread"}}
123
+{"error": {"class": "GenericError", "desc": "Cannot change iothread of active block backend"}}
124
{"return": {}}
125
{"return": {}}
126
{"return": {}}
127
--
128
2.20.1
129
130
diff view generated by jsdifflib
Deleted patch
1
So far, we only made sure that updating the AioContext of a node
2
affected the whole subtree. However, if a node is newly attached to a
3
new parent, we also need to make sure that both the subtree of the node
4
and the parent are in the same AioContext. This tries to move the new
5
child node to the parent AioContext and returns an error if this isn't
6
possible.
7
1
8
BlockBackends now actually apply their AioContext to their root node.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block_int.h | 1 +
13
block.c | 35 ++++++++++++++++++++++++++++++++++-
14
block/block-backend.c | 9 ++++-----
15
blockjob.c | 10 ++++++++--
16
tests/test-bdrv-drain.c | 6 ++++--
17
5 files changed, 51 insertions(+), 10 deletions(-)
18
19
diff --git a/include/block/block_int.h b/include/block/block_int.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block_int.h
22
+++ b/include/block/block_int.h
23
@@ -XXX,XX +XXX,XX @@ void hmp_drive_add_node(Monitor *mon, const char *optstr);
24
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
25
const char *child_name,
26
const BdrvChildRole *child_role,
27
+ AioContext *ctx,
28
uint64_t perm, uint64_t shared_perm,
29
void *opaque, Error **errp);
30
void bdrv_root_unref_child(BdrvChild *child);
31
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block.c
34
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
36
*
37
* On failure NULL is returned, errp is set and the reference to
38
* child_bs is also dropped.
39
+ *
40
+ * The caller must hold the AioContext lock @child_bs, but not that of @ctx
41
+ * (unless @child_bs is already in @ctx).
42
*/
43
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
44
const char *child_name,
45
const BdrvChildRole *child_role,
46
+ AioContext *ctx,
47
uint64_t perm, uint64_t shared_perm,
48
void *opaque, Error **errp)
49
{
50
BdrvChild *child;
51
+ Error *local_err = NULL;
52
int ret;
53
54
ret = bdrv_check_update_perm(child_bs, NULL, perm, shared_perm, NULL, errp);
55
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
56
.opaque = opaque,
57
};
58
59
+ /* If the AioContexts don't match, first try to move the subtree of
60
+ * child_bs into the AioContext of the new parent. If this doesn't work,
61
+ * try moving the parent into the AioContext of child_bs instead. */
62
+ if (bdrv_get_aio_context(child_bs) != ctx) {
63
+ ret = bdrv_try_set_aio_context(child_bs, ctx, &local_err);
64
+ if (ret < 0 && child_role->can_set_aio_ctx) {
65
+ GSList *ignore = g_slist_prepend(NULL, child);;
66
+ ctx = bdrv_get_aio_context(child_bs);
67
+ if (child_role->can_set_aio_ctx(child, ctx, &ignore, NULL)) {
68
+ error_free(local_err);
69
+ ret = 0;
70
+ g_slist_free(ignore);
71
+ ignore = g_slist_prepend(NULL, child);;
72
+ child_role->set_aio_ctx(child, ctx, &ignore);
73
+ }
74
+ g_slist_free(ignore);
75
+ }
76
+ if (ret < 0) {
77
+ error_propagate(errp, local_err);
78
+ g_free(child);
79
+ bdrv_abort_perm_update(child_bs);
80
+ return NULL;
81
+ }
82
+ }
83
+
84
/* This performs the matching bdrv_set_perm() for the above check. */
85
bdrv_replace_child(child, child_bs);
86
87
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
88
*
89
* On failure NULL is returned, errp is set and the reference to
90
* child_bs is also dropped.
91
+ *
92
+ * If @parent_bs and @child_bs are in different AioContexts, the caller must
93
+ * hold the AioContext lock for @child_bs, but not for @parent_bs.
94
*/
95
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
96
BlockDriverState *child_bs,
97
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
98
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
99
100
assert(parent_bs->drv);
101
- assert(bdrv_get_aio_context(parent_bs) == bdrv_get_aio_context(child_bs));
102
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
103
perm, shared_perm, &perm, &shared_perm);
104
105
child = bdrv_root_attach_child(child_bs, child_name, child_role,
106
+ bdrv_get_aio_context(parent_bs),
107
perm, shared_perm, parent_bs, errp);
108
if (child == NULL) {
109
return NULL;
110
diff --git a/block/block-backend.c b/block/block-backend.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/block/block-backend.c
113
+++ b/block/block-backend.c
114
@@ -XXX,XX +XXX,XX @@ BlockBackend *blk_new_open(const char *filename, const char *reference,
115
return NULL;
116
}
117
118
- blk->root = bdrv_root_attach_child(bs, "root", &child_root,
119
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
120
perm, BLK_PERM_ALL, blk, errp);
121
if (!blk->root) {
122
blk_unref(blk);
123
@@ -XXX,XX +XXX,XX @@ int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
124
{
125
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
126
bdrv_ref(bs);
127
- blk->root = bdrv_root_attach_child(bs, "root", &child_root,
128
+ blk->root = bdrv_root_attach_child(bs, "root", &child_root, blk->ctx,
129
blk->perm, blk->shared_perm, blk, errp);
130
if (blk->root == NULL) {
131
return -EPERM;
132
@@ -XXX,XX +XXX,XX @@ AioContext *blk_get_aio_context(BlockBackend *blk)
133
{
134
BlockDriverState *bs = blk_bs(blk);
135
136
- /* FIXME The AioContext of bs and blk can be inconsistent. For the moment,
137
- * we prefer the one of bs for compatibility. */
138
if (bs) {
139
- return bdrv_get_aio_context(blk_bs(blk));
140
+ AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
141
+ assert(ctx == blk->ctx);
142
}
143
144
return blk->ctx;
145
diff --git a/blockjob.c b/blockjob.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/blockjob.c
148
+++ b/blockjob.c
149
@@ -XXX,XX +XXX,XX @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs,
150
BdrvChild *c;
151
152
bdrv_ref(bs);
153
- c = bdrv_root_attach_child(bs, name, &child_job, perm, shared_perm,
154
- job, errp);
155
+ if (job->job.aio_context != qemu_get_aio_context()) {
156
+ aio_context_release(job->job.aio_context);
157
+ }
158
+ c = bdrv_root_attach_child(bs, name, &child_job, job->job.aio_context,
159
+ perm, shared_perm, job, errp);
160
+ if (job->job.aio_context != qemu_get_aio_context()) {
161
+ aio_context_acquire(job->job.aio_context);
162
+ }
163
if (c == NULL) {
164
return -EPERM;
165
}
166
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/tests/test-bdrv-drain.c
169
+++ b/tests/test-bdrv-drain.c
170
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
171
&error_abort);
172
blk_target = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
173
blk_insert_bs(blk_target, target, &error_abort);
174
+ blk_set_allow_aio_context_change(blk_target, true);
175
176
aio_context_acquire(ctx);
177
tjob = block_job_create("job0", &test_job_driver, NULL, src,
178
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
179
g_assert_false(job->job.paused);
180
g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */
181
182
- do_drain_begin(drain_type, target);
183
+ do_drain_begin_unlocked(drain_type, target);
184
185
if (drain_type == BDRV_DRAIN_ALL) {
186
/* bdrv_drain_all() drains both src and target */
187
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
188
g_assert_true(job->job.paused);
189
g_assert_false(job->job.busy); /* The job is paused */
190
191
- do_drain_end(drain_type, target);
192
+ do_drain_end_unlocked(drain_type, target);
193
194
if (use_iothread) {
195
/* paused is reset in the I/O thread, wait for it */
196
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
197
198
if (use_iothread) {
199
blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort);
200
+ blk_set_aio_context(blk_target, qemu_get_aio_context(), &error_abort);
201
}
202
aio_context_release(ctx);
203
204
--
205
2.20.1
206
207
diff view generated by jsdifflib
Deleted patch
1
Opening a new parent node for a node that has already been moved into a
2
different AioContext must cause the new parent to move into the same
3
context.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/test-block-iothread.c | 33 +++++++++++++++++++++++++++++++++
8
1 file changed, 33 insertions(+)
9
10
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/test-block-iothread.c
13
+++ b/tests/test-block-iothread.c
14
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
15
bdrv_unref(target);
16
}
17
18
+static void test_attach_second_node(void)
19
+{
20
+ IOThread *iothread = iothread_new();
21
+ AioContext *ctx = iothread_get_aio_context(iothread);
22
+ AioContext *main_ctx = qemu_get_aio_context();
23
+ BlockBackend *blk;
24
+ BlockDriverState *bs, *filter;
25
+ QDict *options;
26
+
27
+ blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
28
+ bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
29
+ blk_insert_bs(blk, bs, &error_abort);
30
+
31
+ options = qdict_new();
32
+ qdict_put_str(options, "driver", "raw");
33
+ qdict_put_str(options, "file", "base");
34
+
35
+ filter = bdrv_open(NULL, NULL, options, BDRV_O_RDWR, &error_abort);
36
+ g_assert(blk_get_aio_context(blk) == ctx);
37
+ g_assert(bdrv_get_aio_context(bs) == ctx);
38
+ g_assert(bdrv_get_aio_context(filter) == ctx);
39
+
40
+ blk_set_aio_context(blk, main_ctx, &error_abort);
41
+ g_assert(blk_get_aio_context(blk) == main_ctx);
42
+ g_assert(bdrv_get_aio_context(bs) == main_ctx);
43
+ g_assert(bdrv_get_aio_context(filter) == main_ctx);
44
+
45
+ bdrv_unref(filter);
46
+ bdrv_unref(bs);
47
+ blk_unref(blk);
48
+}
49
+
50
int main(int argc, char **argv)
51
{
52
int i;
53
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
54
}
55
56
g_test_add_func("/attach/blockjob", test_attach_blockjob);
57
+ g_test_add_func("/attach/second_node", test_attach_second_node);
58
g_test_add_func("/propagate/basic", test_propagate_basic);
59
g_test_add_func("/propagate/diamond", test_propagate_diamond);
60
g_test_add_func("/propagate/mirror", test_propagate_mirror);
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
Test that BlockBackends preserve their assigned AioContext even when the
2
root node goes away. Inserting a new root node will move it to the right
3
AioContext.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/test-block-iothread.c | 33 +++++++++++++++++++++++++++++++++
8
1 file changed, 33 insertions(+)
9
10
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/tests/test-block-iothread.c
13
+++ b/tests/test-block-iothread.c
14
@@ -XXX,XX +XXX,XX @@ static void test_attach_second_node(void)
15
blk_unref(blk);
16
}
17
18
+static void test_attach_preserve_blk_ctx(void)
19
+{
20
+ IOThread *iothread = iothread_new();
21
+ AioContext *ctx = iothread_get_aio_context(iothread);
22
+ BlockBackend *blk;
23
+ BlockDriverState *bs;
24
+
25
+ blk = blk_new(ctx, BLK_PERM_ALL, BLK_PERM_ALL);
26
+ bs = bdrv_new_open_driver(&bdrv_test, "base", BDRV_O_RDWR, &error_abort);
27
+ bs->total_sectors = 65536 / BDRV_SECTOR_SIZE;
28
+
29
+ /* Add node to BlockBackend that has an iothread context assigned */
30
+ blk_insert_bs(blk, bs, &error_abort);
31
+ g_assert(blk_get_aio_context(blk) == ctx);
32
+ g_assert(bdrv_get_aio_context(bs) == ctx);
33
+
34
+ /* Remove the node again */
35
+ blk_remove_bs(blk);
36
+ /* TODO bs should move back to main context here */
37
+ g_assert(blk_get_aio_context(blk) == ctx);
38
+ g_assert(bdrv_get_aio_context(bs) == ctx);
39
+
40
+ /* Re-attach the node */
41
+ blk_insert_bs(blk, bs, &error_abort);
42
+ g_assert(blk_get_aio_context(blk) == ctx);
43
+ g_assert(bdrv_get_aio_context(bs) == ctx);
44
+
45
+ blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort);
46
+ bdrv_unref(bs);
47
+ blk_unref(blk);
48
+}
49
+
50
int main(int argc, char **argv)
51
{
52
int i;
53
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
54
55
g_test_add_func("/attach/blockjob", test_attach_blockjob);
56
g_test_add_func("/attach/second_node", test_attach_second_node);
57
+ g_test_add_func("/attach/preserve_blk_ctx", test_attach_preserve_blk_ctx);
58
g_test_add_func("/propagate/basic", test_propagate_basic);
59
g_test_add_func("/propagate/diamond", test_propagate_diamond);
60
g_test_add_func("/propagate/mirror", test_propagate_mirror);
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
Deleted patch
1
A node should only be in a non-default AioContext if a user is attached
2
to it that requires this. When the last parent of a node is gone, it can
3
move back to the main AioContext.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
block.c | 4 ++++
8
tests/test-bdrv-drain.c | 2 +-
9
tests/test-block-iothread.c | 3 +--
10
3 files changed, 6 insertions(+), 3 deletions(-)
11
12
diff --git a/block.c b/block.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block.c
15
+++ b/block.c
16
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child(BdrvChild *child, BlockDriverState *new_bs)
17
bdrv_get_cumulative_perm(old_bs, &perm, &shared_perm);
18
bdrv_check_perm(old_bs, NULL, perm, shared_perm, NULL, &error_abort);
19
bdrv_set_perm(old_bs, perm, shared_perm);
20
+
21
+ /* When the parent requiring a non-default AioContext is removed, the
22
+ * node moves back to the main AioContext */
23
+ bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
24
}
25
26
if (new_bs) {
27
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/tests/test-bdrv-drain.c
30
+++ b/tests/test-bdrv-drain.c
31
@@ -XXX,XX +XXX,XX @@ static void test_blockjob_common_drain_node(enum drain_type drain_type,
32
33
if (use_iothread) {
34
blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort);
35
- blk_set_aio_context(blk_target, qemu_get_aio_context(), &error_abort);
36
+ assert(blk_get_aio_context(blk_target) == qemu_get_aio_context());
37
}
38
aio_context_release(ctx);
39
40
diff --git a/tests/test-block-iothread.c b/tests/test-block-iothread.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/test-block-iothread.c
43
+++ b/tests/test-block-iothread.c
44
@@ -XXX,XX +XXX,XX @@ static void test_attach_preserve_blk_ctx(void)
45
46
/* Remove the node again */
47
blk_remove_bs(blk);
48
- /* TODO bs should move back to main context here */
49
g_assert(blk_get_aio_context(blk) == ctx);
50
- g_assert(bdrv_get_aio_context(bs) == ctx);
51
+ g_assert(bdrv_get_aio_context(bs) == qemu_get_aio_context());
52
53
/* Re-attach the node */
54
blk_insert_bs(blk, bs, &error_abort);
55
--
56
2.20.1
57
58
diff view generated by jsdifflib
Deleted patch
1
Monitor commands can handle errors, so they can easily be converted to
2
using the safer bdrv_try_set_aio_context() function.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
blockdev.c | 44 ++++++++++++++++++++++++++++----------------
7
1 file changed, 28 insertions(+), 16 deletions(-)
8
9
diff --git a/blockdev.c b/blockdev.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/blockdev.c
12
+++ b/blockdev.c
13
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
14
DO_UPCAST(ExternalSnapshotState, common, common);
15
TransactionAction *action = common->action;
16
AioContext *aio_context;
17
+ int ret;
18
19
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
20
* purpose but a different set of parameters */
21
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
22
goto out;
23
}
24
25
- bdrv_set_aio_context(state->new_bs, aio_context);
26
+ ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
27
+ if (ret < 0) {
28
+ goto out;
29
+ }
30
31
/* This removes our old bs and adds the new bs. This is an operation that
32
* can fail, so we need to do it in .prepare; undoing it for abort is
33
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
34
int flags, job_flags = JOB_DEFAULT;
35
int64_t size;
36
bool set_backing_hd = false;
37
+ int ret;
38
39
if (!backup->has_speed) {
40
backup->speed = 0;
41
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
42
goto out;
43
}
44
45
- bdrv_set_aio_context(target_bs, aio_context);
46
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
47
+ if (ret < 0) {
48
+ bdrv_unref(target_bs);
49
+ goto out;
50
+ }
51
52
if (set_backing_hd) {
53
bdrv_set_backing_hd(target_bs, source, &local_err);
54
@@ -XXX,XX +XXX,XX @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
55
AioContext *aio_context;
56
BlockJob *job = NULL;
57
int job_flags = JOB_DEFAULT;
58
+ int ret;
59
60
if (!backup->has_speed) {
61
backup->speed = 0;
62
@@ -XXX,XX +XXX,XX @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
63
goto out;
64
}
65
66
- if (bdrv_get_aio_context(target_bs) != aio_context) {
67
- if (!bdrv_has_blk(target_bs)) {
68
- /* The target BDS is not attached, we can safely move it to another
69
- * AioContext. */
70
- bdrv_set_aio_context(target_bs, aio_context);
71
- } else {
72
- error_setg(errp, "Target is attached to a different thread from "
73
- "source.");
74
- goto out;
75
- }
76
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
77
+ if (ret < 0) {
78
+ goto out;
79
}
80
81
if (backup->has_bitmap) {
82
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
83
int flags;
84
int64_t size;
85
const char *format = arg->format;
86
+ int ret;
87
88
bs = qmp_get_root_bs(arg->device, errp);
89
if (!bs) {
90
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
91
goto out;
92
}
93
94
- bdrv_set_aio_context(target_bs, aio_context);
95
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
96
+ if (ret < 0) {
97
+ bdrv_unref(target_bs);
98
+ goto out;
99
+ }
100
101
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
102
arg->has_replaces, arg->replaces, arg->sync,
103
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
104
AioContext *aio_context;
105
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
106
Error *local_err = NULL;
107
+ int ret;
108
109
bs = qmp_get_root_bs(device, errp);
110
if (!bs) {
111
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
112
aio_context = bdrv_get_aio_context(bs);
113
aio_context_acquire(aio_context);
114
115
- bdrv_set_aio_context(target_bs, aio_context);
116
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
117
+ if (ret < 0) {
118
+ goto out;
119
+ }
120
121
blockdev_mirror_common(has_job_id ? job_id : NULL, bs, target_bs,
122
has_replaces, replaces, sync, backing_mode,
123
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
124
has_auto_dismiss, auto_dismiss,
125
&local_err);
126
error_propagate(errp, local_err);
127
-
128
+out:
129
aio_context_release(aio_context);
130
}
131
132
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
133
old_context = bdrv_get_aio_context(bs);
134
aio_context_acquire(old_context);
135
136
- bdrv_set_aio_context(bs, new_context);
137
+ bdrv_try_set_aio_context(bs, new_context, errp);
138
139
aio_context_release(old_context);
140
}
141
--
142
2.20.1
143
144
diff view generated by jsdifflib
Deleted patch
1
The mirror and commit block jobs use bdrv_set_aio_context() to move
2
their filter node into the right AioContext before hooking it up in the
3
graph. Similarly, bdrv_open_backing_file() explicitly moves the backing
4
file node into the right AioContext first.
5
1
6
This isn't necessary any more, they get automatically moved into the
7
right context now when attaching them.
8
9
However, in the case of bdrv_open_backing_file() with a node reference,
10
it's actually not only unnecessary, but even wrong: The unchecked
11
bdrv_set_aio_context() changes the AioContext of the child node even if
12
other parents require it to retain the old context. So this is not only
13
a simplification, but a bug fix, too.
14
15
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1684342
16
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
---
18
block.c | 1 -
19
block/commit.c | 2 --
20
block/mirror.c | 1 -
21
3 files changed, 4 deletions(-)
22
23
diff --git a/block.c b/block.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/block.c
26
+++ b/block.c
27
@@ -XXX,XX +XXX,XX @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
28
ret = -EINVAL;
29
goto free_exit;
30
}
31
- bdrv_set_aio_context(backing_hd, bdrv_get_aio_context(bs));
32
33
if (implicit_backing) {
34
bdrv_refresh_filename(backing_hd);
35
diff --git a/block/commit.c b/block/commit.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/block/commit.c
38
+++ b/block/commit.c
39
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
40
commit_top_bs->implicit = true;
41
}
42
commit_top_bs->total_sectors = top->total_sectors;
43
- bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(top));
44
45
bdrv_append(commit_top_bs, top, &local_err);
46
if (local_err) {
47
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
48
error_report_err(local_err);
49
goto ro_cleanup;
50
}
51
- bdrv_set_aio_context(commit_top_bs, bdrv_get_aio_context(backing_file_bs));
52
53
bdrv_set_backing_hd(commit_top_bs, backing_file_bs, &error_abort);
54
bdrv_set_backing_hd(bs, commit_top_bs, &error_abort);
55
diff --git a/block/mirror.c b/block/mirror.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block/mirror.c
58
+++ b/block/mirror.c
59
@@ -XXX,XX +XXX,XX @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
60
BDRV_REQ_NO_FALLBACK;
61
bs_opaque = g_new0(MirrorBDSOpaque, 1);
62
mirror_top_bs->opaque = bs_opaque;
63
- bdrv_set_aio_context(mirror_top_bs, bdrv_get_aio_context(bs));
64
65
/* bdrv_append takes ownership of the mirror_top_bs reference, need to keep
66
* it alive until block_job_create() succeeds even if bs has no parent. */
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
Deleted patch
1
This tests that blockdev-add can correctly add a qcow2 overlay to an
2
image used by a virtio-scsi disk in an iothread. The interesting point
3
here is whether the newly added node gets correctly moved into the
4
iothread AioContext.
5
1
6
If it isn't, we get an assertion failure in virtio-scsi while processing
7
the next request:
8
9
virtio_scsi_ctx_check: Assertion `blk_get_aio_context(d->conf.blk) == s->ctx' failed.
10
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
tests/libqtest.h | 11 +++++++
14
tests/libqtest.c | 19 ++++++++++++
15
tests/virtio-scsi-test.c | 62 ++++++++++++++++++++++++++++++++++++++++
16
3 files changed, 92 insertions(+)
17
18
diff --git a/tests/libqtest.h b/tests/libqtest.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tests/libqtest.h
21
+++ b/tests/libqtest.h
22
@@ -XXX,XX +XXX,XX @@ static inline void qtest_end(void)
23
QDict *qmp(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
24
25
/**
26
+ * qmp_assert_success:
27
+ * @fmt...: QMP message to send to qemu, formatted like
28
+ * qobject_from_jsonf_nofail(). See parse_escape() for what's
29
+ * supported after '%'.
30
+ *
31
+ * Sends a QMP message to QEMU and asserts that a 'return' key is present in
32
+ * the response.
33
+ */
34
+void qmp_assert_success(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
35
+
36
+/*
37
* qmp_eventwait:
38
* @s: #event event to wait for.
39
*
40
diff --git a/tests/libqtest.c b/tests/libqtest.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tests/libqtest.c
43
+++ b/tests/libqtest.c
44
@@ -XXX,XX +XXX,XX @@ QDict *qmp(const char *fmt, ...)
45
return response;
46
}
47
48
+void qmp_assert_success(const char *fmt, ...)
49
+{
50
+ va_list ap;
51
+ QDict *response;
52
+
53
+ va_start(ap, fmt);
54
+ response = qtest_vqmp(global_qtest, fmt, ap);
55
+ va_end(ap);
56
+
57
+ g_assert(response);
58
+ if (!qdict_haskey(response, "return")) {
59
+ QString *s = qobject_to_json_pretty(QOBJECT(response));
60
+ g_test_message("%s", qstring_get_str(s));
61
+ qobject_unref(s);
62
+ }
63
+ g_assert(qdict_haskey(response, "return"));
64
+ qobject_unref(response);
65
+}
66
+
67
char *hmp(const char *fmt, ...)
68
{
69
va_list ap;
70
diff --git a/tests/virtio-scsi-test.c b/tests/virtio-scsi-test.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tests/virtio-scsi-test.c
73
+++ b/tests/virtio-scsi-test.c
74
@@ -XXX,XX +XXX,XX @@ static void test_unaligned_write_same(void *obj, void *data,
75
qvirtio_scsi_pci_free(vs);
76
}
77
78
+static void test_iothread_attach_node(void *obj, void *data,
79
+ QGuestAllocator *t_alloc)
80
+{
81
+ QVirtioSCSI *scsi = obj;
82
+ QVirtioSCSIQueues *vs;
83
+ char tmp_path[] = "/tmp/qtest.XXXXXX";
84
+ int fd;
85
+ int ret;
86
+
87
+ uint8_t buf[512] = { 0 };
88
+ const uint8_t write_cdb[VIRTIO_SCSI_CDB_SIZE] = {
89
+ /* WRITE(10) to LBA 0, transfer length 1 */
90
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00
91
+ };
92
+
93
+ alloc = t_alloc;
94
+ vs = qvirtio_scsi_init(scsi->vdev);
95
+
96
+ /* Create a temporary qcow2 overlay*/
97
+ fd = mkstemp(tmp_path);
98
+ g_assert(fd >= 0);
99
+ close(fd);
100
+
101
+ if (!have_qemu_img()) {
102
+ g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
103
+ "skipping snapshot test");
104
+ goto fail;
105
+ }
106
+
107
+ mkqcow2(tmp_path, 64);
108
+
109
+ /* Attach the overlay to the null0 node */
110
+ qmp_assert_success("{'execute': 'blockdev-add', 'arguments': {"
111
+ " 'driver': 'qcow2', 'node-name': 'overlay',"
112
+ " 'backing': 'null0', 'file': {"
113
+ " 'driver': 'file', 'filename': %s}}}", tmp_path);
114
+
115
+ /* Send a request to see if the AioContext is still right */
116
+ ret = virtio_scsi_do_command(vs, write_cdb, NULL, 0, buf, 512, NULL);
117
+ g_assert_cmphex(ret, ==, 0);
118
+
119
+fail:
120
+ qvirtio_scsi_pci_free(vs);
121
+ unlink(tmp_path);
122
+}
123
+
124
static void *virtio_scsi_hotplug_setup(GString *cmd_line, void *arg)
125
{
126
g_string_append(cmd_line,
127
@@ -XXX,XX +XXX,XX @@ static void *virtio_scsi_setup(GString *cmd_line, void *arg)
128
return arg;
129
}
130
131
+static void *virtio_scsi_setup_iothread(GString *cmd_line, void *arg)
132
+{
133
+ g_string_append(cmd_line,
134
+ " -object iothread,id=thread0"
135
+ " -blockdev driver=null-co,node-name=null0"
136
+ " -device scsi-hd,drive=null0");
137
+ return arg;
138
+}
139
+
140
static void register_virtio_scsi_test(void)
141
{
142
QOSGraphTestOptions opts = { };
143
@@ -XXX,XX +XXX,XX @@ static void register_virtio_scsi_test(void)
144
opts.before = virtio_scsi_setup;
145
qos_add_test("unaligned-write-same", "virtio-scsi",
146
test_unaligned_write_same, &opts);
147
+
148
+ opts.before = virtio_scsi_setup_iothread;
149
+ opts.edge = (QOSGraphEdgeOptions) {
150
+ .extra_device_opts = "iothread=thread0",
151
+ };
152
+ qos_add_test("iothread-attach-node", "virtio-scsi",
153
+ test_iothread_attach_node, &opts);
154
}
155
156
libqos_init(register_virtio_scsi_test);
157
--
158
2.20.1
159
160
diff view generated by jsdifflib
Deleted patch
1
This tests that devices refuse to be attached to a node that has already
2
been moved to a different iothread if they can't be or aren't configured
3
to work in the same iothread.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
tests/qemu-iotests/051 | 24 ++++++++++++++++++++++++
8
tests/qemu-iotests/051.out | 3 +++
9
tests/qemu-iotests/051.pc.out | 27 +++++++++++++++++++++++++++
10
3 files changed, 54 insertions(+)
11
12
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/051
15
+++ b/tests/qemu-iotests/051
16
@@ -XXX,XX +XXX,XX @@ case "$QEMU_DEFAULT_MACHINE" in
17
;;
18
esac
19
20
+echo
21
+echo === Attach to node in non-default iothread ===
22
+echo
23
+
24
+case "$QEMU_DEFAULT_MACHINE" in
25
+ pc)
26
+ iothread="-drive file=$TEST_IMG,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on"
27
+
28
+ # Can't add a device in the main thread while virtio-scsi0 uses the node
29
+ run_qemu $iothread -device ide-hd,drive=disk,share-rw=on
30
+ run_qemu $iothread -device virtio-blk-pci,drive=disk,share-rw=on
31
+ run_qemu $iothread -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on
32
+ run_qemu $iothread -device virtio-scsi,id=virtio-scsi1 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
33
+
34
+ # virtio-blk enables the iothread only when the driver initialises the
35
+ # device, so a second virtio-blk device can't be added even with the
36
+ # same iothread. virtio-scsi allows this.
37
+ run_qemu $iothread -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on
38
+ run_qemu $iothread -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
39
+ ;;
40
+ *)
41
+ ;;
42
+esac
43
+
44
echo
45
echo === Read-only ===
46
echo
47
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
48
index XXXXXXX..XXXXXXX 100644
49
--- a/tests/qemu-iotests/051.out
50
+++ b/tests/qemu-iotests/051.out
51
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
52
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
53
54
55
+=== Attach to node in non-default iothread ===
56
+
57
+
58
=== Read-only ===
59
60
Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
61
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
62
index XXXXXXX..XXXXXXX 100644
63
--- a/tests/qemu-iotests/051.pc.out
64
+++ b/tests/qemu-iotests/051.pc.out
65
@@ -XXX,XX +XXX,XX @@ QEMU X.Y.Z monitor - type 'help' for more information
66
(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
67
68
69
+=== Attach to node in non-default iothread ===
70
+
71
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device ide-hd,drive=disk,share-rw=on
72
+QEMU X.Y.Z monitor - type 'help' for more information
73
+(qemu) QEMU_PROG: -device ide-hd,drive=disk,share-rw=on: Cannot change iothread of active block backend
74
+
75
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,share-rw=on
76
+QEMU X.Y.Z monitor - type 'help' for more information
77
+(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,share-rw=on: Cannot change iothread of active block backend
78
+
79
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on
80
+QEMU X.Y.Z monitor - type 'help' for more information
81
+(qemu) QEMU_PROG: -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on: HBA does not support iothreads
82
+
83
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
84
+QEMU X.Y.Z monitor - type 'help' for more information
85
+(qemu) QEMU_PROG: -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on: Cannot change iothread of active block backend
86
+
87
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on
88
+QEMU X.Y.Z monitor - type 'help' for more information
89
+(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,iohtread=iothread0,share-rw=on: Cannot change iothread of active block backend
90
+
91
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
92
+QEMU X.Y.Z monitor - type 'help' for more information
93
+(qemu) quit
94
+
95
+
96
=== Read-only ===
97
98
Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
Deleted patch
1
No reason to use the unchecked version in tests, even more so when these
2
are the last callers of bdrv_set_aio_context() outside of block.c.
3
1
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
tests/test-bdrv-drain.c | 6 +++---
7
1 file changed, 3 insertions(+), 3 deletions(-)
8
9
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/tests/test-bdrv-drain.c
12
+++ b/tests/test-bdrv-drain.c
13
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
14
&error_abort);
15
16
bdrv_drained_begin(bs);
17
- bdrv_set_aio_context(bs, ctx_a);
18
+ bdrv_try_set_aio_context(bs, ctx_a, &error_abort);
19
20
aio_context_acquire(ctx_a);
21
bdrv_drained_end(bs);
22
23
bdrv_drained_begin(bs);
24
- bdrv_set_aio_context(bs, ctx_b);
25
+ bdrv_try_set_aio_context(bs, ctx_b, &error_abort);
26
aio_context_release(ctx_a);
27
aio_context_acquire(ctx_b);
28
- bdrv_set_aio_context(bs, qemu_get_aio_context());
29
+ bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort);
30
aio_context_release(ctx_b);
31
bdrv_drained_end(bs);
32
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
Deleted patch
1
All callers of bdrv_set_aio_context() are eliminated now, they have
2
moved to bdrv_try_set_aio_context() and related safe functions. Remove
3
bdrv_set_aio_context().
4
1
5
With this, we can now know that the .set_aio_ctx callback must be
6
present in bdrv_set_aio_context_ignore() because
7
bdrv_can_set_aio_context() would have returned false previously, so
8
instead of checking the condition, we can assert it.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
docs/devel/multiple-iothreads.txt | 4 ++--
13
include/block/block.h | 9 ---------
14
block.c | 30 ++++++++++++++----------------
15
3 files changed, 16 insertions(+), 27 deletions(-)
16
17
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
18
index XXXXXXX..XXXXXXX 100644
19
--- a/docs/devel/multiple-iothreads.txt
20
+++ b/docs/devel/multiple-iothreads.txt
21
@@ -XXX,XX +XXX,XX @@ The AioContext originates from the QEMU block layer, even though nowadays
22
AioContext is a generic event loop that can be used by any QEMU subsystem.
23
24
The block layer has support for AioContext integrated. Each BlockDriverState
25
-is associated with an AioContext using bdrv_set_aio_context() and
26
+is associated with an AioContext using bdrv_try_set_aio_context() and
27
bdrv_get_aio_context(). This allows block layer code to process I/O inside the
28
right AioContext. Other subsystems may wish to follow a similar approach.
29
30
@@ -XXX,XX +XXX,XX @@ Long-running jobs (usually in the form of coroutines) are best scheduled in
31
the BlockDriverState's AioContext to avoid the need to acquire/release around
32
each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
33
or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
34
-can be used to get a notification whenever bdrv_set_aio_context() moves a
35
+can be used to get a notification whenever bdrv_try_set_aio_context() moves a
36
BlockDriverState to a different AioContext.
37
diff --git a/include/block/block.h b/include/block/block.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/block/block.h
40
+++ b/include/block/block.h
41
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_get_aio_context(BlockDriverState *bs);
42
*/
43
void bdrv_coroutine_enter(BlockDriverState *bs, Coroutine *co);
44
45
-/**
46
- * bdrv_set_aio_context:
47
- *
48
- * Changes the #AioContext used for fd handlers, timers, and BHs by this
49
- * BlockDriverState and all its children.
50
- *
51
- * This function must be called with iothread lock held.
52
- */
53
-void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context);
54
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
55
AioContext *new_context, GSList **ignore);
56
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
57
diff --git a/block.c b/block.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/block.c
60
+++ b/block.c
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
62
bs->walking_aio_notifiers = false;
63
}
64
65
-/* @ignore will accumulate all visited BdrvChild object. The caller is
66
- * responsible for freeing the list afterwards. */
67
+/*
68
+ * Changes the AioContext used for fd handlers, timers, and BHs by this
69
+ * BlockDriverState and all its children and parents.
70
+ *
71
+ * The caller must own the AioContext lock for the old AioContext of bs, but it
72
+ * must not own the AioContext lock for new_context (unless new_context is the
73
+ * same as the current context of bs).
74
+ *
75
+ * @ignore will accumulate all visited BdrvChild object. The caller is
76
+ * responsible for freeing the list afterwards.
77
+ */
78
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
79
AioContext *new_context, GSList **ignore)
80
{
81
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
82
if (g_slist_find(*ignore, child)) {
83
continue;
84
}
85
- if (child->role->set_aio_ctx) {
86
- *ignore = g_slist_prepend(*ignore, child);
87
- child->role->set_aio_ctx(child, new_context, ignore);
88
- }
89
+ assert(child->role->set_aio_ctx);
90
+ *ignore = g_slist_prepend(*ignore, child);
91
+ child->role->set_aio_ctx(child, new_context, ignore);
92
}
93
94
bdrv_detach_aio_context(bs);
95
@@ -XXX,XX +XXX,XX @@ void bdrv_set_aio_context_ignore(BlockDriverState *bs,
96
aio_context_release(new_context);
97
}
98
99
-/* The caller must own the AioContext lock for the old AioContext of bs, but it
100
- * must not own the AioContext lock for new_context (unless new_context is
101
- * the same as the current context of bs). */
102
-void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context)
103
-{
104
- GSList *ignore_list = NULL;
105
- bdrv_set_aio_context_ignore(bs, new_context, &ignore_list);
106
- g_slist_free(ignore_list);
107
-}
108
-
109
static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
110
GSList **ignore, Error **errp)
111
{
112
--
113
2.20.1
114
115
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Let's at least trace ignored failure.
4
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2-refcount.c | 7 ++++++-
10
block/trace-events | 3 +++
11
2 files changed, 9 insertions(+), 1 deletion(-)
12
13
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2-refcount.c
16
+++ b/block/qcow2-refcount.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "qemu/range.h"
19
#include "qemu/bswap.h"
20
#include "qemu/cutils.h"
21
+#include "trace.h"
22
23
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
24
uint64_t max);
25
@@ -XXX,XX +XXX,XX @@ void qcow2_process_discards(BlockDriverState *bs, int ret)
26
27
/* Discard is optional, ignore the return value */
28
if (ret >= 0) {
29
- bdrv_pdiscard(bs->file, d->offset, d->bytes);
30
+ int r2 = bdrv_pdiscard(bs->file, d->offset, d->bytes);
31
+ if (r2 < 0) {
32
+ trace_qcow2_process_discards_failed_region(d->offset, d->bytes,
33
+ r2);
34
+ }
35
}
36
37
g_free(d);
38
diff --git a/block/trace-events b/block/trace-events
39
index XXXXXXX..XXXXXXX 100644
40
--- a/block/trace-events
41
+++ b/block/trace-events
42
@@ -XXX,XX +XXX,XX @@ qcow2_cache_get_done(void *co, int c, int i) "co %p is_l2_cache %d index %d"
43
qcow2_cache_flush(void *co, int c) "co %p is_l2_cache %d"
44
qcow2_cache_entry_flush(void *co, int c, int i) "co %p is_l2_cache %d index %d"
45
46
+# qcow2-refcount.c
47
+qcow2_process_discards_failed_region(uint64_t offset, uint64_t bytes, int ret) "offset 0x%" PRIx64 " bytes 0x%" PRIx64 " ret %d"
48
+
49
# qed-l2-cache.c
50
qed_alloc_l2_cache_entry(void *l2_cache, void *entry) "l2_cache %p entry %p"
51
qed_unref_l2_cache_entry(void *entry, int ref) "entry %p ref %d"
52
--
53
2.20.1
54
55
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
This fixes at least one overflow in qcow2_process_discards, which
4
passes 64bit region length to bdrv_pdiscard where bytes (or sectors in
5
the past) parameter is int since its introduction in 0b919fae.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block.h | 4 ++--
11
block/io.c | 16 ++++++++--------
12
2 files changed, 10 insertions(+), 10 deletions(-)
13
14
diff --git a/include/block/block.h b/include/block/block.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block.h
17
+++ b/include/block/block.h
18
@@ -XXX,XX +XXX,XX @@ void bdrv_drain_all(void);
19
AIO_WAIT_WHILE(bdrv_get_aio_context(bs_), \
20
cond); })
21
22
-int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes);
23
-int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes);
24
+int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
25
+int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
26
int bdrv_has_zero_init_1(BlockDriverState *bs);
27
int bdrv_has_zero_init(BlockDriverState *bs);
28
bool bdrv_unallocated_blocks_are_zero(BlockDriverState *bs);
29
diff --git a/block/io.c b/block/io.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/block/io.c
32
+++ b/block/io.c
33
@@ -XXX,XX +XXX,XX @@ int bdrv_flush(BlockDriverState *bs)
34
typedef struct DiscardCo {
35
BdrvChild *child;
36
int64_t offset;
37
- int bytes;
38
+ int64_t bytes;
39
int ret;
40
} DiscardCo;
41
static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
42
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_pdiscard_co_entry(void *opaque)
43
aio_wait_kick();
44
}
45
46
-int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
47
+int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
48
+ int64_t bytes)
49
{
50
BdrvTrackedRequest req;
51
int max_pdiscard, ret;
52
int head, tail, align;
53
BlockDriverState *bs = child->bs;
54
55
- if (!bs || !bs->drv) {
56
+ if (!bs || !bs->drv || !bdrv_is_inserted(bs)) {
57
return -ENOMEDIUM;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
61
return -EPERM;
62
}
63
64
- ret = bdrv_check_byte_request(bs, offset, bytes);
65
- if (ret < 0) {
66
- return ret;
67
+ if (offset < 0 || bytes < 0 || bytes > INT64_MAX - offset) {
68
+ return -EIO;
69
}
70
71
/* Do nothing if disabled. */
72
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int bytes)
73
assert(max_pdiscard >= bs->bl.request_alignment);
74
75
while (bytes > 0) {
76
- int num = bytes;
77
+ int64_t num = bytes;
78
79
if (head) {
80
/* Make small requests to get to alignment boundaries. */
81
@@ -XXX,XX +XXX,XX @@ out:
82
return ret;
83
}
84
85
-int bdrv_pdiscard(BdrvChild *child, int64_t offset, int bytes)
86
+int bdrv_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes)
87
{
88
Coroutine *co;
89
DiscardCo rwco = {
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
Deleted patch
1
Commit 70ff5b07 wanted to move the diff between actual and reference
2
output to the end after printing the test result line. It really only
3
copied it, though, so the diff is now displayed twice. Remove the old
4
one.
5
1
6
Fixes: 70ff5b07fcdd378180ad2d5cc0b0d5e67e7ef325
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
tests/qemu-iotests/check | 1 -
10
1 file changed, 1 deletion(-)
11
12
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
13
index XXXXXXX..XXXXXXX 100755
14
--- a/tests/qemu-iotests/check
15
+++ b/tests/qemu-iotests/check
16
@@ -XXX,XX +XXX,XX @@ do
17
fi
18
else
19
mv $tmp.out $seq.out.bad
20
- $diff -w "$reference" "$PWD"/$seq.out.bad
21
status="fail"
22
results="output mismatch (see $seq.out.bad)"
23
printdiff=true
24
--
25
2.20.1
26
27
diff view generated by jsdifflib