1
The following changes since commit 105b07f1ba462ec48b27e5cb74ddf81c6a79364c:
1
The following changes since commit 344744e148e6e865f5a57e745b02a87e5ea534ad:
2
2
3
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20200127' into staging (2020-01-27 13:02:36 +0000)
3
Merge tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging (2022-10-26 10:53:49 -0400)
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 5fbf1d56c24018772e900a40a0955175ff82f35c:
9
for you to fetch changes up to be8da05b5ed8fb546731b9edb997f303f272bad8:
10
10
11
iscsi: Don't access non-existent scsi_lba_status_descriptor (2020-01-27 17:19:53 +0100)
11
block/block-backend: blk_set_enable_write_cache is IO_CODE (2022-10-27 20:27:37 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711)
16
- Cleanup bs->backing and bs->file handling
17
- AioContext fixes in QMP commands for backup and bitmaps
17
- Refactor bdrv_try_set_aio_context using transactions
18
- iotests fixes
18
- Changes for improved coroutine_fn consistency
19
- vhost-user-blk: fix the resize crash
20
- io_uring: Use of io_uring_register_ring_fd() led to breakage, revert
21
- vvfat: Fix some problems with r/w mode
22
- Code cleanup
23
- MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
19
24
20
----------------------------------------------------------------
25
----------------------------------------------------------------
21
Eiichi Tsukata (1):
26
Alberto Faria (20):
22
block/backup: fix memory leak in bdrv_backup_top_append()
27
backup: remove incorrect coroutine_fn annotation
28
block: remove incorrect coroutine_fn annotation
29
monitor: add missing coroutine_fn annotation
30
ssh: add missing coroutine_fn annotation
31
block: add missing coroutine_fn annotation to prototypes
32
coroutine-lock: add missing coroutine_fn annotation to prototypes
33
coroutine-io: add missing coroutine_fn annotation to prototypes
34
block: add missing coroutine_fn annotation to BlockDriverState callbacks
35
qcow2: add coroutine_fn annotation for indirect-called functions
36
commit: switch to *_co_* functions
37
block: switch to *_co_* functions
38
mirror: switch to *_co_* functions
39
parallels: switch to *_co_* functions
40
qcow: switch to *_co_* functions
41
qcow2: switch to *_co_* functions
42
qed: switch to *_co_* functions
43
vdi: switch to *_co_* functions
44
vhdx: switch to *_co_* functions
45
vmdk: switch to *_co_* functions
46
monitor: switch to *_co_* functions
23
47
24
Felipe Franciosi (1):
48
Bin Meng (3):
25
iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711)
49
block: Ignore close() failure in get_tmp_filename()
50
block: Refactor get_tmp_filename()
51
block/nfs: Fix 32-bit Windows build
26
52
27
Kevin Wolf (1):
53
Emanuele Giuseppe Esposito (11):
28
iscsi: Don't access non-existent scsi_lba_status_descriptor
54
block.c: assert bs->aio_context is written under BQL and drains
55
block: use transactions as a replacement of ->{can_}set_aio_context()
56
bdrv_change_aio_context: use hash table instead of list of visited nodes
57
blockjob: implement .change_aio_ctx in child_job
58
block: implement .change_aio_ctx in child_of_bds
59
block-backend: implement .change_aio_ctx in child_root
60
block: use the new _change_ API instead of _can_set_ and _set_
61
block: remove all unused ->can_set_aio_ctx and ->set_aio_ctx callbacks
62
block: rename bdrv_child_try_change_aio_context in bdrv_try_change_aio_context
63
block: remove bdrv_try_set_aio_context and replace it with bdrv_try_change_aio_context
64
block/block-backend: blk_set_enable_write_cache is IO_CODE
29
65
30
Max Reitz (1):
66
Hervé Poussineau (2):
31
iotests.py: Let wait_migration wait even more
67
vvfat: allow some writes to bootsector
68
vvfat: allow spaces in file names
32
69
33
Sergio Lopez (8):
70
Li Feng (1):
34
blockdev: fix coding style issues in drive_backup_prepare
71
vhost-user-blk: fix the resize crash
35
blockdev: unify qmp_drive_backup and drive-backup transaction paths
36
blockdev: unify qmp_blockdev_backup and blockdev-backup transaction paths
37
blockdev: honor bdrv_try_set_aio_context() context requirements
38
block/backup-top: Don't acquire context while dropping top
39
blockdev: Acquire AioContext on dirty bitmap functions
40
blockdev: Return bs to the proper context on snapshot abort
41
iotests: Test handling of AioContexts with some blockdev actions
42
72
43
Thomas Huth (1):
73
Markus Armbruster (1):
44
iotests: Add more "skip_if_unsupported" statements to the python tests
74
MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core"
45
75
46
block/backup-top.c | 7 +-
76
Paolo Bonzini (4):
47
block/backup.c | 3 +
77
blkdebug: add missing coroutine_fn annotation for indirect-called functions
48
block/iscsi.c | 7 +-
78
qcow: manually add more coroutine_fn annotations
49
blockdev.c | 393 +++++++++++++++++++++++-------------------
79
qcow2: manually add more coroutine_fn annotations
50
tests/qemu-iotests/iotests.py | 6 +-
80
vmdk: manually add more coroutine_fn annotations
51
tests/qemu-iotests/030 | 4 +-
81
52
tests/qemu-iotests/040 | 2 +
82
Sam Li (1):
53
tests/qemu-iotests/041 | 39 +----
83
block/io_uring: revert "Use io_uring_register_ring_fd() to skip fd operations"
54
tests/qemu-iotests/141.out | 2 +
84
55
tests/qemu-iotests/185.out | 2 +
85
Vladimir Sementsov-Ogievskiy (15):
56
tests/qemu-iotests/219 | 7 +-
86
block: BlockDriver: add .filtered_child_is_backing field
57
tests/qemu-iotests/219.out | 8 +
87
block: introduce bdrv_open_file_child() helper
58
tests/qemu-iotests/234 | 8 +-
88
block/blklogwrites: don't care to remove bs->file child on failure
59
tests/qemu-iotests/245 | 2 +
89
test-bdrv-graph-mod: update test_parallel_perm_update test case
60
tests/qemu-iotests/262 | 4 +-
90
tests-bdrv-drain: bdrv_replace_test driver: declare supports_backing
61
tests/qemu-iotests/280 | 2 +-
91
test-bdrv-graph-mod: fix filters to be filters
62
tests/qemu-iotests/281 | 247 ++++++++++++++++++++++++++
92
block: document connection between child roles and bs->backing/bs->file
63
tests/qemu-iotests/281.out | 5 +
93
block/snapshot: stress that we fallback to primary child
64
tests/qemu-iotests/group | 1 +
94
Revert "block: Let replace_child_noperm free children"
65
19 files changed, 510 insertions(+), 239 deletions(-)
95
Revert "block: Let replace_child_tran keep indirect pointer"
66
create mode 100755 tests/qemu-iotests/281
96
Revert "block: Restructure remove_file_or_backing_child()"
67
create mode 100644 tests/qemu-iotests/281.out
97
Revert "block: Pass BdrvChild ** to replace_child_noperm"
98
block: Manipulate bs->file / bs->backing pointers in .attach/.detach
99
block/snapshot: drop indirection around bdrv_snapshot_fallback_ptr
100
block: refactor bdrv_remove_file_or_backing_child to bdrv_remove_child
101
102
docs/devel/multiple-iothreads.txt | 4 +-
103
block/qcow2.h | 32 +-
104
include/block/block-common.h | 39 ++
105
include/block/block-global-state.h | 18 +-
106
include/block/block-hmp-cmds.h | 2 +-
107
include/block/block-io.h | 5 +-
108
include/block/block_int-common.h | 49 ++-
109
include/monitor/hmp.h | 3 +-
110
include/qemu/coroutine.h | 18 +-
111
block.c | 855 +++++++++++++++++--------------------
112
block/backup.c | 2 +-
113
block/blkdebug.c | 11 +-
114
block/blklogwrites.c | 11 +-
115
block/blkreplay.c | 7 +-
116
block/blkverify.c | 9 +-
117
block/block-backend.c | 76 ++--
118
block/bochs.c | 7 +-
119
block/cloop.c | 7 +-
120
block/commit.c | 3 +-
121
block/copy-before-write.c | 9 +-
122
block/copy-on-read.c | 9 +-
123
block/crypto.c | 11 +-
124
block/dmg.c | 7 +-
125
block/export/export.c | 2 +-
126
block/filter-compress.c | 8 +-
127
block/io.c | 8 +-
128
block/io_uring.c | 13 +-
129
block/mirror.c | 5 +-
130
block/monitor/block-hmp-cmds.c | 2 +-
131
block/nfs.c | 8 +
132
block/parallels.c | 35 +-
133
block/preallocate.c | 9 +-
134
block/qcow.c | 66 +--
135
block/qcow2-bitmap.c | 4 +-
136
block/qcow2-cluster.c | 29 +-
137
block/qcow2-refcount.c | 18 +-
138
block/qcow2-snapshot.c | 6 +-
139
block/qcow2.c | 40 +-
140
block/qed-table.c | 2 +-
141
block/qed.c | 20 +-
142
block/raw-format.c | 4 +-
143
block/replication.c | 8 +-
144
block/snapshot-access.c | 6 +-
145
block/snapshot.c | 59 +--
146
block/ssh.c | 6 +-
147
block/throttle.c | 8 +-
148
block/vdi.c | 24 +-
149
block/vhdx.c | 15 +-
150
block/vmdk.c | 95 ++---
151
block/vpc.c | 7 +-
152
block/vvfat.c | 35 +-
153
blockdev.c | 24 +-
154
blockjob.c | 50 ++-
155
hw/block/vhost-user-blk.c | 4 +
156
job.c | 2 +-
157
tests/unit/test-bdrv-drain.c | 17 +-
158
tests/unit/test-bdrv-graph-mod.c | 104 +++--
159
tests/unit/test-block-iothread.c | 10 +-
160
MAINTAINERS | 12 +-
161
meson.build | 1 -
162
tests/qemu-iotests/051 | 3 +-
163
tests/qemu-iotests/051.out | 2 +-
164
tests/qemu-iotests/051.pc.out | 2 +-
165
63 files changed, 984 insertions(+), 983 deletions(-)
68
166
69
167
diff view generated by jsdifflib
New patch
1
From: Markus Armbruster <armbru@redhat.com>
1
2
3
Section "Block QAPI, monitor, command line" is about the external
4
interfaces we provide for block devices. It covers the relevant QAPI
5
schema parts, monitor and command line code, more or less.
6
7
The section's files are also covered by section "Block layer core",
8
except for the QAPI schema files.
9
10
I haven't acted as maintainer in this area for a long time. Make it
11
official: add the QAPI schema files to section "Block layer core", and
12
delete section "Block QAPI, monitor, command line".
13
14
Cc: Kevin Wolf <kwolf@redhat.com>
15
Cc: Hanna Reitz <hreitz@redhat.com>
16
Signed-off-by: Markus Armbruster <armbru@redhat.com>
17
Message-Id: <20221020120541.80757-1-armbru@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
20
---
21
MAINTAINERS | 12 ++----------
22
1 file changed, 2 insertions(+), 10 deletions(-)
23
24
diff --git a/MAINTAINERS b/MAINTAINERS
25
index XXXXXXX..XXXXXXX 100644
26
--- a/MAINTAINERS
27
+++ b/MAINTAINERS
28
@@ -XXX,XX +XXX,XX @@ S: Supported
29
F: block*
30
F: block/
31
F: hw/block/
32
+F: qapi/block*.json
33
+F: qapi/transaction.json
34
F: include/block/
35
F: qemu-img*
36
F: docs/tools/qemu-img.rst
37
@@ -XXX,XX +XXX,XX @@ F: include/qemu/co-shared-resource.h
38
T: git https://gitlab.com/jsnow/qemu.git jobs
39
T: git https://gitlab.com/vsementsov/qemu.git block
40
41
-Block QAPI, monitor, command line
42
-M: Markus Armbruster <armbru@redhat.com>
43
-S: Supported
44
-F: blockdev.c
45
-F: blockdev-hmp-cmds.c
46
-F: block/qapi.c
47
-F: qapi/block*.json
48
-F: qapi/transaction.json
49
-T: git https://repo.or.cz/qemu/armbru.git block-next
50
-
51
Compute Express Link
52
M: Ben Widawsky <ben.widawsky@intel.com>
53
M: Jonathan Cameron <jonathan.cameron@huawei.com>
54
--
55
2.37.3
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bin.meng@windriver.com>
1
2
3
The temporary file has been created and is ready for use. Checking
4
return value of close() does not seem useful. The file descriptor
5
is almost certainly closed; see close(2) under "Dealing with error
6
returns from close()".
7
8
Let's simply ignore close() failure here.
9
10
Suggested-by: Markus Armbruster <armbru@redhat.com>
11
Signed-off-by: Bin Meng <bin.meng@windriver.com>
12
Reviewed-by: Markus Armbruster <armbru@redhat.com>
13
Message-Id: <20221010040432.3380478-1-bin.meng@windriver.com>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block.c | 5 +----
18
1 file changed, 1 insertion(+), 4 deletions(-)
19
20
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block.c
23
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ int get_tmp_filename(char *filename, int size)
25
if (fd < 0) {
26
return -errno;
27
}
28
- if (close(fd) != 0) {
29
- unlink(filename);
30
- return -errno;
31
- }
32
+ close(fd);
33
return 0;
34
#endif
35
}
36
--
37
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Bin Meng <bin.meng@windriver.com>
2
3
At present there are two callers of get_tmp_filename() and they are
4
inconsistent.
5
6
One does:
7
8
/* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
9
char *tmp_filename = g_malloc0(PATH_MAX + 1);
10
...
11
ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
12
13
while the other does:
14
15
s->qcow_filename = g_malloc(PATH_MAX);
16
ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
17
18
As we can see different 'size' arguments are passed. There are also
19
platform specific implementations inside the function, and the use
20
of snprintf is really undesirable.
21
22
The function name is also misleading. It creates a temporary file,
23
not just a filename.
24
25
Refactor this routine by changing its name and signature to:
26
27
char *create_tmp_file(Error **errp)
28
29
and use g_get_tmp_dir() / g_mkstemp() for a consistent implementation.
30
31
While we are here, add some comments to mention that /var/tmp is
32
preferred over /tmp on non-win32 hosts.
33
34
Signed-off-by: Bin Meng <bin.meng@windriver.com>
35
Message-Id: <20221010040432.3380478-2-bin.meng@windriver.com>
36
[kwolf: Fixed incorrect errno negation and iotest 051]
37
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
38
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
39
---
40
include/block/block_int-common.h | 2 +-
41
block.c | 56 +++++++++++++++++---------------
42
block/vvfat.c | 7 ++--
43
tests/qemu-iotests/051 | 3 +-
44
tests/qemu-iotests/051.out | 2 +-
45
tests/qemu-iotests/051.pc.out | 2 +-
46
6 files changed, 38 insertions(+), 34 deletions(-)
47
48
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
49
index XXXXXXX..XXXXXXX 100644
50
--- a/include/block/block_int-common.h
51
+++ b/include/block/block_int-common.h
52
@@ -XXX,XX +XXX,XX @@ static inline BlockDriverState *child_bs(BdrvChild *child)
53
}
54
55
int bdrv_check_request(int64_t offset, int64_t bytes, Error **errp);
56
-int get_tmp_filename(char *filename, int size);
57
+char *create_tmp_file(Error **errp);
58
void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
59
QDict *options);
60
61
diff --git a/block.c b/block.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block.c
64
+++ b/block.c
65
@@ -XXX,XX +XXX,XX @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
66
67
/*
68
* Create a uniquely-named empty temporary file.
69
- * Return 0 upon success, otherwise a negative errno value.
70
+ * Return the actual file name used upon success, otherwise NULL.
71
+ * This string should be freed with g_free() when not needed any longer.
72
+ *
73
+ * Note: creating a temporary file for the caller to (re)open is
74
+ * inherently racy. Use g_file_open_tmp() instead whenever practical.
75
*/
76
-int get_tmp_filename(char *filename, int size)
77
+char *create_tmp_file(Error **errp)
78
{
79
-#ifdef _WIN32
80
- char temp_dir[MAX_PATH];
81
- /* GetTempFileName requires that its output buffer (4th param)
82
- have length MAX_PATH or greater. */
83
- assert(size >= MAX_PATH);
84
- return (GetTempPath(MAX_PATH, temp_dir)
85
- && GetTempFileName(temp_dir, "qem", 0, filename)
86
- ? 0 : -GetLastError());
87
-#else
88
int fd;
89
const char *tmpdir;
90
- tmpdir = getenv("TMPDIR");
91
- if (!tmpdir) {
92
+ g_autofree char *filename = NULL;
93
+
94
+ tmpdir = g_get_tmp_dir();
95
+#ifndef _WIN32
96
+ /*
97
+ * See commit 69bef79 ("block: use /var/tmp instead of /tmp for -snapshot")
98
+ *
99
+ * This function is used to create temporary disk images (like -snapshot),
100
+ * so the files can become very large. /tmp is often a tmpfs where as
101
+ * /var/tmp is usually on a disk, so more appropriate for disk images.
102
+ */
103
+ if (!g_strcmp0(tmpdir, "/tmp")) {
104
tmpdir = "/var/tmp";
105
}
106
- if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
107
- return -EOVERFLOW;
108
- }
109
- fd = mkstemp(filename);
110
+#endif
111
+
112
+ filename = g_strdup_printf("%s/vl.XXXXXX", tmpdir);
113
+ fd = g_mkstemp(filename);
114
if (fd < 0) {
115
- return -errno;
116
+ error_setg_errno(errp, errno, "Could not open temporary file '%s'",
117
+ filename);
118
+ return NULL;
119
}
120
close(fd);
121
- return 0;
122
-#endif
123
+
124
+ return g_steal_pointer(&filename);
125
}
126
127
/*
128
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
129
QDict *snapshot_options,
130
Error **errp)
131
{
132
- /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
133
- char *tmp_filename = g_malloc0(PATH_MAX + 1);
134
+ g_autofree char *tmp_filename = NULL;
135
int64_t total_size;
136
QemuOpts *opts = NULL;
137
BlockDriverState *bs_snapshot = NULL;
138
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
139
}
140
141
/* Create the temporary image */
142
- ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
143
- if (ret < 0) {
144
- error_setg_errno(errp, -ret, "Could not get temporary filename");
145
+ tmp_filename = create_tmp_file(errp);
146
+ if (!tmp_filename) {
147
goto out;
148
}
149
150
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
151
152
out:
153
qobject_unref(snapshot_options);
154
- g_free(tmp_filename);
155
return bs_snapshot;
156
}
157
158
diff --git a/block/vvfat.c b/block/vvfat.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/block/vvfat.c
161
+++ b/block/vvfat.c
162
@@ -XXX,XX +XXX,XX @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
163
164
array_init(&(s->commits), sizeof(commit_t));
165
166
- s->qcow_filename = g_malloc(PATH_MAX);
167
- ret = get_tmp_filename(s->qcow_filename, PATH_MAX);
168
- if (ret < 0) {
169
- error_setg_errno(errp, -ret, "can't create temporary file");
170
+ s->qcow_filename = create_tmp_file(errp);
171
+ if (!s->qcow_filename) {
172
+ ret = -ENOENT;
173
goto err;
174
}
175
176
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
177
index XXXXXXX..XXXXXXX 100755
178
--- a/tests/qemu-iotests/051
179
+++ b/tests/qemu-iotests/051
180
@@ -XXX,XX +XXX,XX @@ if [ "${VALGRIND_QEMU_VM}" == "y" ]; then
181
_casenotrun "Valgrind needs a valid TMPDIR for itself"
182
fi
183
VALGRIND_QEMU_VM= \
184
-TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on
185
+TMPDIR=/nonexistent run_qemu -drive driver=null-co,snapshot=on |
186
+ sed -e "s#'[^']*/vl\.[A-Za-z0-9]\{6\}'#SNAPSHOT_PATH#g"
187
188
# Using snapshot=on together with read-only=on
189
echo "info block" |
190
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
191
index XXXXXXX..XXXXXXX 100644
192
--- a/tests/qemu-iotests/051.out
193
+++ b/tests/qemu-iotests/051.out
194
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
195
read 4096/4096 bytes at offset 0
196
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
197
Testing: -drive driver=null-co,snapshot=on
198
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
199
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
200
201
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
202
QEMU X.Y.Z monitor - type 'help' for more information
203
diff --git a/tests/qemu-iotests/051.pc.out b/tests/qemu-iotests/051.pc.out
204
index XXXXXXX..XXXXXXX 100644
205
--- a/tests/qemu-iotests/051.pc.out
206
+++ b/tests/qemu-iotests/051.pc.out
207
@@ -XXX,XX +XXX,XX @@ wrote 4096/4096 bytes at offset 0
208
read 4096/4096 bytes at offset 0
209
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
210
Testing: -drive driver=null-co,snapshot=on
211
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
212
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
213
214
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
215
QEMU X.Y.Z monitor - type 'help' for more information
216
--
217
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
external_snapshot_abort() calls to bdrv_set_backing_hd(), which
3
'reserved1' field in bootsector is used to mark volume dirty, or need to verify.
4
returns state->old_bs to the main AioContext, as it's intended to be
4
Allow writes to bootsector which only changes the 'reserved1' field.
5
used then the BDS is going to be released. As that's not the case when
6
aborting an external snapshot, return it to the AioContext it was
7
before the call.
8
5
9
This issue can be triggered by issuing a transaction with two actions,
6
This fixes I/O errors on Windows guests.
10
a proper blockdev-snapshot-sync and a bogus one, so the second will
11
trigger a transaction abort. This results in a crash with an stack
12
trace like this one:
13
7
14
#0 0x00007fa1048b28df in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
8
Resolves: https://bugs.launchpad.net/qemu/+bug/1889421
15
#1 0x00007fa10489ccf5 in __GI_abort () at abort.c:79
9
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
16
#2 0x00007fa10489cbc9 in __assert_fail_base
10
Message-Id: <20221010175511.3414357-2-hpoussin@reactos.org>
17
(fmt=0x7fa104a03300 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=0x557224014d30 "block.c", line=2240, function=<optimized out>) at assert.c:92
11
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
#3 0x00007fa1048aae96 in __GI___assert_fail
19
(assertion=assertion@entry=0x5572240b44d8 "bdrv_get_aio_context(old_bs) == bdrv_get_aio_context(new_bs)", file=file@entry=0x557224014d30 "block.c", line=line@entry=2240, function=function@entry=0x5572240b5d60 <__PRETTY_FUNCTION__.31620> "bdrv_replace_child_noperm") at assert.c:101
20
#4 0x0000557223e631f8 in bdrv_replace_child_noperm (child=0x557225b9c980, new_bs=new_bs@entry=0x557225c42e40) at block.c:2240
21
#5 0x0000557223e68be7 in bdrv_replace_node (from=0x557226951a60, to=0x557225c42e40, errp=0x5572247d6138 <error_abort>) at block.c:4196
22
#6 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1731
23
#7 0x0000557223d069c4 in external_snapshot_abort (common=0x557225d7e170) at blockdev.c:1717
24
#8 0x0000557223d09013 in qmp_transaction (dev_list=<optimized out>, has_props=<optimized out>, props=0x557225cc7d70, errp=errp@entry=0x7ffe704c0c98) at blockdev.c:2360
25
#9 0x0000557223e32085 in qmp_marshal_transaction (args=<optimized out>, ret=<optimized out>, errp=0x7ffe704c0d08) at qapi/qapi-commands-transaction.c:44
26
#10 0x0000557223ee798c in do_qmp_dispatch (errp=0x7ffe704c0d00, allow_oob=<optimized out>, request=<optimized out>, cmds=0x5572247d3cc0 <qmp_commands>) at qapi/qmp-dispatch.c:132
27
#11 0x0000557223ee798c in qmp_dispatch (cmds=0x5572247d3cc0 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>) at qapi/qmp-dispatch.c:175
28
#12 0x0000557223e06141 in monitor_qmp_dispatch (mon=0x557225c69ff0, req=<optimized out>) at monitor/qmp.c:120
29
#13 0x0000557223e0678a in monitor_qmp_bh_dispatcher (data=<optimized out>) at monitor/qmp.c:209
30
#14 0x0000557223f2f366 in aio_bh_call (bh=0x557225b9dc60) at util/async.c:117
31
#15 0x0000557223f2f366 in aio_bh_poll (ctx=ctx@entry=0x557225b9c840) at util/async.c:117
32
#16 0x0000557223f32754 in aio_dispatch (ctx=0x557225b9c840) at util/aio-posix.c:459
33
#17 0x0000557223f2f242 in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
34
#18 0x00007fa10913467d in g_main_dispatch (context=0x557225c28e80) at gmain.c:3176
35
#19 0x00007fa10913467d in g_main_context_dispatch (context=context@entry=0x557225c28e80) at gmain.c:3829
36
#20 0x0000557223f31808 in glib_pollfds_poll () at util/main-loop.c:219
37
#21 0x0000557223f31808 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:242
38
#22 0x0000557223f31808 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:518
39
#23 0x0000557223d13201 in main_loop () at vl.c:1828
40
#24 0x0000557223bbfb82 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4504
41
42
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779036
43
Signed-off-by: Sergio Lopez <slp@redhat.com>
44
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
45
---
13
---
46
blockdev.c | 21 +++++++++++++++++++++
14
block/vvfat.c | 26 +++++++++++++++++++++++++-
47
1 file changed, 21 insertions(+)
15
1 file changed, 25 insertions(+), 1 deletion(-)
48
16
49
diff --git a/blockdev.c b/blockdev.c
17
diff --git a/block/vvfat.c b/block/vvfat.c
50
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
51
--- a/blockdev.c
19
--- a/block/vvfat.c
52
+++ b/blockdev.c
20
+++ b/block/vvfat.c
53
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
21
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
54
if (state->new_bs) {
22
55
if (state->overlay_appended) {
23
vvfat_close_current_file(s);
56
AioContext *aio_context;
24
57
+ AioContext *tmp_context;
25
+ if (sector_num == s->offset_to_bootsector && nb_sectors == 1) {
58
+ int ret;
26
+ /*
59
27
+ * Write on bootsector. Allow only changing the reserved1 field,
60
aio_context = bdrv_get_aio_context(state->old_bs);
28
+ * used to mark volume dirtiness
61
aio_context_acquire(aio_context);
29
+ */
62
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
30
+ unsigned char *bootsector = s->first_sectors
63
bdrv_ref(state->old_bs); /* we can't let bdrv_set_backind_hd()
31
+ + s->offset_to_bootsector * 0x200;
64
close state->old_bs; we need it */
32
+ /*
65
bdrv_set_backing_hd(state->new_bs, NULL, &error_abort);
33
+ * LATER TODO: if FAT32, this is wrong (see init_directories(),
34
+ * which always creates a FAT16 bootsector)
35
+ */
36
+ const int reserved1_offset = offsetof(bootsector_t, u.fat16.reserved1);
66
+
37
+
67
+ /*
38
+ for (i = 0; i < 0x200; i++) {
68
+ * The call to bdrv_set_backing_hd() above returns state->old_bs to
39
+ if (i != reserved1_offset && bootsector[i] != buf[i]) {
69
+ * the main AioContext. As we're still going to be using it, return
40
+ fprintf(stderr, "Tried to write to protected bootsector\n");
70
+ * it to the AioContext it was before.
41
+ return -1;
71
+ */
42
+ }
72
+ tmp_context = bdrv_get_aio_context(state->old_bs);
43
+ }
73
+ if (aio_context != tmp_context) {
74
+ aio_context_release(aio_context);
75
+ aio_context_acquire(tmp_context);
76
+
44
+
77
+ ret = bdrv_try_set_aio_context(state->old_bs,
45
+ /* Update bootsector with the only updatable byte, and return success */
78
+ aio_context, NULL);
46
+ bootsector[reserved1_offset] = buf[reserved1_offset];
79
+ assert(ret == 0);
47
+ return 0;
48
+ }
80
+
49
+
81
+ aio_context_release(tmp_context);
50
/*
82
+ aio_context_acquire(aio_context);
51
* Some sanity checks:
83
+ }
52
* - do not allow writing to the boot sector
84
+
53
*/
85
bdrv_replace_node(state->new_bs, state->old_bs, &error_abort);
54
-
86
bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */
55
if (sector_num < s->offset_to_fat)
56
return -1;
87
57
88
--
58
--
89
2.20.1
59
2.37.3
90
60
91
61
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Hervé Poussineau <hpoussin@reactos.org>
2
2
3
Includes the following tests:
3
In R/W mode, files with spaces were never created on host side.
4
4
5
- Adding a dirty bitmap.
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1176
6
* RHBZ: 1782175
6
Fixes: c79e243ed67683d6d06692bd7040f7394da178b0
7
7
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
8
- Starting a drive-mirror to an NBD-backed target.
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
* RHBZ: 1746217, 1773517
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
10
Message-Id: <20221010175511.3414357-3-hpoussin@reactos.org>
11
- Aborting an external snapshot transaction.
12
* RHBZ: 1779036
13
14
- Aborting a blockdev backup transaction.
15
* RHBZ: 1782111
16
17
For each one of them, a VM with a number of disks running in an
18
IOThread AioContext is used.
19
20
Signed-off-by: Sergio Lopez <slp@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
12
---
23
tests/qemu-iotests/281 | 247 +++++++++++++++++++++++++++++++++++++
13
block/vvfat.c | 2 +-
24
tests/qemu-iotests/281.out | 5 +
14
1 file changed, 1 insertion(+), 1 deletion(-)
25
tests/qemu-iotests/group | 1 +
26
3 files changed, 253 insertions(+)
27
create mode 100755 tests/qemu-iotests/281
28
create mode 100644 tests/qemu-iotests/281.out
29
15
30
diff --git a/tests/qemu-iotests/281 b/tests/qemu-iotests/281
16
diff --git a/block/vvfat.c b/block/vvfat.c
31
new file mode 100755
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/tests/qemu-iotests/281
35
@@ -XXX,XX +XXX,XX @@
36
+#!/usr/bin/env python
37
+#
38
+# Test cases for blockdev + IOThread interactions
39
+#
40
+# Copyright (C) 2019 Red Hat, Inc.
41
+#
42
+# This program is free software; you can redistribute it and/or modify
43
+# it under the terms of the GNU General Public License as published by
44
+# the Free Software Foundation; either version 2 of the License, or
45
+# (at your option) any later version.
46
+#
47
+# This program is distributed in the hope that it will be useful,
48
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
49
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50
+# GNU General Public License for more details.
51
+#
52
+# You should have received a copy of the GNU General Public License
53
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
54
+#
55
+
56
+import os
57
+import iotests
58
+from iotests import qemu_img
59
+
60
+image_len = 64 * 1024 * 1024
61
+
62
+# Test for RHBZ#1782175
63
+class TestDirtyBitmapIOThread(iotests.QMPTestCase):
64
+ drive0_img = os.path.join(iotests.test_dir, 'drive0.img')
65
+ images = { 'drive0': drive0_img }
66
+
67
+ def setUp(self):
68
+ for name in self.images:
69
+ qemu_img('create', '-f', iotests.imgfmt,
70
+ self.images[name], str(image_len))
71
+
72
+ self.vm = iotests.VM()
73
+ self.vm.add_object('iothread,id=iothread0')
74
+
75
+ for name in self.images:
76
+ self.vm.add_blockdev('driver=file,filename=%s,node-name=file_%s'
77
+ % (self.images[name], name))
78
+ self.vm.add_blockdev('driver=qcow2,file=file_%s,node-name=%s'
79
+ % (name, name))
80
+
81
+ self.vm.launch()
82
+ self.vm.qmp('x-blockdev-set-iothread',
83
+ node_name='drive0', iothread='iothread0',
84
+ force=True)
85
+
86
+ def tearDown(self):
87
+ self.vm.shutdown()
88
+ for name in self.images:
89
+ os.remove(self.images[name])
90
+
91
+ def test_add_dirty_bitmap(self):
92
+ result = self.vm.qmp(
93
+ 'block-dirty-bitmap-add',
94
+ node='drive0',
95
+ name='bitmap1',
96
+ persistent=True,
97
+ )
98
+
99
+ self.assert_qmp(result, 'return', {})
100
+
101
+
102
+# Test for RHBZ#1746217 & RHBZ#1773517
103
+class TestNBDMirrorIOThread(iotests.QMPTestCase):
104
+ nbd_sock = os.path.join(iotests.sock_dir, 'nbd.sock')
105
+ drive0_img = os.path.join(iotests.test_dir, 'drive0.img')
106
+ mirror_img = os.path.join(iotests.test_dir, 'mirror.img')
107
+ images = { 'drive0': drive0_img, 'mirror': mirror_img }
108
+
109
+ def setUp(self):
110
+ for name in self.images:
111
+ qemu_img('create', '-f', iotests.imgfmt,
112
+ self.images[name], str(image_len))
113
+
114
+ self.vm_src = iotests.VM(path_suffix='src')
115
+ self.vm_src.add_object('iothread,id=iothread0')
116
+ self.vm_src.add_blockdev('driver=file,filename=%s,node-name=file0'
117
+ % (self.drive0_img))
118
+ self.vm_src.add_blockdev('driver=qcow2,file=file0,node-name=drive0')
119
+ self.vm_src.launch()
120
+ self.vm_src.qmp('x-blockdev-set-iothread',
121
+ node_name='drive0', iothread='iothread0',
122
+ force=True)
123
+
124
+ self.vm_tgt = iotests.VM(path_suffix='tgt')
125
+ self.vm_tgt.add_object('iothread,id=iothread0')
126
+ self.vm_tgt.add_blockdev('driver=file,filename=%s,node-name=file0'
127
+ % (self.mirror_img))
128
+ self.vm_tgt.add_blockdev('driver=qcow2,file=file0,node-name=drive0')
129
+ self.vm_tgt.launch()
130
+ self.vm_tgt.qmp('x-blockdev-set-iothread',
131
+ node_name='drive0', iothread='iothread0',
132
+ force=True)
133
+
134
+ def tearDown(self):
135
+ self.vm_src.shutdown()
136
+ self.vm_tgt.shutdown()
137
+ for name in self.images:
138
+ os.remove(self.images[name])
139
+
140
+ def test_nbd_mirror(self):
141
+ result = self.vm_tgt.qmp(
142
+ 'nbd-server-start',
143
+ addr={
144
+ 'type': 'unix',
145
+ 'data': { 'path': self.nbd_sock }
146
+ }
147
+ )
148
+ self.assert_qmp(result, 'return', {})
149
+
150
+ result = self.vm_tgt.qmp(
151
+ 'nbd-server-add',
152
+ device='drive0',
153
+ writable=True
154
+ )
155
+ self.assert_qmp(result, 'return', {})
156
+
157
+ result = self.vm_src.qmp(
158
+ 'drive-mirror',
159
+ device='drive0',
160
+ target='nbd+unix:///drive0?socket=' + self.nbd_sock,
161
+ sync='full',
162
+ mode='existing',
163
+ speed=64*1024*1024,
164
+ job_id='j1'
165
+ )
166
+ self.assert_qmp(result, 'return', {})
167
+
168
+ self.vm_src.event_wait(name="BLOCK_JOB_READY")
169
+
170
+
171
+# Test for RHBZ#1779036
172
+class TestExternalSnapshotAbort(iotests.QMPTestCase):
173
+ drive0_img = os.path.join(iotests.test_dir, 'drive0.img')
174
+ snapshot_img = os.path.join(iotests.test_dir, 'snapshot.img')
175
+ images = { 'drive0': drive0_img, 'snapshot': snapshot_img }
176
+
177
+ def setUp(self):
178
+ for name in self.images:
179
+ qemu_img('create', '-f', iotests.imgfmt,
180
+ self.images[name], str(image_len))
181
+
182
+ self.vm = iotests.VM()
183
+ self.vm.add_object('iothread,id=iothread0')
184
+ self.vm.add_blockdev('driver=file,filename=%s,node-name=file0'
185
+ % (self.drive0_img))
186
+ self.vm.add_blockdev('driver=qcow2,file=file0,node-name=drive0')
187
+ self.vm.launch()
188
+ self.vm.qmp('x-blockdev-set-iothread',
189
+ node_name='drive0', iothread='iothread0',
190
+ force=True)
191
+
192
+ def tearDown(self):
193
+ self.vm.shutdown()
194
+ for name in self.images:
195
+ os.remove(self.images[name])
196
+
197
+ def test_external_snapshot_abort(self):
198
+ # Use a two actions transaction with a bogus values on the second
199
+ # one to trigger an abort of the transaction.
200
+ result = self.vm.qmp('transaction', actions=[
201
+ {
202
+ 'type': 'blockdev-snapshot-sync',
203
+ 'data': { 'node-name': 'drive0',
204
+ 'snapshot-file': self.snapshot_img,
205
+ 'snapshot-node-name': 'snap1',
206
+ 'mode': 'absolute-paths',
207
+ 'format': 'qcow2' }
208
+ },
209
+ {
210
+ 'type': 'blockdev-snapshot-sync',
211
+ 'data': { 'node-name': 'drive0',
212
+ 'snapshot-file': '/fakesnapshot',
213
+ 'snapshot-node-name': 'snap2',
214
+ 'mode': 'absolute-paths',
215
+ 'format': 'qcow2' }
216
+ },
217
+ ])
218
+
219
+ # Crashes on failure, we expect this error.
220
+ self.assert_qmp(result, 'error/class', 'GenericError')
221
+
222
+
223
+# Test for RHBZ#1782111
224
+class TestBlockdevBackupAbort(iotests.QMPTestCase):
225
+ drive0_img = os.path.join(iotests.test_dir, 'drive0.img')
226
+ drive1_img = os.path.join(iotests.test_dir, 'drive1.img')
227
+ snap0_img = os.path.join(iotests.test_dir, 'snap0.img')
228
+ snap1_img = os.path.join(iotests.test_dir, 'snap1.img')
229
+ images = { 'drive0': drive0_img,
230
+ 'drive1': drive1_img,
231
+ 'snap0': snap0_img,
232
+ 'snap1': snap1_img }
233
+
234
+ def setUp(self):
235
+ for name in self.images:
236
+ qemu_img('create', '-f', iotests.imgfmt,
237
+ self.images[name], str(image_len))
238
+
239
+ self.vm = iotests.VM()
240
+ self.vm.add_object('iothread,id=iothread0')
241
+ self.vm.add_device('virtio-scsi,iothread=iothread0')
242
+
243
+ for name in self.images:
244
+ self.vm.add_blockdev('driver=file,filename=%s,node-name=file_%s'
245
+ % (self.images[name], name))
246
+ self.vm.add_blockdev('driver=qcow2,file=file_%s,node-name=%s'
247
+ % (name, name))
248
+
249
+ self.vm.add_device('scsi-hd,drive=drive0')
250
+ self.vm.add_device('scsi-hd,drive=drive1')
251
+ self.vm.launch()
252
+
253
+ def tearDown(self):
254
+ self.vm.shutdown()
255
+ for name in self.images:
256
+ os.remove(self.images[name])
257
+
258
+ def test_blockdev_backup_abort(self):
259
+ # Use a two actions transaction with a bogus values on the second
260
+ # one to trigger an abort of the transaction.
261
+ result = self.vm.qmp('transaction', actions=[
262
+ {
263
+ 'type': 'blockdev-backup',
264
+ 'data': { 'device': 'drive0',
265
+ 'target': 'snap0',
266
+ 'sync': 'full',
267
+ 'job-id': 'j1' }
268
+ },
269
+ {
270
+ 'type': 'blockdev-backup',
271
+ 'data': { 'device': 'drive1',
272
+ 'target': 'snap1',
273
+ 'sync': 'full' }
274
+ },
275
+ ])
276
+
277
+ # Hangs on failure, we expect this error.
278
+ self.assert_qmp(result, 'error/class', 'GenericError')
279
+
280
+if __name__ == '__main__':
281
+ iotests.main(supported_fmts=['qcow2'],
282
+ supported_protocols=['file'])
283
diff --git a/tests/qemu-iotests/281.out b/tests/qemu-iotests/281.out
284
new file mode 100644
285
index XXXXXXX..XXXXXXX
286
--- /dev/null
287
+++ b/tests/qemu-iotests/281.out
288
@@ -XXX,XX +XXX,XX @@
289
+....
290
+----------------------------------------------------------------------
291
+Ran 4 tests
292
+
293
+OK
294
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
295
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
296
--- a/tests/qemu-iotests/group
18
--- a/block/vvfat.c
297
+++ b/tests/qemu-iotests/group
19
+++ b/block/vvfat.c
298
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static bool valid_filename(const unsigned char *name)
299
277 rw quick
21
(c >= 'A' && c <= 'Z') ||
300
279 rw backing quick
22
(c >= 'a' && c <= 'z') ||
301
280 rw migration quick
23
c > 127 ||
302
+281 rw quick
24
- strchr("$%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
25
+ strchr(" $%'-_@~`!(){}^#&.+,;=[]", c) != NULL))
26
{
27
return false;
28
}
303
--
29
--
304
2.20.1
30
2.37.3
305
31
306
32
diff view generated by jsdifflib
New patch
1
From: Sam Li <faithilikerun@gmail.com>
1
2
3
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1193
4
5
The commit "Use io_uring_register_ring_fd() to skip fd operations" broke
6
when booting a guest with iothread and io_uring. That is because the
7
io_uring_register_ring_fd() call is made from the main thread instead of
8
IOThread where io_uring_submit() is called. It can not be guaranteed
9
to register the ring fd in the correct thread or unregister the same ring
10
fd if the IOThread is disabled. This optimization is not critical so we
11
will revert previous commit.
12
13
This reverts commit e2848bc574fe2715c694bf8fe9a1ba7f78a1125a
14
and 77e3f038af1764983087e3551a0fde9951952c4d.
15
16
Cc: qemu-stable@nongnu.org
17
Signed-off-by: Sam Li <faithilikerun@gmail.com>
18
Message-Id: <20220924144815.5591-1-faithilikerun@gmail.com>
19
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
20
Tested-by: Dario Faggioli <dfaggioli@suse.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
23
block/io_uring.c | 13 +------------
24
meson.build | 1 -
25
2 files changed, 1 insertion(+), 13 deletions(-)
26
27
diff --git a/block/io_uring.c b/block/io_uring.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block/io_uring.c
30
+++ b/block/io_uring.c
31
@@ -XXX,XX +XXX,XX @@
32
#include "qemu/osdep.h"
33
#include <liburing.h>
34
#include "block/aio.h"
35
-#include "qemu/error-report.h"
36
#include "qemu/queue.h"
37
#include "block/block.h"
38
#include "block/raw-aio.h"
39
@@ -XXX,XX +XXX,XX @@
40
#include "qapi/error.h"
41
#include "trace.h"
42
43
-
44
/* io_uring ring size */
45
#define MAX_ENTRIES 128
46
47
@@ -XXX,XX +XXX,XX @@ LuringState *luring_init(Error **errp)
48
}
49
50
ioq_init(&s->io_q);
51
-#ifdef CONFIG_LIBURING_REGISTER_RING_FD
52
- if (io_uring_register_ring_fd(&s->ring) < 0) {
53
- /*
54
- * Only warn about this error: we will fallback to the non-optimized
55
- * io_uring operations.
56
- */
57
- warn_report("failed to register linux io_uring ring file descriptor");
58
- }
59
-#endif
60
-
61
return s;
62
+
63
}
64
65
void luring_cleanup(LuringState *s)
66
diff --git a/meson.build b/meson.build
67
index XXXXXXX..XXXXXXX 100644
68
--- a/meson.build
69
+++ b/meson.build
70
@@ -XXX,XX +XXX,XX @@ config_host_data.set('CONFIG_LIBNFS', libnfs.found())
71
config_host_data.set('CONFIG_LIBSSH', libssh.found())
72
config_host_data.set('CONFIG_LINUX_AIO', libaio.found())
73
config_host_data.set('CONFIG_LINUX_IO_URING', linux_io_uring.found())
74
-config_host_data.set('CONFIG_LIBURING_REGISTER_RING_FD', cc.has_function('io_uring_register_ring_fd', prefix: '#include <liburing.h>', dependencies:linux_io_uring))
75
config_host_data.set('CONFIG_LIBPMEM', libpmem.found())
76
config_host_data.set('CONFIG_NUMA', numa.found())
77
config_host_data.set('CONFIG_OPENGL', opengl.found())
78
--
79
2.37.3
diff view generated by jsdifflib
New patch
1
From: Li Feng <fengli@smartx.com>
1
2
3
If the os is not installed and doesn't have the virtio guest driver,
4
the vhost dev isn't started, so the dev->vdev is NULL.
5
6
Reproduce: mount a Win 2019 iso, go into the install ui, then resize
7
the virtio-blk device, qemu crash.
8
9
Signed-off-by: Li Feng <fengli@smartx.com>
10
Message-Id: <20220919121816.3252223-1-fengli@smartx.com>
11
Reviewed-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
hw/block/vhost-user-blk.c | 4 ++++
16
1 file changed, 4 insertions(+)
17
18
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/block/vhost-user-blk.c
21
+++ b/hw/block/vhost-user-blk.c
22
@@ -XXX,XX +XXX,XX @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
23
VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
24
Error *local_err = NULL;
25
26
+ if (!dev->started) {
27
+ return 0;
28
+ }
29
+
30
ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
31
vdev->config_len, &local_err);
32
if (ret < 0) {
33
--
34
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Unfortunately not all filters use .file child as filtered child. Two
4
exclusions are mirror_top and commit_top. Happily they both are private
5
filters. Bad thing is that this inconsistency is observable through qmp
6
commands query-block / query-named-block-nodes. So, could we just
7
change mirror_top and commit_top to use file child as all other filter
8
driver is an open question. Probably, we could do that with some kind
9
of deprecation period, but how to warn users during it?
10
11
For now, let's just add a field so we can distinguish them in generic
12
code, it will be used in further commits.
13
14
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Message-Id: <20220726201134.924743-2-vsementsov@yandex-team.ru>
17
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
include/block/block_int-common.h | 13 +++++++++++++
21
block/commit.c | 1 +
22
block/mirror.c | 1 +
23
3 files changed, 15 insertions(+)
24
25
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block_int-common.h
28
+++ b/include/block/block_int-common.h
29
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
30
* (And this filtered child must then be bs->file or bs->backing.)
31
*/
32
bool is_filter;
33
+ /*
34
+ * Only make sense for filter drivers, for others must be false.
35
+ * If true, filtered child is bs->backing. Otherwise it's bs->file.
36
+ * Only two internal filters use bs->backing as filtered child and has this
37
+ * field set to true: mirror_top and commit_top.
38
+ *
39
+ * Never create any more such filters!
40
+ *
41
+ * TODO: imagine how to deprecate this behavior and make all filters work
42
+ * similarly using bs->file as filtered child.
43
+ */
44
+ bool filtered_child_is_backing;
45
+
46
/*
47
* Set to true if the BlockDriver is a format driver. Format nodes
48
* generally do not expect their children to be other format nodes
49
diff --git a/block/commit.c b/block/commit.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/block/commit.c
52
+++ b/block/commit.c
53
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_commit_top = {
54
.bdrv_child_perm = bdrv_commit_top_child_perm,
55
56
.is_filter = true,
57
+ .filtered_child_is_backing = true,
58
};
59
60
void commit_start(const char *job_id, BlockDriverState *bs,
61
diff --git a/block/mirror.c b/block/mirror.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/block/mirror.c
64
+++ b/block/mirror.c
65
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_mirror_top = {
66
.bdrv_child_perm = bdrv_mirror_top_child_perm,
67
68
.is_filter = true,
69
+ .filtered_child_is_backing = true,
70
};
71
72
static BlockJob *mirror_start_job(
73
--
74
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Almost all drivers call bdrv_open_child() similarly. Let's create a
4
helper for this.
5
6
The only not updated drivers that call bdrv_open_child() to set
7
bs->file are raw-format and snapshot-access:
8
raw-format sometimes want to have filtered child but
9
don't set drv->is_filter to true.
10
snapshot-access wants only DATA | PRIMARY
11
12
Possibly we should implement drv->is_filter_func() handler, to consider
13
raw-format as filter when it works as filter.. But it's another story.
14
15
Note also, that we decrease assignments to bs->file in code: it helps
16
us restrict modifying this field in further commit.
17
18
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
19
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
20
Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
24
include/block/block-global-state.h | 3 +++
25
block.c | 21 +++++++++++++++++++++
26
block/blkdebug.c | 9 +++------
27
block/blklogwrites.c | 7 ++-----
28
block/blkreplay.c | 7 ++-----
29
block/blkverify.c | 9 +++------
30
block/bochs.c | 7 +++----
31
block/cloop.c | 7 +++----
32
block/copy-before-write.c | 9 ++++-----
33
block/copy-on-read.c | 9 ++++-----
34
block/crypto.c | 11 ++++++-----
35
block/dmg.c | 7 +++----
36
block/filter-compress.c | 8 +++-----
37
block/parallels.c | 7 +++----
38
block/preallocate.c | 9 ++++-----
39
block/qcow.c | 6 ++----
40
block/qcow2.c | 8 ++++----
41
block/qed.c | 8 ++++----
42
block/replication.c | 8 +++-----
43
block/throttle.c | 8 +++-----
44
block/vdi.c | 7 +++----
45
block/vhdx.c | 7 +++----
46
block/vmdk.c | 7 +++----
47
block/vpc.c | 7 +++----
48
24 files changed, 95 insertions(+), 101 deletions(-)
49
50
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
51
index XXXXXXX..XXXXXXX 100644
52
--- a/include/block/block-global-state.h
53
+++ b/include/block/block-global-state.h
54
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
55
const BdrvChildClass *child_class,
56
BdrvChildRole child_role,
57
bool allow_none, Error **errp);
58
+int bdrv_open_file_child(const char *filename,
59
+ QDict *options, const char *bdref_key,
60
+ BlockDriverState *parent, Error **errp);
61
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
62
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
63
Error **errp);
64
diff --git a/block.c b/block.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/block.c
67
+++ b/block.c
68
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_open_child(const char *filename,
69
errp);
70
}
71
72
+/*
73
+ * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
74
+ */
75
+int bdrv_open_file_child(const char *filename,
76
+ QDict *options, const char *bdref_key,
77
+ BlockDriverState *parent, Error **errp)
78
+{
79
+ BdrvChildRole role;
80
+
81
+ /* commit_top and mirror_top don't use this function */
82
+ assert(!parent->drv->filtered_child_is_backing);
83
+
84
+ role = parent->drv->is_filter ?
85
+ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
86
+
87
+ parent->file = bdrv_open_child(filename, options, bdref_key, parent,
88
+ &child_of_bds, role, false, errp);
89
+
90
+ return parent->file ? 0 : -EINVAL;
91
+}
92
+
93
/*
94
* TODO Future callers may need to specify parent/child_class in order for
95
* option inheritance to work. Existing callers use it for the root node.
96
diff --git a/block/blkdebug.c b/block/blkdebug.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/block/blkdebug.c
99
+++ b/block/blkdebug.c
100
@@ -XXX,XX +XXX,XX @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
101
}
102
103
/* Open the image file */
104
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
105
- bs, &child_of_bds,
106
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
107
- false, errp);
108
- if (!bs->file) {
109
- ret = -EINVAL;
110
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
111
+ bs, errp);
112
+ if (ret < 0) {
113
goto out;
114
}
115
116
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/blklogwrites.c
119
+++ b/block/blklogwrites.c
120
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
121
}
122
123
/* Open the file */
124
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
125
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
126
- errp);
127
- if (!bs->file) {
128
- ret = -EINVAL;
129
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
130
+ if (ret < 0) {
131
goto fail;
132
}
133
134
diff --git a/block/blkreplay.c b/block/blkreplay.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/block/blkreplay.c
137
+++ b/block/blkreplay.c
138
@@ -XXX,XX +XXX,XX @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
139
int ret;
140
141
/* Open the image file */
142
- bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
143
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
144
- false, errp);
145
- if (!bs->file) {
146
- ret = -EINVAL;
147
+ ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
148
+ if (ret < 0) {
149
goto fail;
150
}
151
152
diff --git a/block/blkverify.c b/block/blkverify.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/block/blkverify.c
155
+++ b/block/blkverify.c
156
@@ -XXX,XX +XXX,XX @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
157
}
158
159
/* Open the raw file */
160
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
161
- bs, &child_of_bds,
162
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
163
- false, errp);
164
- if (!bs->file) {
165
- ret = -EINVAL;
166
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
167
+ bs, errp);
168
+ if (ret < 0) {
169
goto fail;
170
}
171
172
diff --git a/block/bochs.c b/block/bochs.c
173
index XXXXXXX..XXXXXXX 100644
174
--- a/block/bochs.c
175
+++ b/block/bochs.c
176
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
177
return ret;
178
}
179
180
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
181
- BDRV_CHILD_IMAGE, false, errp);
182
- if (!bs->file) {
183
- return -EINVAL;
184
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
185
+ if (ret < 0) {
186
+ return ret;
187
}
188
189
ret = bdrv_pread(bs->file, 0, sizeof(bochs), &bochs, 0);
190
diff --git a/block/cloop.c b/block/cloop.c
191
index XXXXXXX..XXXXXXX 100644
192
--- a/block/cloop.c
193
+++ b/block/cloop.c
194
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
195
return ret;
196
}
197
198
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
199
- BDRV_CHILD_IMAGE, false, errp);
200
- if (!bs->file) {
201
- return -EINVAL;
202
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
203
+ if (ret < 0) {
204
+ return ret;
205
}
206
207
/* read header */
208
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
209
index XXXXXXX..XXXXXXX 100644
210
--- a/block/copy-before-write.c
211
+++ b/block/copy-before-write.c
212
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
213
int64_t cluster_size;
214
g_autoptr(BlockdevOptions) full_opts = NULL;
215
BlockdevOptionsCbw *opts;
216
+ int ret;
217
218
full_opts = cbw_parse_options(options, errp);
219
if (!full_opts) {
220
@@ -XXX,XX +XXX,XX @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
221
assert(full_opts->driver == BLOCKDEV_DRIVER_COPY_BEFORE_WRITE);
222
opts = &full_opts->u.copy_before_write;
223
224
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
225
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
226
- false, errp);
227
- if (!bs->file) {
228
- return -EINVAL;
229
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
230
+ if (ret < 0) {
231
+ return ret;
232
}
233
234
s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
235
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
236
index XXXXXXX..XXXXXXX 100644
237
--- a/block/copy-on-read.c
238
+++ b/block/copy-on-read.c
239
@@ -XXX,XX +XXX,XX @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
240
BDRVStateCOR *state = bs->opaque;
241
/* Find a bottom node name, if any */
242
const char *bottom_node = qdict_get_try_str(options, "bottom");
243
+ int ret;
244
245
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
246
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
247
- false, errp);
248
- if (!bs->file) {
249
- return -EINVAL;
250
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
251
+ if (ret < 0) {
252
+ return ret;
253
}
254
255
bs->supported_read_flags = BDRV_REQ_PREFETCH;
256
diff --git a/block/crypto.c b/block/crypto.c
257
index XXXXXXX..XXXXXXX 100644
258
--- a/block/crypto.c
259
+++ b/block/crypto.c
260
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
261
{
262
BlockCrypto *crypto = bs->opaque;
263
QemuOpts *opts = NULL;
264
- int ret = -EINVAL;
265
+ int ret;
266
QCryptoBlockOpenOptions *open_opts = NULL;
267
unsigned int cflags = 0;
268
QDict *cryptoopts = NULL;
269
270
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
271
- BDRV_CHILD_IMAGE, false, errp);
272
- if (!bs->file) {
273
- return -EINVAL;
274
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
275
+ if (ret < 0) {
276
+ return ret;
277
}
278
279
bs->supported_write_flags = BDRV_REQ_FUA &
280
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
281
282
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
283
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
284
+ ret = -EINVAL;
285
goto cleanup;
286
}
287
288
@@ -XXX,XX +XXX,XX @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
289
290
open_opts = block_crypto_open_opts_init(cryptoopts, errp);
291
if (!open_opts) {
292
+ ret = -EINVAL;
293
goto cleanup;
294
}
295
296
diff --git a/block/dmg.c b/block/dmg.c
297
index XXXXXXX..XXXXXXX 100644
298
--- a/block/dmg.c
299
+++ b/block/dmg.c
300
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
301
return ret;
302
}
303
304
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
305
- BDRV_CHILD_IMAGE, false, errp);
306
- if (!bs->file) {
307
- return -EINVAL;
308
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
309
+ if (ret < 0) {
310
+ return ret;
311
}
312
313
block_module_load_one("dmg-bz2");
314
diff --git a/block/filter-compress.c b/block/filter-compress.c
315
index XXXXXXX..XXXXXXX 100644
316
--- a/block/filter-compress.c
317
+++ b/block/filter-compress.c
318
@@ -XXX,XX +XXX,XX @@
319
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
320
Error **errp)
321
{
322
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
323
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
324
- false, errp);
325
- if (!bs->file) {
326
- return -EINVAL;
327
+ int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
328
+ if (ret < 0) {
329
+ return ret;
330
}
331
332
if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
333
diff --git a/block/parallels.c b/block/parallels.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/block/parallels.c
336
+++ b/block/parallels.c
337
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
338
Error *local_err = NULL;
339
char *buf;
340
341
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
342
- BDRV_CHILD_IMAGE, false, errp);
343
- if (!bs->file) {
344
- return -EINVAL;
345
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
346
+ if (ret < 0) {
347
+ return ret;
348
}
349
350
ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
351
diff --git a/block/preallocate.c b/block/preallocate.c
352
index XXXXXXX..XXXXXXX 100644
353
--- a/block/preallocate.c
354
+++ b/block/preallocate.c
355
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
356
Error **errp)
357
{
358
BDRVPreallocateState *s = bs->opaque;
359
+ int ret;
360
361
/*
362
* s->data_end and friends should be initialized on permission update.
363
@@ -XXX,XX +XXX,XX @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
364
*/
365
s->file_end = s->zero_start = s->data_end = -EINVAL;
366
367
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
368
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
369
- false, errp);
370
- if (!bs->file) {
371
- return -EINVAL;
372
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
373
+ if (ret < 0) {
374
+ return ret;
375
}
376
377
if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
378
diff --git a/block/qcow.c b/block/qcow.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/block/qcow.c
381
+++ b/block/qcow.c
382
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
383
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
384
encryptfmt = qdict_get_try_str(encryptopts, "format");
385
386
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
387
- BDRV_CHILD_IMAGE, false, errp);
388
- if (!bs->file) {
389
- ret = -EINVAL;
390
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
391
+ if (ret < 0) {
392
goto fail;
393
}
394
395
diff --git a/block/qcow2.c b/block/qcow2.c
396
index XXXXXXX..XXXXXXX 100644
397
--- a/block/qcow2.c
398
+++ b/block/qcow2.c
399
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
400
.errp = errp,
401
.ret = -EINPROGRESS
402
};
403
+ int ret;
404
405
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
406
- BDRV_CHILD_IMAGE, false, errp);
407
- if (!bs->file) {
408
- return -EINVAL;
409
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
410
+ if (ret < 0) {
411
+ return ret;
412
}
413
414
/* Initialise locks */
415
diff --git a/block/qed.c b/block/qed.c
416
index XXXXXXX..XXXXXXX 100644
417
--- a/block/qed.c
418
+++ b/block/qed.c
419
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
420
.errp = errp,
421
.ret = -EINPROGRESS
422
};
423
+ int ret;
424
425
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
426
- BDRV_CHILD_IMAGE, false, errp);
427
- if (!bs->file) {
428
- return -EINVAL;
429
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
430
+ if (ret < 0) {
431
+ return ret;
432
}
433
434
bdrv_qed_init_state(bs);
435
diff --git a/block/replication.c b/block/replication.c
436
index XXXXXXX..XXXXXXX 100644
437
--- a/block/replication.c
438
+++ b/block/replication.c
439
@@ -XXX,XX +XXX,XX @@ static int replication_open(BlockDriverState *bs, QDict *options,
440
const char *mode;
441
const char *top_id;
442
443
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
444
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
445
- false, errp);
446
- if (!bs->file) {
447
- return -EINVAL;
448
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
449
+ if (ret < 0) {
450
+ return ret;
451
}
452
453
ret = -EINVAL;
454
diff --git a/block/throttle.c b/block/throttle.c
455
index XXXXXXX..XXXXXXX 100644
456
--- a/block/throttle.c
457
+++ b/block/throttle.c
458
@@ -XXX,XX +XXX,XX @@ static int throttle_open(BlockDriverState *bs, QDict *options,
459
char *group;
460
int ret;
461
462
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
463
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
464
- false, errp);
465
- if (!bs->file) {
466
- return -EINVAL;
467
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
468
+ if (ret < 0) {
469
+ return ret;
470
}
471
bs->supported_write_flags = bs->file->bs->supported_write_flags |
472
BDRV_REQ_WRITE_UNCHANGED;
473
diff --git a/block/vdi.c b/block/vdi.c
474
index XXXXXXX..XXXXXXX 100644
475
--- a/block/vdi.c
476
+++ b/block/vdi.c
477
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
478
int ret;
479
QemuUUID uuid_link, uuid_parent;
480
481
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
482
- BDRV_CHILD_IMAGE, false, errp);
483
- if (!bs->file) {
484
- return -EINVAL;
485
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
486
+ if (ret < 0) {
487
+ return ret;
488
}
489
490
logout("\n");
491
diff --git a/block/vhdx.c b/block/vhdx.c
492
index XXXXXXX..XXXXXXX 100644
493
--- a/block/vhdx.c
494
+++ b/block/vhdx.c
495
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
496
uint64_t signature;
497
Error *local_err = NULL;
498
499
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
500
- BDRV_CHILD_IMAGE, false, errp);
501
- if (!bs->file) {
502
- return -EINVAL;
503
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
504
+ if (ret < 0) {
505
+ return ret;
506
}
507
508
s->bat = NULL;
509
diff --git a/block/vmdk.c b/block/vmdk.c
510
index XXXXXXX..XXXXXXX 100644
511
--- a/block/vmdk.c
512
+++ b/block/vmdk.c
513
@@ -XXX,XX +XXX,XX @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
514
BDRVVmdkState *s = bs->opaque;
515
uint32_t magic;
516
517
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
518
- BDRV_CHILD_IMAGE, false, errp);
519
- if (!bs->file) {
520
- return -EINVAL;
521
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
522
+ if (ret < 0) {
523
+ return ret;
524
}
525
526
buf = vmdk_read_desc(bs->file, 0, errp);
527
diff --git a/block/vpc.c b/block/vpc.c
528
index XXXXXXX..XXXXXXX 100644
529
--- a/block/vpc.c
530
+++ b/block/vpc.c
531
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
532
int ret;
533
int64_t bs_size;
534
535
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
536
- BDRV_CHILD_IMAGE, false, errp);
537
- if (!bs->file) {
538
- return -EINVAL;
539
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
540
+ if (ret < 0) {
541
+ return ret;
542
}
543
544
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
545
--
546
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
We don't need to remove bs->file, generic layer takes care of it. No
4
other driver cares to remove bs->file on failure by hand.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220726201134.924743-4-vsementsov@yandex-team.ru>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/blklogwrites.c | 4 ----
13
1 file changed, 4 deletions(-)
14
15
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/blklogwrites.c
18
+++ b/block/blklogwrites.c
19
@@ -XXX,XX +XXX,XX @@ fail_log:
20
s->log_file = NULL;
21
}
22
fail:
23
- if (ret < 0) {
24
- bdrv_unref_child(bs, bs->file);
25
- bs->file = NULL;
26
- }
27
qemu_opts_del(opts);
28
return ret;
29
}
30
--
31
2.37.3
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
The python code already contains a possibility to skip tests if the
3
test_parallel_perm_update() does two things that we are going to
4
corresponding driver is not available in the qemu binary - use it
4
restrict in the near future:
5
in more spots to avoid that the tests are failing if the driver has
6
been disabled.
7
5
8
While we're at it, we can now also remove some of the old checks that
6
1. It updates bs->file field by hand. bs->file will be managed
9
were using iotests.supports_quorum() - and which were apparently not
7
automatically by generic code (together with bs->children list).
10
working as expected since the tests aborted instead of being skipped
11
when "quorum" was missing in the QEMU binary.
12
8
13
Signed-off-by: Thomas Huth <thuth@redhat.com>
9
Let's better refactor our "tricky" bds to have own state where one
10
of children is linked as "selected".
11
This also looks less "tricky", so avoid using this word.
12
13
2. It create FILTERED children that are not PRIMARY. Except for tests
14
all FILTERED children in the Qemu block layer are always PRIMARY as
15
well. We are going to formalize this rule, so let's better use DATA
16
children here.
17
18
3. It creates more than one FILTERED child, which is already abandoned
19
in BDRV_CHILD_FILTERED's description.
20
21
While being here, update the picture to better correspond to the test
22
code.
23
24
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
25
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
26
Message-Id: <20220726201134.924743-5-vsementsov@yandex-team.ru>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
27
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
28
---
16
tests/qemu-iotests/030 | 4 +---
29
tests/unit/test-bdrv-graph-mod.c | 80 +++++++++++++++++++-------------
17
tests/qemu-iotests/040 | 2 ++
30
1 file changed, 49 insertions(+), 31 deletions(-)
18
tests/qemu-iotests/041 | 39 +++------------------------------------
19
tests/qemu-iotests/245 | 2 ++
20
4 files changed, 8 insertions(+), 39 deletions(-)
21
31
22
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
32
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
23
index XXXXXXX..XXXXXXX 100755
24
--- a/tests/qemu-iotests/030
25
+++ b/tests/qemu-iotests/030
26
@@ -XXX,XX +XXX,XX @@ class TestQuorum(iotests.QMPTestCase):
27
children = []
28
backing = []
29
30
+ @iotests.skip_if_unsupported(['quorum'])
31
def setUp(self):
32
opts = ['driver=quorum', 'vote-threshold=2']
33
34
@@ -XXX,XX +XXX,XX @@ class TestQuorum(iotests.QMPTestCase):
35
os.remove(img)
36
37
def test_stream_quorum(self):
38
- if not iotests.supports_quorum():
39
- return
40
-
41
self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]),
42
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]),
43
'image file map matches backing file before streaming')
44
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
45
index XXXXXXX..XXXXXXX 100755
46
--- a/tests/qemu-iotests/040
47
+++ b/tests/qemu-iotests/040
48
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
49
self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
50
self.assertEqual(-1, qemu_io('-f', 'raw', '-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
51
52
+ @iotests.skip_if_unsupported(['throttle'])
53
def test_commit_with_filter_and_quit(self):
54
result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
55
self.assert_qmp(result, 'return', {})
56
@@ -XXX,XX +XXX,XX @@ class TestSingleDrive(ImageCommitTestCase):
57
self.has_quit = True
58
59
# Same as above, but this time we add the filter after starting the job
60
+ @iotests.skip_if_unsupported(['throttle'])
61
def test_commit_plus_filter_and_quit(self):
62
result = self.vm.qmp('object-add', qom_type='throttle-group', id='tg')
63
self.assert_qmp(result, 'return', {})
64
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
65
index XXXXXXX..XXXXXXX 100755
66
--- a/tests/qemu-iotests/041
67
+++ b/tests/qemu-iotests/041
68
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
69
image_len = 1 * 1024 * 1024 # MB
70
IMAGES = [ quorum_img1, quorum_img2, quorum_img3 ]
71
72
+ @iotests.skip_if_unsupported(['quorum'])
73
def setUp(self):
74
self.vm = iotests.VM()
75
76
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
77
#assemble the quorum block device from the individual files
78
args = { "driver": "quorum", "node-name": "quorum0",
79
"vote-threshold": 2, "children": [ "img0", "img1", "img2" ] }
80
- if iotests.supports_quorum():
81
- result = self.vm.qmp("blockdev-add", **args)
82
- self.assert_qmp(result, 'return', {})
83
+ result = self.vm.qmp("blockdev-add", **args)
84
+ self.assert_qmp(result, 'return', {})
85
86
87
def tearDown(self):
88
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
89
pass
90
91
def test_complete(self):
92
- if not iotests.supports_quorum():
93
- return
94
-
95
self.assert_no_active_block_jobs()
96
97
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
98
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
99
'target image does not match source after mirroring')
100
101
def test_cancel(self):
102
- if not iotests.supports_quorum():
103
- return
104
-
105
self.assert_no_active_block_jobs()
106
107
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
108
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
109
self.vm.shutdown()
110
111
def test_cancel_after_ready(self):
112
- if not iotests.supports_quorum():
113
- return
114
-
115
self.assert_no_active_block_jobs()
116
117
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
118
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
119
'target image does not match source after mirroring')
120
121
def test_pause(self):
122
- if not iotests.supports_quorum():
123
- return
124
-
125
self.assert_no_active_block_jobs()
126
127
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
128
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
129
'target image does not match source after mirroring')
130
131
def test_medium_not_found(self):
132
- if not iotests.supports_quorum():
133
- return
134
-
135
if iotests.qemu_default_machine != 'pc':
136
return
137
138
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
139
self.assert_qmp(result, 'error/class', 'GenericError')
140
141
def test_image_not_found(self):
142
- if not iotests.supports_quorum():
143
- return
144
-
145
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
146
sync='full', node_name='repair0', replaces='img1',
147
mode='existing', target=quorum_repair_img,
148
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
149
self.assert_qmp(result, 'error/class', 'GenericError')
150
151
def test_device_not_found(self):
152
- if not iotests.supports_quorum():
153
- return
154
-
155
result = self.vm.qmp('drive-mirror', job_id='job0',
156
device='nonexistent', sync='full',
157
node_name='repair0',
158
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
159
self.assert_qmp(result, 'error/class', 'GenericError')
160
161
def test_wrong_sync_mode(self):
162
- if not iotests.supports_quorum():
163
- return
164
-
165
result = self.vm.qmp('drive-mirror', device='quorum0', job_id='job0',
166
node_name='repair0',
167
replaces='img1',
168
@@ -XXX,XX +XXX,XX @@ class TestRepairQuorum(iotests.QMPTestCase):
169
self.assert_qmp(result, 'error/class', 'GenericError')
170
171
def test_no_node_name(self):
172
- if not iotests.supports_quorum():
173
- return
174
-
175
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
176
sync='full', replaces='img1',
177
target=quorum_repair_img, format=iotests.imgfmt)
178
self.assert_qmp(result, 'error/class', 'GenericError')
179
180
def test_nonexistent_replaces(self):
181
- if not iotests.supports_quorum():
182
- return
183
-
184
result = self.vm.qmp('drive-mirror', job_id='job0', device='quorum0',
185
sync='full', node_name='repair0', replaces='img77',
186
target=quorum_repair_img, format=iotests.imgfmt)
187
self.assert_qmp(result, 'error/class', 'GenericError')
188
189
def test_after_a_quorum_snapshot(self):
190
- if not iotests.supports_quorum():
191
- return
192
-
193
result = self.vm.qmp('blockdev-snapshot-sync', node_name='img1',
194
snapshot_file=quorum_snapshot_file,
195
snapshot_node_name="snap1");
196
diff --git a/tests/qemu-iotests/245 b/tests/qemu-iotests/245
197
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
198
--- a/tests/qemu-iotests/245
34
--- a/tests/unit/test-bdrv-graph-mod.c
199
+++ b/tests/qemu-iotests/245
35
+++ b/tests/unit/test-bdrv-graph-mod.c
200
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
36
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
201
# This test verifies that we can't change the children of a block
37
bdrv_unref(top);
202
# device during a reopen operation in a way that would create
38
}
203
# cycles in the node graph
39
204
+ @iotests.skip_if_unsupported(['blkverify'])
40
-static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
205
def test_graph_cycles(self):
41
- BdrvChildRole role,
206
opts = []
42
- BlockReopenQueue *reopen_queue,
207
43
- uint64_t perm, uint64_t shared,
208
@@ -XXX,XX +XXX,XX @@ class TestBlockdevReopen(iotests.QMPTestCase):
44
- uint64_t *nperm, uint64_t *nshared)
209
self.assert_qmp(result, 'return', {})
45
+/*
210
46
+ * write-to-selected node may have several DATA children, one of them may be
211
# Misc reopen tests with different block drivers
47
+ * "selected". Exclusive write permission is taken on selected child.
212
+ @iotests.skip_if_unsupported(['quorum', 'throttle'])
48
+ *
213
def test_misc_drivers(self):
49
+ * We don't realize write handler itself, as we need only to test how permission
214
####################
50
+ * update works.
215
###### quorum ######
51
+ */
52
+typedef struct BDRVWriteToSelectedState {
53
+ BdrvChild *selected;
54
+} BDRVWriteToSelectedState;
55
+
56
+static void write_to_selected_perms(BlockDriverState *bs, BdrvChild *c,
57
+ BdrvChildRole role,
58
+ BlockReopenQueue *reopen_queue,
59
+ uint64_t perm, uint64_t shared,
60
+ uint64_t *nperm, uint64_t *nshared)
61
{
62
- if (bs->file && c == bs->file) {
63
+ BDRVWriteToSelectedState *s = bs->opaque;
64
+
65
+ if (s->selected && c == s->selected) {
66
*nperm = BLK_PERM_WRITE;
67
*nshared = BLK_PERM_ALL & ~BLK_PERM_WRITE;
68
} else {
69
@@ -XXX,XX +XXX,XX @@ static void write_to_file_perms(BlockDriverState *bs, BdrvChild *c,
70
}
71
}
72
73
-static BlockDriver bdrv_write_to_file = {
74
- .format_name = "tricky-perm",
75
- .bdrv_child_perm = write_to_file_perms,
76
+static BlockDriver bdrv_write_to_selected = {
77
+ .format_name = "write-to-selected",
78
+ .instance_size = sizeof(BDRVWriteToSelectedState),
79
+ .bdrv_child_perm = write_to_selected_perms,
80
};
81
82
83
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
84
* The following test shows that topological-sort order is required for
85
* permission update, simple DFS is not enough.
86
*
87
- * Consider the block driver which has two filter children: one active
88
- * with exclusive write access and one inactive with no specific
89
- * permissions.
90
+ * Consider the block driver (write-to-selected) which has two children: one is
91
+ * selected so we have exclusive write access to it and for the other one we
92
+ * don't need any specific permissions.
93
*
94
* And, these two children has a common base child, like this:
95
+ * (additional "top" on top is used in test just because the only public
96
+ * function to update permission should get a specific child to update.
97
+ * Making bdrv_refresh_perms() public just for this test isn't worth it)
98
*
99
- * ┌─────┐ ┌──────┐
100
- * │ fl2 │ ◀── │ top │
101
- * └─────┘ └──────┘
102
+ * ┌─────┐ ┌───────────────────┐ ┌─────┐
103
+ * │ fl2 │ ◀── │ write-to-selected │ ◀── │ top │
104
+ * └─────┘ └───────────────────┘ └─────┘
105
* │ │
106
* │ │ w
107
* │ ▼
108
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
109
*
110
* So, exclusive write is propagated.
111
*
112
- * Assume, we want to make fl2 active instead of fl1.
113
- * So, we set some option for top driver and do permission update.
114
+ * Assume, we want to select fl2 instead of fl1.
115
+ * So, we set some option for write-to-selected driver and do permission update.
116
*
117
* With simple DFS, if permission update goes first through
118
- * top->fl1->base branch it will succeed: it firstly drop exclusive write
119
- * permissions and than apply them for another BdrvChildren.
120
- * But if permission update goes first through top->fl2->base branch it
121
- * will fail, as when we try to update fl2->base child, old not yet
122
+ * write-to-selected -> fl1 -> base branch it will succeed: it firstly drop
123
+ * exclusive write permissions and than apply them for another BdrvChildren.
124
+ * But if permission update goes first through write-to-selected -> fl2 -> base
125
+ * branch it will fail, as when we try to update fl2->base child, old not yet
126
* updated fl1->base child will be in conflict.
127
*
128
* With topological-sort order we always update parents before children, so fl1
129
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_write_to_file = {
130
static void test_parallel_perm_update(void)
131
{
132
BlockDriverState *top = no_perm_node("top");
133
- BlockDriverState *tricky =
134
- bdrv_new_open_driver(&bdrv_write_to_file, "tricky", BDRV_O_RDWR,
135
+ BlockDriverState *ws =
136
+ bdrv_new_open_driver(&bdrv_write_to_selected, "ws", BDRV_O_RDWR,
137
&error_abort);
138
+ BDRVWriteToSelectedState *s = ws->opaque;
139
BlockDriverState *base = no_perm_node("base");
140
BlockDriverState *fl1 = pass_through_node("fl1");
141
BlockDriverState *fl2 = pass_through_node("fl2");
142
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
143
*/
144
bdrv_ref(base);
145
146
- bdrv_attach_child(top, tricky, "file", &child_of_bds, BDRV_CHILD_DATA,
147
+ bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA,
148
&error_abort);
149
- c_fl1 = bdrv_attach_child(tricky, fl1, "first", &child_of_bds,
150
- BDRV_CHILD_FILTERED, &error_abort);
151
- c_fl2 = bdrv_attach_child(tricky, fl2, "second", &child_of_bds,
152
- BDRV_CHILD_FILTERED, &error_abort);
153
+ c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds,
154
+ BDRV_CHILD_DATA, &error_abort);
155
+ c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
156
+ BDRV_CHILD_DATA, &error_abort);
157
bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
158
&error_abort);
159
bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
160
&error_abort);
161
162
/* Select fl1 as first child to be active */
163
- tricky->file = c_fl1;
164
+ s->selected = c_fl1;
165
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
166
167
assert(c_fl1->perm & BLK_PERM_WRITE);
168
assert(!(c_fl2->perm & BLK_PERM_WRITE));
169
170
/* Now, try to switch active child and update permissions */
171
- tricky->file = c_fl2;
172
+ s->selected = c_fl2;
173
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
174
175
assert(c_fl2->perm & BLK_PERM_WRITE);
176
assert(!(c_fl1->perm & BLK_PERM_WRITE));
177
178
/* Switch once more, to not care about real child order in the list */
179
- tricky->file = c_fl1;
180
+ s->selected = c_fl1;
181
bdrv_child_refresh_perms(top, top->children.lh_first, &error_abort);
182
183
assert(c_fl1->perm & BLK_PERM_WRITE);
216
--
184
--
217
2.20.1
185
2.37.3
218
186
219
187
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
We do add COW child to the node. In future we are going to forbid
4
adding COW child to the node that doesn't support backing. So, fix it
5
here now.
6
7
Don't worry about setting bs->backing itself: in further commit we'll
8
update the block-layer to automatically set/unset this field in generic
9
code.
10
11
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
12
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Message-Id: <20220726201134.924743-6-vsementsov@yandex-team.ru>
14
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
tests/unit/test-bdrv-drain.c | 1 +
18
1 file changed, 1 insertion(+)
19
20
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/unit/test-bdrv-drain.c
23
+++ b/tests/unit/test-bdrv-drain.c
24
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn bdrv_replace_test_co_drain_end(BlockDriverState *bs)
25
static BlockDriver bdrv_replace_test = {
26
.format_name = "replace_test",
27
.instance_size = sizeof(BDRVReplaceTestState),
28
+ .supports_backing = true,
29
30
.bdrv_close = bdrv_replace_test_close,
31
.bdrv_co_preadv = bdrv_replace_test_co_preadv,
32
--
33
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
bdrv_pass_through is used as filter, even all node variables has
4
corresponding names. We want to append it, so it should be
5
backing-child-based filter like mirror_top.
6
So, in test_update_perm_tree, first child should be DATA, as we don't
7
want filters with two filtered children.
8
9
bdrv_exclusive_writer is used as a filter once. So it should be filter
10
anyway. We want to append it, so it should be backing-child-based
11
fitler too.
12
13
Make all FILTERED children to be PRIMARY as well. We are going to force
14
this rule by assertion soon.
15
16
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
17
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
18
Message-Id: <20220726201134.924743-7-vsementsov@yandex-team.ru>
19
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
22
include/block/block_int-common.h | 5 +++--
23
tests/unit/test-bdrv-graph-mod.c | 24 +++++++++++++++++-------
24
2 files changed, 20 insertions(+), 9 deletions(-)
25
26
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
27
index XXXXXXX..XXXXXXX 100644
28
--- a/include/block/block_int-common.h
29
+++ b/include/block/block_int-common.h
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
31
/*
32
* Only make sense for filter drivers, for others must be false.
33
* If true, filtered child is bs->backing. Otherwise it's bs->file.
34
- * Only two internal filters use bs->backing as filtered child and has this
35
- * field set to true: mirror_top and commit_top.
36
+ * Two internal filters use bs->backing as filtered child and has this
37
+ * field set to true: mirror_top and commit_top. There also two such test
38
+ * filters in tests/unit/test-bdrv-graph-mod.c.
39
*
40
* Never create any more such filters!
41
*
42
diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/tests/unit/test-bdrv-graph-mod.c
45
+++ b/tests/unit/test-bdrv-graph-mod.c
46
@@ -XXX,XX +XXX,XX @@
47
48
static BlockDriver bdrv_pass_through = {
49
.format_name = "pass-through",
50
+ .is_filter = true,
51
+ .filtered_child_is_backing = true,
52
.bdrv_child_perm = bdrv_default_perms,
53
};
54
55
@@ -XXX,XX +XXX,XX @@ static void exclusive_write_perms(BlockDriverState *bs, BdrvChild *c,
56
57
static BlockDriver bdrv_exclusive_writer = {
58
.format_name = "exclusive-writer",
59
+ .is_filter = true,
60
+ .filtered_child_is_backing = true,
61
.bdrv_child_perm = exclusive_write_perms,
62
};
63
64
@@ -XXX,XX +XXX,XX @@ static void test_update_perm_tree(void)
65
blk_insert_bs(root, bs, &error_abort);
66
67
bdrv_attach_child(filter, bs, "child", &child_of_bds,
68
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, &error_abort);
69
+ BDRV_CHILD_DATA, &error_abort);
70
71
ret = bdrv_append(filter, bs, NULL);
72
g_assert_cmpint(ret, <, 0);
73
@@ -XXX,XX +XXX,XX @@ static void test_parallel_exclusive_write(void)
74
*/
75
bdrv_ref(base);
76
77
- bdrv_attach_child(top, fl1, "backing", &child_of_bds, BDRV_CHILD_DATA,
78
+ bdrv_attach_child(top, fl1, "backing", &child_of_bds,
79
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
80
&error_abort);
81
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
82
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
83
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
84
&error_abort);
85
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
86
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
87
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
88
&error_abort);
89
90
bdrv_replace_node(fl1, fl2, &error_abort);
91
@@ -XXX,XX +XXX,XX @@ static void test_parallel_perm_update(void)
92
BDRV_CHILD_DATA, &error_abort);
93
c_fl2 = bdrv_attach_child(ws, fl2, "second", &child_of_bds,
94
BDRV_CHILD_DATA, &error_abort);
95
- bdrv_attach_child(fl1, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
96
+ bdrv_attach_child(fl1, base, "backing", &child_of_bds,
97
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
98
&error_abort);
99
- bdrv_attach_child(fl2, base, "backing", &child_of_bds, BDRV_CHILD_FILTERED,
100
+ bdrv_attach_child(fl2, base, "backing", &child_of_bds,
101
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
102
&error_abort);
103
104
/* Select fl1 as first child to be active */
105
@@ -XXX,XX +XXX,XX @@ static void test_append_greedy_filter(void)
106
BlockDriverState *base = no_perm_node("base");
107
BlockDriverState *fl = exclusive_writer_node("fl1");
108
109
- bdrv_attach_child(top, base, "backing", &child_of_bds, BDRV_CHILD_COW,
110
+ bdrv_attach_child(top, base, "backing", &child_of_bds,
111
+ BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
112
&error_abort);
113
114
bdrv_append(fl, base, &error_abort);
115
--
116
2.37.3
diff view generated by jsdifflib
1
From: Max Reitz <mreitz@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
The "migration completed" event may be sent (on the source, to be
3
Make the informal rules formal. In further commit we'll add
4
specific) before the migration is actually completed, so the VM runstate
4
corresponding assertions.
5
will still be "finish-migrate" instead of "postmigrate". So ask the
6
users of VM.wait_migration() to specify the final runstate they desire
7
and then poll the VM until it has reached that state. (This should be
8
over very quickly, so busy polling is fine.)
9
5
10
Without this patch, I see intermittent failures in the new iotest 280
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
11
under high system load. I have not yet seen such failures with other
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
12
iotests that use VM.wait_migration() and query-status afterwards, but
8
Message-Id: <20220726201134.924743-8-vsementsov@yandex-team.ru>
13
maybe they just occur even more rarely, or it is because they also wait
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
on the destination VM to be running.
15
16
Signed-off-by: Max Reitz <mreitz@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
11
---
19
tests/qemu-iotests/iotests.py | 6 +++++-
12
include/block/block-common.h | 39 ++++++++++++++++++++++++++++++++++++
20
tests/qemu-iotests/234 | 8 ++++----
13
1 file changed, 39 insertions(+)
21
tests/qemu-iotests/262 | 4 ++--
22
tests/qemu-iotests/280 | 2 +-
23
4 files changed, 12 insertions(+), 8 deletions(-)
24
14
25
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
15
diff --git a/include/block/block-common.h b/include/block/block-common.h
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/tests/qemu-iotests/iotests.py
17
--- a/include/block/block-common.h
28
+++ b/tests/qemu-iotests/iotests.py
18
+++ b/include/block/block-common.h
29
@@ -XXX,XX +XXX,XX @@ class VM(qtest.QEMUQtestMachine):
19
@@ -XXX,XX +XXX,XX @@ enum {
30
}
20
*
31
]))
21
* At least one of DATA, METADATA, FILTERED, or COW must be set for
32
22
* every child.
33
- def wait_migration(self):
23
+ *
34
+ def wait_migration(self, expect_runstate):
24
+ *
35
while True:
25
+ * = Connection with bs->children, bs->file and bs->backing fields =
36
event = self.event_wait('MIGRATION')
26
+ *
37
log(event, filters=[filter_qmp_event])
27
+ * 1. Filters
38
if event['data']['status'] == 'completed':
28
+ *
39
break
29
+ * Filter drivers have drv->is_filter = true.
40
+ # The event may occur in finish-migrate, so wait for the expected
30
+ *
41
+ # post-migration runstate
31
+ * Filter node has exactly one FILTERED|PRIMARY child, and may have other
42
+ while self.qmp('query-status')['return']['status'] != expect_runstate:
32
+ * children which must not have these bits (one example is the
43
+ pass
33
+ * copy-before-write filter, which also has its target DATA child).
44
34
+ *
45
def node_info(self, node_name):
35
+ * Filter nodes never have COW children.
46
nodes = self.qmp('query-named-block-nodes')
36
+ *
47
diff --git a/tests/qemu-iotests/234 b/tests/qemu-iotests/234
37
+ * For most filters, the filtered child is linked in bs->file, bs->backing is
48
index XXXXXXX..XXXXXXX 100755
38
+ * NULL. For some filters (as an exception), it is the other way around; those
49
--- a/tests/qemu-iotests/234
39
+ * drivers will have drv->filtered_child_is_backing set to true (see that
50
+++ b/tests/qemu-iotests/234
40
+ * field’s documentation for what drivers this concerns)
51
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
41
+ *
52
iotests.log(vm_a.qmp('migrate', uri='exec:cat >%s' % (fifo_a)))
42
+ * 2. "raw" driver (block/raw-format.c)
53
with iotests.Timeout(3, 'Migration does not complete'):
43
+ *
54
# Wait for the source first (which includes setup=setup)
44
+ * Formally it's not a filter (drv->is_filter = false)
55
- vm_a.wait_migration()
45
+ *
56
+ vm_a.wait_migration('postmigrate')
46
+ * bs->backing is always NULL
57
# Wait for the destination second (which does not)
47
+ *
58
- vm_b.wait_migration()
48
+ * Only has one child, linked in bs->file. Its role is either FILTERED|PRIMARY
59
+ vm_b.wait_migration('running')
49
+ * (like filter) or DATA|PRIMARY depending on options.
60
50
+ *
61
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
51
+ * 3. Other drivers
62
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
52
+ *
63
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
53
+ * Don't have any FILTERED children.
64
iotests.log(vm_b.qmp('migrate', uri='exec:cat >%s' % (fifo_b)))
54
+ *
65
with iotests.Timeout(3, 'Migration does not complete'):
55
+ * May have at most one COW child. In this case it's linked in bs->backing.
66
# Wait for the source first (which includes setup=setup)
56
+ * Otherwise bs->backing is NULL. COW child is never PRIMARY.
67
- vm_b.wait_migration()
57
+ *
68
+ vm_b.wait_migration('postmigrate')
58
+ * May have at most one PRIMARY child. In this case it's linked in bs->file.
69
# Wait for the destination second (which does not)
59
+ * Otherwise bs->file is NULL.
70
- vm_a.wait_migration()
60
+ *
71
+ vm_a.wait_migration('running')
61
+ * May also have some other children that don't have the PRIMARY or COW bit set.
72
62
*/
73
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
63
enum BdrvChildRoleBits {
74
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
64
/*
75
diff --git a/tests/qemu-iotests/262 b/tests/qemu-iotests/262
76
index XXXXXXX..XXXXXXX 100755
77
--- a/tests/qemu-iotests/262
78
+++ b/tests/qemu-iotests/262
79
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('img') as img_path, \
80
iotests.log(vm_a.qmp('migrate', uri='exec:cat >%s' % (fifo)))
81
with iotests.Timeout(3, 'Migration does not complete'):
82
# Wait for the source first (which includes setup=setup)
83
- vm_a.wait_migration()
84
+ vm_a.wait_migration('postmigrate')
85
# Wait for the destination second (which does not)
86
- vm_b.wait_migration()
87
+ vm_b.wait_migration('running')
88
89
iotests.log(vm_a.qmp('query-migrate')['return']['status'])
90
iotests.log(vm_b.qmp('query-migrate')['return']['status'])
91
diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280
92
index XXXXXXX..XXXXXXX 100755
93
--- a/tests/qemu-iotests/280
94
+++ b/tests/qemu-iotests/280
95
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('base') as base_path , \
96
vm.qmp_log('migrate', uri='exec:cat > /dev/null')
97
98
with iotests.Timeout(3, 'Migration does not complete'):
99
- vm.wait_migration()
100
+ vm.wait_migration('postmigrate')
101
102
iotests.log('\nVM is now stopped:')
103
iotests.log(vm.qmp('query-migrate')['return']['status'])
104
--
65
--
105
2.20.1
66
2.37.3
106
67
107
68
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Actually what we chose is a primary child. Let's stress it in the code.
4
5
We are going to drop indirect pointer logic here in future. Actually
6
this commit simplifies the future work: we drop use of indirection in
7
the assertion now.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-9-vsementsov@yandex-team.ru>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
15
block/snapshot.c | 30 ++++++++++--------------------
16
1 file changed, 10 insertions(+), 20 deletions(-)
17
18
diff --git a/block/snapshot.c b/block/snapshot.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/snapshot.c
21
+++ b/block/snapshot.c
22
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
23
static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
24
{
25
BdrvChild **fallback;
26
- BdrvChild *child;
27
+ BdrvChild *child = bdrv_primary_child(bs);
28
29
- /*
30
- * The only BdrvChild pointers that are safe to modify (and which
31
- * we can thus return a reference to) are bs->file and
32
- * bs->backing.
33
- */
34
- fallback = &bs->file;
35
- if (!*fallback && bs->drv && bs->drv->is_filter) {
36
- fallback = &bs->backing;
37
- }
38
-
39
- if (!*fallback) {
40
+ /* We allow fallback only to primary child */
41
+ if (!child) {
42
return NULL;
43
}
44
+ fallback = (child == bs->file ? &bs->file : &bs->backing);
45
+ assert(*fallback == child);
46
47
/*
48
* Check that there are no other children that would need to be
49
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
50
}
51
52
/*
53
- * fallback_ptr is &bs->file or &bs->backing. *fallback_ptr
54
- * was closed above and set to NULL, but the .bdrv_open() call
55
- * has opened it again, because we set the respective option
56
- * (with the qdict_put_str() call above).
57
- * Assert that .bdrv_open() has attached some child on
58
- * *fallback_ptr, and that it has attached the one we wanted
59
- * it to (i.e., fallback_bs).
60
+ * fallback was a primary child. It was closed above and set to NULL,
61
+ * but the .bdrv_open() call has opened it again, because we set the
62
+ * respective option (with the qdict_put_str() call above).
63
+ * Assert that .bdrv_open() has attached the right BDS as primary child.
64
*/
65
- assert(*fallback_ptr && fallback_bs == (*fallback_ptr)->bs);
66
+ assert(bdrv_primary_bs(bs) == fallback_bs);
67
bdrv_unref(fallback_bs);
68
return ret;
69
}
70
--
71
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
3
We are going to reimplement this behavior (clear bs->file / bs->backing
4
pointers automatically when child->bs is cleared) in a nicer way, see
5
further commit
6
"block: Manipulate bs->file / bs->backing pointers in .attach/.detach".
7
8
With this revert we bring back a problem that was fixed by b0a9f6fed3d8.
9
Still the problem was mostly theoretical, we don't have concrete bugs
10
fixed by b0a9f6fed3d8, we don't have a specific test. Probably some
11
accidental failures of iotests are related.
12
13
Alternatively, we may merge this and following three reverts into final
14
"block: Manipulate ..." to avoid any kind of regression. But seems that
15
in this case having separate clear revert commits is better.
16
17
This reverts commit b0a9f6fed3d80de610dcd04a7e66f9f30a04174f.
18
19
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
20
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
Message-Id: <20220726201134.924743-10-vsementsov@yandex-team.ru>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
24
block.c | 102 +++++++++++++-------------------------------------------
25
1 file changed, 23 insertions(+), 79 deletions(-)
26
27
diff --git a/block.c b/block.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/block.c
30
+++ b/block.c
31
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
32
static bool bdrv_recurse_has_child(BlockDriverState *bs,
33
BlockDriverState *child);
34
35
-static void bdrv_child_free(BdrvChild *child);
36
static void bdrv_replace_child_noperm(BdrvChild **child,
37
- BlockDriverState *new_bs,
38
- bool free_empty_child);
39
+ BlockDriverState *new_bs);
40
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
41
BdrvChild *child,
42
Transaction *tran);
43
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvReplaceChildState {
44
BdrvChild *child;
45
BdrvChild **childp;
46
BlockDriverState *old_bs;
47
- bool free_empty_child;
48
} BdrvReplaceChildState;
49
50
static void bdrv_replace_child_commit(void *opaque)
51
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_commit(void *opaque)
52
BdrvReplaceChildState *s = opaque;
53
GLOBAL_STATE_CODE();
54
55
- if (s->free_empty_child && !s->child->bs) {
56
- bdrv_child_free(s->child);
57
- }
58
bdrv_unref(s->old_bs);
59
}
60
61
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
62
* modify the BdrvChild * pointer we indirectly pass to it, i.e. it
63
* will not modify s->child. From that perspective, it does not matter
64
* whether we pass s->childp or &s->child.
65
+ * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
66
+ * pointer anyway (though it will in the future), so at this point it
67
+ * absolutely does not matter whether we pass s->childp or &s->child.)
68
* (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
69
* it here.
70
* (3) If new_bs is NULL, *s->childp will have been NULLed by
71
* bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
72
* must not pass a NULL *s->childp here.
73
+ * (TODO: In its current state, bdrv_replace_child_noperm() will not
74
+ * have NULLed *s->childp, so this does not apply yet. It will in the
75
+ * future.)
76
*
77
* So whether new_bs was NULL or not, we cannot pass s->childp here; and in
78
* any case, there is no reason to pass it anyway.
79
*/
80
- bdrv_replace_child_noperm(&s->child, s->old_bs, true);
81
- /*
82
- * The child was pre-existing, so s->old_bs must be non-NULL, and
83
- * s->child thus must not have been freed
84
- */
85
- assert(s->child != NULL);
86
- if (!new_bs) {
87
- /* As described above, *s->childp was cleared, so restore it */
88
- assert(s->childp != NULL);
89
- *s->childp = s->child;
90
- }
91
+ bdrv_replace_child_noperm(&s->child, s->old_bs);
92
bdrv_unref(new_bs);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
96
*
97
* The function doesn't update permissions, caller is responsible for this.
98
*
99
- * (*childp)->bs must not be NULL.
100
- *
101
* Note that if new_bs == NULL, @childp is stored in a state object attached
102
* to @tran, so that the old child can be reinstated in the abort handler.
103
* Therefore, if @new_bs can be NULL, @childp must stay valid until the
104
* transaction is committed or aborted.
105
*
106
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
107
- * freed (on commit). @free_empty_child should only be false if the
108
- * caller will free the BDrvChild themselves (which may be important
109
- * if this is in turn called in another transactional context).
110
+ * (TODO: The reinstating does not happen yet, but it will once
111
+ * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
112
*/
113
static void bdrv_replace_child_tran(BdrvChild **childp,
114
BlockDriverState *new_bs,
115
- Transaction *tran,
116
- bool free_empty_child)
117
+ Transaction *tran)
118
{
119
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
120
*s = (BdrvReplaceChildState) {
121
.child = *childp,
122
.childp = new_bs == NULL ? childp : NULL,
123
.old_bs = (*childp)->bs,
124
- .free_empty_child = free_empty_child,
125
};
126
tran_add(tran, &bdrv_replace_child_drv, s);
127
128
- /* The abort handler relies on this */
129
- assert(s->old_bs != NULL);
130
-
131
if (new_bs) {
132
bdrv_ref(new_bs);
133
}
134
- /*
135
- * Pass free_empty_child=false, we will free the child (if
136
- * necessary) in bdrv_replace_child_commit() (if our
137
- * @free_empty_child parameter was true).
138
- */
139
- bdrv_replace_child_noperm(childp, new_bs, false);
140
+ bdrv_replace_child_noperm(childp, new_bs);
141
/* old_bs reference is transparently moved from *childp to @s */
142
}
143
144
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
145
return permissions[qapi_perm];
146
}
147
148
-/**
149
- * Replace (*childp)->bs by @new_bs.
150
- *
151
- * If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
152
- * generally cannot handle a BdrvChild with .bs == NULL, so clearing
153
- * BdrvChild.bs should generally immediately be followed by the
154
- * BdrvChild pointer being cleared as well.
155
- *
156
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
157
- * freed. @free_empty_child should only be false if the caller will
158
- * free the BdrvChild themselves (this may be important in a
159
- * transactional context, where it may only be freed on commit).
160
- */
161
static void bdrv_replace_child_noperm(BdrvChild **childp,
162
- BlockDriverState *new_bs,
163
- bool free_empty_child)
164
+ BlockDriverState *new_bs)
165
{
166
BdrvChild *child = *childp;
167
BlockDriverState *old_bs = child->bs;
168
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
169
}
170
171
child->bs = new_bs;
172
- if (!new_bs) {
173
- *childp = NULL;
174
- }
175
176
if (new_bs) {
177
assert_bdrv_graph_writable(new_bs);
178
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
179
bdrv_parent_drained_end_single(child);
180
drain_saldo++;
181
}
182
-
183
- if (free_empty_child && !child->bs) {
184
- bdrv_child_free(child);
185
- }
186
}
187
188
/**
189
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
190
BlockDriverState *bs = child->bs;
191
192
GLOBAL_STATE_CODE();
193
- /*
194
- * Pass free_empty_child=false, because we still need the child
195
- * for the AioContext operations on the parent below; those
196
- * BdrvChildClass methods all work on a BdrvChild object, so we
197
- * need to keep it as an empty shell (after this function, it will
198
- * not be attached to any parent, and it will not have a .bs).
199
- */
200
- bdrv_replace_child_noperm(s->child, NULL, false);
201
+ bdrv_replace_child_noperm(s->child, NULL);
202
203
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
204
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
205
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
206
207
bdrv_unref(bs);
208
bdrv_child_free(child);
209
+ *s->child = NULL;
210
}
211
212
static TransactionActionDrv bdrv_attach_child_common_drv = {
213
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
214
}
215
216
bdrv_ref(child_bs);
217
- bdrv_replace_child_noperm(&new_child, child_bs, true);
218
- /* child_bs was non-NULL, so new_child must not have been freed */
219
- assert(new_child != NULL);
220
+ bdrv_replace_child_noperm(&new_child, child_bs);
221
222
*child = new_child;
223
224
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild **childp)
225
BlockDriverState *old_bs = (*childp)->bs;
226
227
GLOBAL_STATE_CODE();
228
- bdrv_replace_child_noperm(childp, NULL, true);
229
+ bdrv_replace_child_noperm(childp, NULL);
230
+ bdrv_child_free(*childp);
231
232
if (old_bs) {
233
/*
234
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
235
}
236
237
if (child->bs) {
238
- /*
239
- * Pass free_empty_child=false, we will free the child in
240
- * bdrv_remove_filter_or_cow_child_commit()
241
- */
242
- bdrv_replace_child_tran(childp, NULL, tran, false);
243
+ bdrv_replace_child_tran(childp, NULL, tran);
244
}
245
246
s = g_new(BdrvRemoveFilterOrCowChild, 1);
247
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
248
.is_backing = (childp == &bs->backing),
249
};
250
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
251
+
252
+ *childp = NULL;
253
}
254
255
/*
256
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
257
* Passing a pointer to the local variable @c is fine here, because
258
* @to is not NULL, and so &c will not be attached to the transaction.
259
*/
260
- bdrv_replace_child_tran(&c, to, tran, true);
261
+ bdrv_replace_child_tran(&c, to, tran);
262
}
263
264
return 0;
265
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
266
bdrv_drained_begin(old_bs);
267
bdrv_drained_begin(new_bs);
268
269
- bdrv_replace_child_tran(&child, new_bs, tran, true);
270
- /* @new_bs must have been non-NULL, so @child must not have been freed */
271
- assert(child != NULL);
272
+ bdrv_replace_child_tran(&child, new_bs, tran);
273
274
found = g_hash_table_new(NULL, NULL);
275
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
276
--
277
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
3
That's a preparation to previously reverted
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
need it for a new approach.
6
7
This reverts commit 82b54cf51656bf3cd5ed1ac549e8a1085a0e3290.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-11-vsementsov@yandex-team.ru>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block.c | 81 +++++++--------------------------------------------------
15
1 file changed, 10 insertions(+), 71 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ static int bdrv_drv_set_perm(BlockDriverState *bs, uint64_t perm,
22
23
typedef struct BdrvReplaceChildState {
24
BdrvChild *child;
25
- BdrvChild **childp;
26
BlockDriverState *old_bs;
27
} BdrvReplaceChildState;
28
29
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
30
BlockDriverState *new_bs = s->child->bs;
31
32
GLOBAL_STATE_CODE();
33
- /*
34
- * old_bs reference is transparently moved from @s to s->child.
35
- *
36
- * Pass &s->child here instead of s->childp, because:
37
- * (1) s->old_bs must be non-NULL, so bdrv_replace_child_noperm() will not
38
- * modify the BdrvChild * pointer we indirectly pass to it, i.e. it
39
- * will not modify s->child. From that perspective, it does not matter
40
- * whether we pass s->childp or &s->child.
41
- * (TODO: Right now, bdrv_replace_child_noperm() never modifies that
42
- * pointer anyway (though it will in the future), so at this point it
43
- * absolutely does not matter whether we pass s->childp or &s->child.)
44
- * (2) If new_bs is not NULL, s->childp will be NULL. We then cannot use
45
- * it here.
46
- * (3) If new_bs is NULL, *s->childp will have been NULLed by
47
- * bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
48
- * must not pass a NULL *s->childp here.
49
- * (TODO: In its current state, bdrv_replace_child_noperm() will not
50
- * have NULLed *s->childp, so this does not apply yet. It will in the
51
- * future.)
52
- *
53
- * So whether new_bs was NULL or not, we cannot pass s->childp here; and in
54
- * any case, there is no reason to pass it anyway.
55
- */
56
+ /* old_bs reference is transparently moved from @s to @s->child */
57
bdrv_replace_child_noperm(&s->child, s->old_bs);
58
bdrv_unref(new_bs);
59
}
60
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_replace_child_drv = {
61
* Note: real unref of old_bs is done only on commit.
62
*
63
* The function doesn't update permissions, caller is responsible for this.
64
- *
65
- * Note that if new_bs == NULL, @childp is stored in a state object attached
66
- * to @tran, so that the old child can be reinstated in the abort handler.
67
- * Therefore, if @new_bs can be NULL, @childp must stay valid until the
68
- * transaction is committed or aborted.
69
- *
70
- * (TODO: The reinstating does not happen yet, but it will once
71
- * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
72
*/
73
-static void bdrv_replace_child_tran(BdrvChild **childp,
74
- BlockDriverState *new_bs,
75
+static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
76
Transaction *tran)
77
{
78
BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
79
*s = (BdrvReplaceChildState) {
80
- .child = *childp,
81
- .childp = new_bs == NULL ? childp : NULL,
82
- .old_bs = (*childp)->bs,
83
+ .child = child,
84
+ .old_bs = child->bs,
85
};
86
tran_add(tran, &bdrv_replace_child_drv, s);
87
88
if (new_bs) {
89
bdrv_ref(new_bs);
90
}
91
- bdrv_replace_child_noperm(childp, new_bs);
92
- /* old_bs reference is transparently moved from *childp to @s */
93
+ bdrv_replace_child_noperm(&child, new_bs);
94
+ /* old_bs reference is transparently moved from @child to @s */
95
}
96
97
/*
98
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
99
100
typedef struct BdrvRemoveFilterOrCowChild {
101
BdrvChild *child;
102
- BlockDriverState *bs;
103
bool is_backing;
104
} BdrvRemoveFilterOrCowChild;
105
106
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
107
bdrv_child_free(s->child);
108
}
109
110
-static void bdrv_remove_filter_or_cow_child_clean(void *opaque)
111
-{
112
- BdrvRemoveFilterOrCowChild *s = opaque;
113
-
114
- /* Drop the bs reference after the transaction is done */
115
- bdrv_unref(s->bs);
116
- g_free(s);
117
-}
118
-
119
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
120
.abort = bdrv_remove_filter_or_cow_child_abort,
121
.commit = bdrv_remove_filter_or_cow_child_commit,
122
- .clean = bdrv_remove_filter_or_cow_child_clean,
123
+ .clean = g_free,
124
};
125
126
/*
127
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
128
return;
129
}
130
131
- /*
132
- * Keep a reference to @bs so @childp will stay valid throughout the
133
- * transaction (required by bdrv_replace_child_tran())
134
- */
135
- bdrv_ref(bs);
136
if (child == bs->backing) {
137
childp = &bs->backing;
138
} else if (child == bs->file) {
139
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
140
}
141
142
if (child->bs) {
143
- bdrv_replace_child_tran(childp, NULL, tran);
144
+ bdrv_replace_child_tran(*childp, NULL, tran);
145
}
146
147
s = g_new(BdrvRemoveFilterOrCowChild, 1);
148
*s = (BdrvRemoveFilterOrCowChild) {
149
.child = child,
150
- .bs = bs,
151
.is_backing = (childp == &bs->backing),
152
};
153
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
154
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
155
{
156
BdrvChild *c, *next;
157
158
- assert(to != NULL);
159
GLOBAL_STATE_CODE();
160
161
QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) {
162
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
163
c->name, from->node_name);
164
return -EPERM;
165
}
166
-
167
- /*
168
- * Passing a pointer to the local variable @c is fine here, because
169
- * @to is not NULL, and so &c will not be attached to the transaction.
170
- */
171
- bdrv_replace_child_tran(&c, to, tran);
172
+ bdrv_replace_child_tran(c, to, tran);
173
}
174
175
return 0;
176
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
177
*
178
* With @detach_subchain=true @to must be in a backing chain of @from. In this
179
* case backing link of the cow-parent of @to is removed.
180
- *
181
- * @to must not be NULL.
182
*/
183
static int bdrv_replace_node_common(BlockDriverState *from,
184
BlockDriverState *to,
185
@@ -XXX,XX +XXX,XX @@ static int bdrv_replace_node_common(BlockDriverState *from,
186
int ret;
187
188
GLOBAL_STATE_CODE();
189
- assert(to != NULL);
190
191
if (detach_subchain) {
192
assert(bdrv_chain_contains(from, to));
193
@@ -XXX,XX +XXX,XX @@ out:
194
return ret;
195
}
196
197
-/**
198
- * Replace node @from by @to (where neither may be NULL).
199
- */
200
int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to,
201
Error **errp)
202
{
203
@@ -XXX,XX +XXX,XX @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
204
bdrv_drained_begin(old_bs);
205
bdrv_drained_begin(new_bs);
206
207
- bdrv_replace_child_tran(&child, new_bs, tran);
208
+ bdrv_replace_child_tran(child, new_bs, tran);
209
210
found = g_hash_table_new(NULL, NULL);
211
refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
212
--
213
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
Issuing a drive-backup from qmp_drive_backup takes a slightly
3
That's a preparation to previously reverted
4
different path than when it's issued from a transaction. In the code,
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
this is manifested as some redundancy between do_drive_backup() and
5
need it for a new approach.
6
drive_backup_prepare().
7
6
8
This change unifies both paths, merging do_drive_backup() and
7
This reverts commit 562bda8bb41879eeda0bd484dd3d55134579b28e.
9
drive_backup_prepare(), and changing qmp_drive_backup() to create a
10
transaction instead of calling do_backup_common() direcly.
11
8
12
As a side-effect, now qmp_drive_backup() is executed inside a drained
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
section, as it happens when creating a drive-backup transaction. This
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
change is visible from the user's perspective, as the job gets paused
11
Message-Id: <20220726201134.924743-12-vsementsov@yandex-team.ru>
15
and immediately resumed before starting the actual work.
16
17
Also fix tests 141, 185 and 219 to cope with the extra
18
JOB_STATUS_CHANGE lines.
19
20
Signed-off-by: Sergio Lopez <slp@redhat.com>
21
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
---
13
---
24
blockdev.c | 224 +++++++++++++++++--------------------
14
block.c | 21 +++++++++------------
25
tests/qemu-iotests/141.out | 2 +
15
1 file changed, 9 insertions(+), 12 deletions(-)
26
tests/qemu-iotests/185.out | 2 +
27
tests/qemu-iotests/219 | 7 +-
28
tests/qemu-iotests/219.out | 8 ++
29
5 files changed, 117 insertions(+), 126 deletions(-)
30
16
31
diff --git a/blockdev.c b/blockdev.c
17
diff --git a/block.c b/block.c
32
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
33
--- a/blockdev.c
19
--- a/block.c
34
+++ b/blockdev.c
20
+++ b/block.c
35
@@ -XXX,XX +XXX,XX @@ typedef struct DriveBackupState {
21
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
36
BlockJob *job;
22
BdrvChild *child,
37
} DriveBackupState;
23
Transaction *tran)
38
39
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
40
- Error **errp);
41
+static BlockJob *do_backup_common(BackupCommon *backup,
42
+ BlockDriverState *bs,
43
+ BlockDriverState *target_bs,
44
+ AioContext *aio_context,
45
+ JobTxn *txn, Error **errp);
46
47
static void drive_backup_prepare(BlkActionState *common, Error **errp)
48
{
24
{
49
DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common);
25
- BdrvChild **childp;
50
- BlockDriverState *bs;
26
BdrvRemoveFilterOrCowChild *s;
51
DriveBackup *backup;
27
52
+ BlockDriverState *bs;
28
+ assert(child == bs->backing || child == bs->file);
53
+ BlockDriverState *target_bs;
54
+ BlockDriverState *source = NULL;
55
AioContext *aio_context;
56
+ QDict *options;
57
Error *local_err = NULL;
58
+ int flags;
59
+ int64_t size;
60
+ bool set_backing_hd = false;
61
62
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
63
backup = common->action->u.drive_backup.data;
64
65
+ if (!backup->has_mode) {
66
+ backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
67
+ }
68
+
29
+
69
bs = bdrv_lookup_bs(backup->device, backup->device, errp);
30
if (!child) {
70
if (!bs) {
71
return;
31
return;
72
}
32
}
73
33
74
+ if (!bs->drv) {
34
- if (child == bs->backing) {
75
+ error_setg(errp, "Device has no medium");
35
- childp = &bs->backing;
76
+ return;
36
- } else if (child == bs->file) {
77
+ }
37
- childp = &bs->file;
78
+
38
- } else {
79
aio_context = bdrv_get_aio_context(bs);
39
- g_assert_not_reached();
80
aio_context_acquire(aio_context);
81
82
/* Paired with .clean() */
83
bdrv_drained_begin(bs);
84
85
- state->bs = bs;
86
+ if (!backup->has_format) {
87
+ backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
88
+ NULL : (char *) bs->drv->format_name;
89
+ }
90
+
91
+ /* Early check to avoid creating target */
92
+ if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
93
+ goto out;
94
+ }
95
+
96
+ flags = bs->open_flags | BDRV_O_RDWR;
97
+
98
+ /*
99
+ * See if we have a backing HD we can use to create our new image
100
+ * on top of.
101
+ */
102
+ if (backup->sync == MIRROR_SYNC_MODE_TOP) {
103
+ source = backing_bs(bs);
104
+ if (!source) {
105
+ backup->sync = MIRROR_SYNC_MODE_FULL;
106
+ }
107
+ }
108
+ if (backup->sync == MIRROR_SYNC_MODE_NONE) {
109
+ source = bs;
110
+ flags |= BDRV_O_NO_BACKING;
111
+ set_backing_hd = true;
112
+ }
113
+
114
+ size = bdrv_getlength(bs);
115
+ if (size < 0) {
116
+ error_setg_errno(errp, -size, "bdrv_getlength failed");
117
+ goto out;
118
+ }
119
+
120
+ if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
121
+ assert(backup->format);
122
+ if (source) {
123
+ bdrv_refresh_filename(source);
124
+ bdrv_img_create(backup->target, backup->format, source->filename,
125
+ source->drv->format_name, NULL,
126
+ size, flags, false, &local_err);
127
+ } else {
128
+ bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
129
+ size, flags, false, &local_err);
130
+ }
131
+ }
132
133
- state->job = do_drive_backup(backup, common->block_job_txn, &local_err);
134
if (local_err) {
135
error_propagate(errp, local_err);
136
goto out;
137
}
138
139
+ options = qdict_new();
140
+ qdict_put_str(options, "discard", "unmap");
141
+ qdict_put_str(options, "detect-zeroes", "unmap");
142
+ if (backup->format) {
143
+ qdict_put_str(options, "driver", backup->format);
144
+ }
145
+
146
+ target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
147
+ if (!target_bs) {
148
+ goto out;
149
+ }
150
+
151
+ if (set_backing_hd) {
152
+ bdrv_set_backing_hd(target_bs, source, &local_err);
153
+ if (local_err) {
154
+ goto unref;
155
+ }
156
+ }
157
+
158
+ state->bs = bs;
159
+
160
+ state->job = do_backup_common(qapi_DriveBackup_base(backup),
161
+ bs, target_bs, aio_context,
162
+ common->block_job_txn, errp);
163
+
164
+unref:
165
+ bdrv_unref(target_bs);
166
out:
167
aio_context_release(aio_context);
168
}
169
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
170
return job;
171
}
172
173
-static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
174
- Error **errp)
175
-{
176
- BlockDriverState *bs;
177
- BlockDriverState *target_bs;
178
- BlockDriverState *source = NULL;
179
- BlockJob *job = NULL;
180
- AioContext *aio_context;
181
- QDict *options;
182
- Error *local_err = NULL;
183
- int flags;
184
- int64_t size;
185
- bool set_backing_hd = false;
186
-
187
- if (!backup->has_mode) {
188
- backup->mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS;
189
- }
40
- }
190
-
41
-
191
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
42
if (child->bs) {
192
- if (!bs) {
43
- bdrv_replace_child_tran(*childp, NULL, tran);
193
- return NULL;
44
+ bdrv_replace_child_tran(child, NULL, tran);
194
- }
45
}
195
-
46
196
- if (!bs->drv) {
47
s = g_new(BdrvRemoveFilterOrCowChild, 1);
197
- error_setg(errp, "Device has no medium");
48
*s = (BdrvRemoveFilterOrCowChild) {
198
- return NULL;
49
.child = child,
199
- }
50
- .is_backing = (childp == &bs->backing),
200
-
51
+ .is_backing = (child == bs->backing),
201
- aio_context = bdrv_get_aio_context(bs);
52
};
202
- aio_context_acquire(aio_context);
53
tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
203
-
54
204
- if (!backup->has_format) {
55
- *childp = NULL;
205
- backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
56
+ if (s->is_backing) {
206
- NULL : (char *) bs->drv->format_name;
57
+ bs->backing = NULL;
207
- }
58
+ } else {
208
-
59
+ bs->file = NULL;
209
- /* Early check to avoid creating target */
60
+ }
210
- if (bdrv_op_is_blocked(bs, BLOCK_OP_TYPE_BACKUP_SOURCE, errp)) {
211
- goto out;
212
- }
213
-
214
- flags = bs->open_flags | BDRV_O_RDWR;
215
-
216
- /*
217
- * See if we have a backing HD we can use to create our new image
218
- * on top of.
219
- */
220
- if (backup->sync == MIRROR_SYNC_MODE_TOP) {
221
- source = backing_bs(bs);
222
- if (!source) {
223
- backup->sync = MIRROR_SYNC_MODE_FULL;
224
- }
225
- }
226
- if (backup->sync == MIRROR_SYNC_MODE_NONE) {
227
- source = bs;
228
- flags |= BDRV_O_NO_BACKING;
229
- set_backing_hd = true;
230
- }
231
-
232
- size = bdrv_getlength(bs);
233
- if (size < 0) {
234
- error_setg_errno(errp, -size, "bdrv_getlength failed");
235
- goto out;
236
- }
237
-
238
- if (backup->mode != NEW_IMAGE_MODE_EXISTING) {
239
- assert(backup->format);
240
- if (source) {
241
- bdrv_refresh_filename(source);
242
- bdrv_img_create(backup->target, backup->format, source->filename,
243
- source->drv->format_name, NULL,
244
- size, flags, false, &local_err);
245
- } else {
246
- bdrv_img_create(backup->target, backup->format, NULL, NULL, NULL,
247
- size, flags, false, &local_err);
248
- }
249
- }
250
-
251
- if (local_err) {
252
- error_propagate(errp, local_err);
253
- goto out;
254
- }
255
-
256
- options = qdict_new();
257
- qdict_put_str(options, "discard", "unmap");
258
- qdict_put_str(options, "detect-zeroes", "unmap");
259
- if (backup->format) {
260
- qdict_put_str(options, "driver", backup->format);
261
- }
262
-
263
- target_bs = bdrv_open(backup->target, NULL, options, flags, errp);
264
- if (!target_bs) {
265
- goto out;
266
- }
267
-
268
- if (set_backing_hd) {
269
- bdrv_set_backing_hd(target_bs, source, &local_err);
270
- if (local_err) {
271
- goto unref;
272
- }
273
- }
274
-
275
- job = do_backup_common(qapi_DriveBackup_base(backup),
276
- bs, target_bs, aio_context, txn, errp);
277
-
278
-unref:
279
- bdrv_unref(target_bs);
280
-out:
281
- aio_context_release(aio_context);
282
- return job;
283
-}
284
-
285
-void qmp_drive_backup(DriveBackup *arg, Error **errp)
286
+void qmp_drive_backup(DriveBackup *backup, Error **errp)
287
{
288
-
289
- BlockJob *job;
290
- job = do_drive_backup(arg, NULL, errp);
291
- if (job) {
292
- job_start(&job->job);
293
- }
294
+ TransactionAction action = {
295
+ .type = TRANSACTION_ACTION_KIND_DRIVE_BACKUP,
296
+ .u.drive_backup.data = backup,
297
+ };
298
+ blockdev_do_action(&action, errp);
299
}
61
}
300
62
301
BlockDeviceInfoList *qmp_query_named_block_nodes(Error **errp)
63
/*
302
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
303
index XXXXXXX..XXXXXXX 100644
304
--- a/tests/qemu-iotests/141.out
305
+++ b/tests/qemu-iotests/141.out
306
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.
307
Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
308
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
309
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
310
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
311
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
312
{'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}}
313
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
314
{'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}}
315
diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out
316
index XXXXXXX..XXXXXXX 100644
317
--- a/tests/qemu-iotests/185.out
318
+++ b/tests/qemu-iotests/185.out
319
@@ -XXX,XX +XXX,XX @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l
320
Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
321
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}}
322
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
323
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "disk"}}
324
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}}
325
{"return": {}}
326
{ 'execute': 'quit' }
327
{"return": {}}
328
diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219
329
index XXXXXXX..XXXXXXX 100755
330
--- a/tests/qemu-iotests/219
331
+++ b/tests/qemu-iotests/219
332
@@ -XXX,XX +XXX,XX @@ def test_pause_resume(vm):
333
# logged immediately
334
iotests.log(vm.qmp('query-jobs'))
335
336
-def test_job_lifecycle(vm, job, job_args, has_ready=False):
337
+def test_job_lifecycle(vm, job, job_args, has_ready=False, is_mirror=False):
338
global img_size
339
340
iotests.log('')
341
@@ -XXX,XX +XXX,XX @@ def test_job_lifecycle(vm, job, job_args, has_ready=False):
342
iotests.log('Waiting for PENDING state...')
343
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
344
iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
345
+ if is_mirror:
346
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
347
+ iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE')))
348
349
if not job_args.get('auto-finalize', True):
350
# PENDING state:
351
@@ -XXX,XX +XXX,XX @@ with iotests.FilePath('disk.img') as disk_path, \
352
353
for auto_finalize in [True, False]:
354
for auto_dismiss in [True, False]:
355
- test_job_lifecycle(vm, 'drive-backup', job_args={
356
+ test_job_lifecycle(vm, 'drive-backup', is_mirror=True, job_args={
357
'device': 'drive0-node',
358
'target': copy_path,
359
'sync': 'full',
360
diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out
361
index XXXXXXX..XXXXXXX 100644
362
--- a/tests/qemu-iotests/219.out
363
+++ b/tests/qemu-iotests/219.out
364
@@ -XXX,XX +XXX,XX @@ Pause/resume in RUNNING
365
{"return": {}}
366
367
Waiting for PENDING state...
368
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
369
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
370
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
371
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
372
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
373
@@ -XXX,XX +XXX,XX @@ Pause/resume in RUNNING
374
{"return": {}}
375
376
Waiting for PENDING state...
377
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
378
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
379
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
380
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
381
{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
382
@@ -XXX,XX +XXX,XX @@ Pause/resume in RUNNING
383
{"return": {}}
384
385
Waiting for PENDING state...
386
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
387
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
388
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
389
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
390
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
391
@@ -XXX,XX +XXX,XX @@ Pause/resume in RUNNING
392
{"return": {}}
393
394
Waiting for PENDING state...
395
+{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
396
+{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
397
{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
398
{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
399
{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]}
400
--
64
--
401
2.20.1
65
2.37.3
402
403
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
That's a preparation to previously reverted
4
"block: Let replace_child_noperm free children". Drop it too, we don't
5
need it for a new approach.
6
7
This reverts commit be64bbb0149748f3999c49b13976aafb8330ea86.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-Id: <20220726201134.924743-13-vsementsov@yandex-team.ru>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block.c | 23 +++++++++++------------
15
1 file changed, 11 insertions(+), 12 deletions(-)
16
17
diff --git a/block.c b/block.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block.c
20
+++ b/block.c
21
@@ -XXX,XX +XXX,XX @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
22
static bool bdrv_recurse_has_child(BlockDriverState *bs,
23
BlockDriverState *child);
24
25
-static void bdrv_replace_child_noperm(BdrvChild **child,
26
+static void bdrv_replace_child_noperm(BdrvChild *child,
27
BlockDriverState *new_bs);
28
static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
29
BdrvChild *child,
30
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_abort(void *opaque)
31
32
GLOBAL_STATE_CODE();
33
/* old_bs reference is transparently moved from @s to @s->child */
34
- bdrv_replace_child_noperm(&s->child, s->old_bs);
35
+ bdrv_replace_child_noperm(s->child, s->old_bs);
36
bdrv_unref(new_bs);
37
}
38
39
@@ -XXX,XX +XXX,XX @@ static void bdrv_replace_child_tran(BdrvChild *child, BlockDriverState *new_bs,
40
if (new_bs) {
41
bdrv_ref(new_bs);
42
}
43
- bdrv_replace_child_noperm(&child, new_bs);
44
+ bdrv_replace_child_noperm(child, new_bs);
45
/* old_bs reference is transparently moved from @child to @s */
46
}
47
48
@@ -XXX,XX +XXX,XX @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
49
return permissions[qapi_perm];
50
}
51
52
-static void bdrv_replace_child_noperm(BdrvChild **childp,
53
+static void bdrv_replace_child_noperm(BdrvChild *child,
54
BlockDriverState *new_bs)
55
{
56
- BdrvChild *child = *childp;
57
BlockDriverState *old_bs = child->bs;
58
int new_bs_quiesce_counter;
59
int drain_saldo;
60
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
61
BlockDriverState *bs = child->bs;
62
63
GLOBAL_STATE_CODE();
64
- bdrv_replace_child_noperm(s->child, NULL);
65
+ bdrv_replace_child_noperm(child, NULL);
66
67
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
68
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
69
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
70
}
71
72
bdrv_ref(child_bs);
73
- bdrv_replace_child_noperm(&new_child, child_bs);
74
+ bdrv_replace_child_noperm(new_child, child_bs);
75
76
*child = new_child;
77
78
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
79
return 0;
80
}
81
82
-static void bdrv_detach_child(BdrvChild **childp)
83
+static void bdrv_detach_child(BdrvChild *child)
84
{
85
- BlockDriverState *old_bs = (*childp)->bs;
86
+ BlockDriverState *old_bs = child->bs;
87
88
GLOBAL_STATE_CODE();
89
- bdrv_replace_child_noperm(childp, NULL);
90
- bdrv_child_free(*childp);
91
+ bdrv_replace_child_noperm(child, NULL);
92
+ bdrv_child_free(child);
93
94
if (old_bs) {
95
/*
96
@@ -XXX,XX +XXX,XX @@ void bdrv_root_unref_child(BdrvChild *child)
97
GLOBAL_STATE_CODE();
98
99
child_bs = child->bs;
100
- bdrv_detach_child(&child);
101
+ bdrv_detach_child(child);
102
bdrv_unref(child_bs);
103
}
104
105
--
106
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
3
bs->file and bs->backing are a kind of duplication of part of
4
bs->children. But very useful diplication, so let's not drop them at
5
all:)
6
7
We should manage bs->file and bs->backing in same place, where we
8
manage bs->children, to keep them in sync.
9
10
Moreover, generic io paths are unprepared to BdrvChild without a bs, so
11
it's double good to clear bs->file / bs->backing when we detach the
12
child.
13
14
Detach is simple: if we detach bs->file or bs->backing child, just
15
set corresponding field to NULL.
16
17
Attach is a bit more complicated. But we still can precisely detect
18
should we set one of bs->file / bs->backing or not:
19
20
- if role is BDRV_CHILD_COW, we definitely deal with bs->backing
21
- else, if role is BDRV_CHILD_FILTERED (it must be also
22
BDRV_CHILD_PRIMARY), it's a filtered child. Use
23
bs->drv->filtered_child_is_backing to chose the pointer field to
24
modify.
25
- else, if role is BDRV_CHILD_PRIMARY, we deal with bs->file
26
- in all other cases, it's neither bs->backing nor bs->file. It's some
27
other child and we shouldn't care
28
29
OK. This change brings one more good thing: we can (and should) get rid
30
of all indirect pointers in the block-graph-change transactions:
31
32
bdrv_attach_child_common() stores BdrvChild** into transaction to clear
33
it on abort.
34
35
bdrv_attach_child_common() has two callers: bdrv_attach_child_noperm()
36
just pass-through this feature, bdrv_root_attach_child() doesn't need
37
the feature.
38
39
Look at bdrv_attach_child_noperm() callers:
40
- bdrv_attach_child() doesn't need the feature
41
- bdrv_set_file_or_backing_noperm() uses the feature to manage
42
bs->file and bs->backing, we don't want it anymore
43
- bdrv_append() uses the feature to manage bs->backing, again we
44
don't want it anymore
45
46
So, we should drop this stuff! Great!
47
48
We could probably keep BdrvChild** argument to keep the int return
49
value, but it seems not worth the complexity.
50
51
Finally, we now set .file / .backing automatically in generic code and
52
want to restring setting them by hand outside of .attach/.detach.
53
So, this patch cleanups all remaining places where they were set.
54
To find such places I use:
55
56
git grep '\->file ='
57
git grep '\->backing ='
58
git grep '&.*\<backing\>'
59
git grep '&.*\<file\>'
60
61
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
62
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
63
Message-Id: <20220726201134.924743-14-vsementsov@yandex-team.ru>
64
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
65
---
66
include/block/block_int-common.h | 15 +-
67
block.c | 234 ++++++++++++++-----------------
68
block/raw-format.c | 4 +-
69
block/snapshot-access.c | 6 +-
70
block/snapshot.c | 1 -
71
tests/unit/test-bdrv-drain.c | 10 +-
72
6 files changed, 126 insertions(+), 144 deletions(-)
73
74
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/block/block_int-common.h
77
+++ b/include/block/block_int-common.h
78
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
79
QDict *full_open_options;
80
char exact_filename[PATH_MAX];
81
82
- BdrvChild *backing;
83
- BdrvChild *file;
84
-
85
/* I/O Limits */
86
BlockLimits bl;
87
88
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
89
* parent node of this node.
90
*/
91
BlockDriverState *inherits_from;
92
+
93
+ /*
94
+ * @backing and @file are some of @children or NULL. All these three fields
95
+ * (@file, @backing and @children) are modified only in
96
+ * bdrv_child_cb_attach() and bdrv_child_cb_detach().
97
+ *
98
+ * See also comment in include/block/block.h, to learn how backing and file
99
+ * are connected with BdrvChildRole.
100
+ */
101
QLIST_HEAD(, BdrvChild) children;
102
+ BdrvChild *backing;
103
+ BdrvChild *file;
104
+
105
QLIST_HEAD(, BdrvChild) parents;
106
107
QDict *options;
108
diff --git a/block.c b/block.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/block.c
111
+++ b/block.c
112
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_attach(BdrvChild *child)
113
114
assert_bdrv_graph_writable(bs);
115
QLIST_INSERT_HEAD(&bs->children, child, next);
116
-
117
- if (child->role & BDRV_CHILD_COW) {
118
+ if (bs->drv->is_filter || (child->role & BDRV_CHILD_FILTERED)) {
119
+ /*
120
+ * Here we handle filters and block/raw-format.c when it behave like
121
+ * filter. They generally have a single PRIMARY child, which is also the
122
+ * FILTERED child, and that they may have multiple more children, which
123
+ * are neither PRIMARY nor FILTERED. And never we have a COW child here.
124
+ * So bs->file will be the PRIMARY child, unless the PRIMARY child goes
125
+ * into bs->backing on exceptional cases; and bs->backing will be
126
+ * nothing else.
127
+ */
128
+ assert(!(child->role & BDRV_CHILD_COW));
129
+ if (child->role & BDRV_CHILD_PRIMARY) {
130
+ assert(child->role & BDRV_CHILD_FILTERED);
131
+ assert(!bs->backing);
132
+ assert(!bs->file);
133
+
134
+ if (bs->drv->filtered_child_is_backing) {
135
+ bs->backing = child;
136
+ } else {
137
+ bs->file = child;
138
+ }
139
+ } else {
140
+ assert(!(child->role & BDRV_CHILD_FILTERED));
141
+ }
142
+ } else if (child->role & BDRV_CHILD_COW) {
143
+ assert(bs->drv->supports_backing);
144
+ assert(!(child->role & BDRV_CHILD_PRIMARY));
145
+ assert(!bs->backing);
146
+ bs->backing = child;
147
bdrv_backing_attach(child);
148
+ } else if (child->role & BDRV_CHILD_PRIMARY) {
149
+ assert(!bs->file);
150
+ bs->file = child;
151
}
152
153
bdrv_apply_subtree_drain(child, bs);
154
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_cb_detach(BdrvChild *child)
155
156
assert_bdrv_graph_writable(bs);
157
QLIST_REMOVE(child, next);
158
+ if (child == bs->backing) {
159
+ assert(child != bs->file);
160
+ bs->backing = NULL;
161
+ } else if (child == bs->file) {
162
+ bs->file = NULL;
163
+ }
164
}
165
166
static int bdrv_child_cb_update_filename(BdrvChild *c, BlockDriverState *base,
167
@@ -XXX,XX +XXX,XX @@ open_failed:
168
bs->drv = NULL;
169
if (bs->file != NULL) {
170
bdrv_unref_child(bs, bs->file);
171
- bs->file = NULL;
172
+ assert(!bs->file);
173
}
174
g_free(bs->opaque);
175
bs->opaque = NULL;
176
@@ -XXX,XX +XXX,XX @@ static void bdrv_child_free(BdrvChild *child)
177
}
178
179
typedef struct BdrvAttachChildCommonState {
180
- BdrvChild **child;
181
+ BdrvChild *child;
182
AioContext *old_parent_ctx;
183
AioContext *old_child_ctx;
184
} BdrvAttachChildCommonState;
185
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvAttachChildCommonState {
186
static void bdrv_attach_child_common_abort(void *opaque)
187
{
188
BdrvAttachChildCommonState *s = opaque;
189
- BdrvChild *child = *s->child;
190
- BlockDriverState *bs = child->bs;
191
+ BlockDriverState *bs = s->child->bs;
192
193
GLOBAL_STATE_CODE();
194
- bdrv_replace_child_noperm(child, NULL);
195
+ bdrv_replace_child_noperm(s->child, NULL);
196
197
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
198
bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
199
}
200
201
- if (bdrv_child_get_parent_aio_context(child) != s->old_parent_ctx) {
202
+ if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
203
GSList *ignore;
204
205
/* No need to ignore `child`, because it has been detached already */
206
ignore = NULL;
207
- child->klass->can_set_aio_ctx(child, s->old_parent_ctx, &ignore,
208
- &error_abort);
209
+ s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
210
+ &error_abort);
211
g_slist_free(ignore);
212
213
ignore = NULL;
214
- child->klass->set_aio_ctx(child, s->old_parent_ctx, &ignore);
215
+ s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
216
g_slist_free(ignore);
217
}
218
219
bdrv_unref(bs);
220
- bdrv_child_free(child);
221
- *s->child = NULL;
222
+ bdrv_child_free(s->child);
223
}
224
225
static TransactionActionDrv bdrv_attach_child_common_drv = {
226
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
227
/*
228
* Common part of attaching bdrv child to bs or to blk or to job
229
*
230
- * Resulting new child is returned through @child.
231
- * At start *@child must be NULL.
232
- * @child is saved to a new entry of @tran, so that *@child could be reverted to
233
- * NULL on abort(). So referenced variable must live at least until transaction
234
- * end.
235
- *
236
* Function doesn't update permissions, caller is responsible for this.
237
+ *
238
+ * Returns new created child.
239
*/
240
-static int bdrv_attach_child_common(BlockDriverState *child_bs,
241
- const char *child_name,
242
- const BdrvChildClass *child_class,
243
- BdrvChildRole child_role,
244
- uint64_t perm, uint64_t shared_perm,
245
- void *opaque, BdrvChild **child,
246
- Transaction *tran, Error **errp)
247
+static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
248
+ const char *child_name,
249
+ const BdrvChildClass *child_class,
250
+ BdrvChildRole child_role,
251
+ uint64_t perm, uint64_t shared_perm,
252
+ void *opaque,
253
+ Transaction *tran, Error **errp)
254
{
255
BdrvChild *new_child;
256
AioContext *parent_ctx;
257
AioContext *child_ctx = bdrv_get_aio_context(child_bs);
258
259
- assert(child);
260
- assert(*child == NULL);
261
assert(child_class->get_parent_desc);
262
GLOBAL_STATE_CODE();
263
264
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
265
if (ret < 0) {
266
error_propagate(errp, local_err);
267
bdrv_child_free(new_child);
268
- return ret;
269
+ return NULL;
270
}
271
}
272
273
bdrv_ref(child_bs);
274
bdrv_replace_child_noperm(new_child, child_bs);
275
276
- *child = new_child;
277
-
278
BdrvAttachChildCommonState *s = g_new(BdrvAttachChildCommonState, 1);
279
*s = (BdrvAttachChildCommonState) {
280
- .child = child,
281
+ .child = new_child,
282
.old_parent_ctx = parent_ctx,
283
.old_child_ctx = child_ctx,
284
};
285
tran_add(tran, &bdrv_attach_child_common_drv, s);
286
287
- return 0;
288
+ return new_child;
289
}
290
291
/*
292
- * Variable referenced by @child must live at least until transaction end.
293
- * (see bdrv_attach_child_common() doc for details)
294
- *
295
* Function doesn't update permissions, caller is responsible for this.
296
*/
297
-static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
298
- BlockDriverState *child_bs,
299
- const char *child_name,
300
- const BdrvChildClass *child_class,
301
- BdrvChildRole child_role,
302
- BdrvChild **child,
303
- Transaction *tran,
304
- Error **errp)
305
+static BdrvChild *bdrv_attach_child_noperm(BlockDriverState *parent_bs,
306
+ BlockDriverState *child_bs,
307
+ const char *child_name,
308
+ const BdrvChildClass *child_class,
309
+ BdrvChildRole child_role,
310
+ Transaction *tran,
311
+ Error **errp)
312
{
313
- int ret;
314
uint64_t perm, shared_perm;
315
316
assert(parent_bs->drv);
317
@@ -XXX,XX +XXX,XX @@ static int bdrv_attach_child_noperm(BlockDriverState *parent_bs,
318
if (bdrv_recurse_has_child(child_bs, parent_bs)) {
319
error_setg(errp, "Making '%s' a %s child of '%s' would create a cycle",
320
child_bs->node_name, child_name, parent_bs->node_name);
321
- return -EINVAL;
322
+ return NULL;
323
}
324
325
bdrv_get_cumulative_perm(parent_bs, &perm, &shared_perm);
326
bdrv_child_perm(parent_bs, child_bs, NULL, child_role, NULL,
327
perm, shared_perm, &perm, &shared_perm);
328
329
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
330
- child_role, perm, shared_perm, parent_bs,
331
- child, tran, errp);
332
- if (ret < 0) {
333
- return ret;
334
- }
335
-
336
- return 0;
337
+ return bdrv_attach_child_common(child_bs, child_name, child_class,
338
+ child_role, perm, shared_perm, parent_bs,
339
+ tran, errp);
340
}
341
342
static void bdrv_detach_child(BdrvChild *child)
343
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
344
void *opaque, Error **errp)
345
{
346
int ret;
347
- BdrvChild *child = NULL;
348
+ BdrvChild *child;
349
Transaction *tran = tran_new();
350
351
GLOBAL_STATE_CODE();
352
353
- ret = bdrv_attach_child_common(child_bs, child_name, child_class,
354
+ child = bdrv_attach_child_common(child_bs, child_name, child_class,
355
child_role, perm, shared_perm, opaque,
356
- &child, tran, errp);
357
- if (ret < 0) {
358
+ tran, errp);
359
+ if (!child) {
360
+ ret = -EINVAL;
361
goto out;
362
}
363
364
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
365
366
out:
367
tran_finalize(tran, ret);
368
- /* child is unset on failure by bdrv_attach_child_common_abort() */
369
- assert((ret < 0) == !child);
370
371
bdrv_unref(child_bs);
372
- return child;
373
+
374
+ return ret < 0 ? NULL : child;
375
}
376
377
/*
378
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
379
Error **errp)
380
{
381
int ret;
382
- BdrvChild *child = NULL;
383
+ BdrvChild *child;
384
Transaction *tran = tran_new();
385
386
GLOBAL_STATE_CODE();
387
388
- ret = bdrv_attach_child_noperm(parent_bs, child_bs, child_name, child_class,
389
- child_role, &child, tran, errp);
390
- if (ret < 0) {
391
+ child = bdrv_attach_child_noperm(parent_bs, child_bs, child_name,
392
+ child_class, child_role, tran, errp);
393
+ if (!child) {
394
+ ret = -EINVAL;
395
goto out;
396
}
397
398
@@ -XXX,XX +XXX,XX @@ BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
399
400
out:
401
tran_finalize(tran, ret);
402
- /* child is unset on failure by bdrv_attach_child_common_abort() */
403
- assert((ret < 0) == !child);
404
405
bdrv_unref(child_bs);
406
407
- return child;
408
+ return ret < 0 ? NULL : child;
409
}
410
411
/* Callers must ensure that child->frozen is false. */
412
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
413
bool is_backing,
414
Transaction *tran, Error **errp)
415
{
416
- int ret = 0;
417
bool update_inherits_from =
418
bdrv_inherits_from_recursive(child_bs, parent_bs);
419
BdrvChild *child = is_backing ? parent_bs->backing : parent_bs->file;
420
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
421
goto out;
422
}
423
424
- ret = bdrv_attach_child_noperm(parent_bs, child_bs,
425
- is_backing ? "backing" : "file",
426
- &child_of_bds, role,
427
- is_backing ? &parent_bs->backing :
428
- &parent_bs->file,
429
- tran, errp);
430
- if (ret < 0) {
431
- return ret;
432
+ child = bdrv_attach_child_noperm(parent_bs, child_bs,
433
+ is_backing ? "backing" : "file",
434
+ &child_of_bds, role,
435
+ tran, errp);
436
+ if (!child) {
437
+ return -EINVAL;
438
}
439
440
441
@@ -XXX,XX +XXX,XX @@ int bdrv_open_file_child(const char *filename,
442
443
/* commit_top and mirror_top don't use this function */
444
assert(!parent->drv->filtered_child_is_backing);
445
-
446
role = parent->drv->is_filter ?
447
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
448
449
- parent->file = bdrv_open_child(filename, options, bdref_key, parent,
450
- &child_of_bds, role, false, errp);
451
+ if (!bdrv_open_child(filename, options, bdref_key, parent,
452
+ &child_of_bds, role, false, errp))
453
+ {
454
+ return -EINVAL;
455
+ }
456
457
- return parent->file ? 0 : -EINVAL;
458
+ return 0;
459
}
460
461
/*
462
@@ -XXX,XX +XXX,XX @@ static void bdrv_close(BlockDriverState *bs)
463
bdrv_unref_child(bs, child);
464
}
465
466
- bs->backing = NULL;
467
- bs->file = NULL;
468
+ assert(!bs->backing);
469
+ assert(!bs->file);
470
g_free(bs->opaque);
471
bs->opaque = NULL;
472
qatomic_set(&bs->copy_on_read, 0);
473
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
474
return ret;
475
}
476
477
-typedef struct BdrvRemoveFilterOrCowChild {
478
- BdrvChild *child;
479
- bool is_backing;
480
-} BdrvRemoveFilterOrCowChild;
481
-
482
-static void bdrv_remove_filter_or_cow_child_abort(void *opaque)
483
-{
484
- BdrvRemoveFilterOrCowChild *s = opaque;
485
- BlockDriverState *parent_bs = s->child->opaque;
486
-
487
- if (s->is_backing) {
488
- parent_bs->backing = s->child;
489
- } else {
490
- parent_bs->file = s->child;
491
- }
492
-
493
- /*
494
- * We don't have to restore child->bs here to undo bdrv_replace_child_tran()
495
- * because that function is transactionable and it registered own completion
496
- * entries in @tran, so .abort() for bdrv_replace_child_safe() will be
497
- * called automatically.
498
- */
499
-}
500
-
501
static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
502
{
503
- BdrvRemoveFilterOrCowChild *s = opaque;
504
GLOBAL_STATE_CODE();
505
- bdrv_child_free(s->child);
506
+ bdrv_child_free(opaque);
507
}
508
509
static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
510
- .abort = bdrv_remove_filter_or_cow_child_abort,
511
.commit = bdrv_remove_filter_or_cow_child_commit,
512
- .clean = g_free,
513
};
514
515
/*
516
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
517
BdrvChild *child,
518
Transaction *tran)
519
{
520
- BdrvRemoveFilterOrCowChild *s;
521
-
522
assert(child == bs->backing || child == bs->file);
523
524
if (!child) {
525
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
526
bdrv_replace_child_tran(child, NULL, tran);
527
}
528
529
- s = g_new(BdrvRemoveFilterOrCowChild, 1);
530
- *s = (BdrvRemoveFilterOrCowChild) {
531
- .child = child,
532
- .is_backing = (child == bs->backing),
533
- };
534
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
535
-
536
- if (s->is_backing) {
537
- bs->backing = NULL;
538
- } else {
539
- bs->file = NULL;
540
- }
541
+ tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
542
}
543
544
/*
545
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
546
Error **errp)
547
{
548
int ret;
549
+ BdrvChild *child;
550
Transaction *tran = tran_new();
551
552
GLOBAL_STATE_CODE();
553
554
assert(!bs_new->backing);
555
556
- ret = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
557
- &child_of_bds, bdrv_backing_role(bs_new),
558
- &bs_new->backing, tran, errp);
559
- if (ret < 0) {
560
+ child = bdrv_attach_child_noperm(bs_new, bs_top, "backing",
561
+ &child_of_bds, bdrv_backing_role(bs_new),
562
+ tran, errp);
563
+ if (!child) {
564
+ ret = -EINVAL;
565
goto out;
566
}
567
568
diff --git a/block/raw-format.c b/block/raw-format.c
569
index XXXXXXX..XXXXXXX 100644
570
--- a/block/raw-format.c
571
+++ b/block/raw-format.c
572
@@ -XXX,XX +XXX,XX @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags,
573
file_role = BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY;
574
}
575
576
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
577
- file_role, false, errp);
578
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
579
+ file_role, false, errp);
580
if (!bs->file) {
581
return -EINVAL;
582
}
583
diff --git a/block/snapshot-access.c b/block/snapshot-access.c
584
index XXXXXXX..XXXXXXX 100644
585
--- a/block/snapshot-access.c
586
+++ b/block/snapshot-access.c
587
@@ -XXX,XX +XXX,XX @@ static void snapshot_access_refresh_filename(BlockDriverState *bs)
588
static int snapshot_access_open(BlockDriverState *bs, QDict *options, int flags,
589
Error **errp)
590
{
591
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
592
- BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
593
- false, errp);
594
+ bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
595
+ BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY,
596
+ false, errp);
597
if (!bs->file) {
598
return -EINVAL;
599
}
600
diff --git a/block/snapshot.c b/block/snapshot.c
601
index XXXXXXX..XXXXXXX 100644
602
--- a/block/snapshot.c
603
+++ b/block/snapshot.c
604
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
605
606
/* .bdrv_open() will re-attach it */
607
bdrv_unref_child(bs, *fallback_ptr);
608
- *fallback_ptr = NULL;
609
610
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
611
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
612
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
613
index XXXXXXX..XXXXXXX 100644
614
--- a/tests/unit/test-bdrv-drain.c
615
+++ b/tests/unit/test-bdrv-drain.c
616
@@ -XXX,XX +XXX,XX @@ static void test_drop_intermediate_poll(void)
617
for (i = 0; i < 3; i++) {
618
if (i) {
619
/* Takes the reference to chain[i - 1] */
620
- chain[i]->backing = bdrv_attach_child(chain[i], chain[i - 1],
621
- "chain", &chain_child_class,
622
- BDRV_CHILD_COW, &error_abort);
623
+ bdrv_attach_child(chain[i], chain[i - 1], "chain",
624
+ &chain_child_class, BDRV_CHILD_COW, &error_abort);
625
}
626
}
627
628
@@ -XXX,XX +XXX,XX @@ static void do_test_replace_child_mid_drain(int old_drain_count,
629
new_child_bs->total_sectors = 1;
630
631
bdrv_ref(old_child_bs);
632
- parent_bs->backing = bdrv_attach_child(parent_bs, old_child_bs, "child",
633
- &child_of_bds, BDRV_CHILD_COW,
634
- &error_abort);
635
+ bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds,
636
+ BDRV_CHILD_COW, &error_abort);
637
638
for (i = 0; i < old_drain_count; i++) {
639
bdrv_drained_begin(old_child_bs);
640
--
641
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Now the indirection is not actually used, we can safely reduce it to
4
simple pointer. For consistency do a bit of refactoring to get rid of
5
_ptr suffixes that become meaningless.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20220726201134.924743-15-vsementsov@yandex-team.ru>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/snapshot.c | 38 ++++++++++++++++----------------------
13
1 file changed, 16 insertions(+), 22 deletions(-)
14
15
diff --git a/block/snapshot.c b/block/snapshot.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/snapshot.c
18
+++ b/block/snapshot.c
19
@@ -XXX,XX +XXX,XX @@ bool bdrv_snapshot_find_by_id_and_name(BlockDriverState *bs,
20
}
21
22
/**
23
- * Return a pointer to the child BDS pointer to which we can fall
24
+ * Return a pointer to child of given BDS to which we can fall
25
* back if the given BDS does not support snapshots.
26
* Return NULL if there is no BDS to (safely) fall back to.
27
- *
28
- * We need to return an indirect pointer because bdrv_snapshot_goto()
29
- * has to modify the BdrvChild pointer.
30
*/
31
-static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
32
+static BdrvChild *bdrv_snapshot_fallback_child(BlockDriverState *bs)
33
{
34
- BdrvChild **fallback;
35
- BdrvChild *child = bdrv_primary_child(bs);
36
+ BdrvChild *fallback = bdrv_primary_child(bs);
37
+ BdrvChild *child;
38
39
/* We allow fallback only to primary child */
40
- if (!child) {
41
+ if (!fallback) {
42
return NULL;
43
}
44
- fallback = (child == bs->file ? &bs->file : &bs->backing);
45
- assert(*fallback == child);
46
47
/*
48
* Check that there are no other children that would need to be
49
* snapshotted. If there are, it is not safe to fall back to
50
- * *fallback.
51
+ * fallback.
52
*/
53
QLIST_FOREACH(child, &bs->children, next) {
54
if (child->role & (BDRV_CHILD_DATA | BDRV_CHILD_METADATA |
55
BDRV_CHILD_FILTERED) &&
56
- child != *fallback)
57
+ child != fallback)
58
{
59
return NULL;
60
}
61
@@ -XXX,XX +XXX,XX @@ static BdrvChild **bdrv_snapshot_fallback_ptr(BlockDriverState *bs)
62
63
static BlockDriverState *bdrv_snapshot_fallback(BlockDriverState *bs)
64
{
65
- BdrvChild **child_ptr = bdrv_snapshot_fallback_ptr(bs);
66
- return child_ptr ? (*child_ptr)->bs : NULL;
67
+ return child_bs(bdrv_snapshot_fallback_child(bs));
68
}
69
70
int bdrv_can_snapshot(BlockDriverState *bs)
71
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
72
Error **errp)
73
{
74
BlockDriver *drv = bs->drv;
75
- BdrvChild **fallback_ptr;
76
+ BdrvChild *fallback;
77
int ret, open_ret;
78
79
GLOBAL_STATE_CODE();
80
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
81
return ret;
82
}
83
84
- fallback_ptr = bdrv_snapshot_fallback_ptr(bs);
85
- if (fallback_ptr) {
86
+ fallback = bdrv_snapshot_fallback_child(bs);
87
+ if (fallback) {
88
QDict *options;
89
QDict *file_options;
90
Error *local_err = NULL;
91
- BlockDriverState *fallback_bs = (*fallback_ptr)->bs;
92
- char *subqdict_prefix = g_strdup_printf("%s.", (*fallback_ptr)->name);
93
+ BlockDriverState *fallback_bs = fallback->bs;
94
+ char *subqdict_prefix = g_strdup_printf("%s.", fallback->name);
95
96
options = qdict_clone_shallow(bs->options);
97
98
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
99
qobject_unref(file_options);
100
g_free(subqdict_prefix);
101
102
- /* Force .bdrv_open() below to re-attach fallback_bs on *fallback_ptr */
103
- qdict_put_str(options, (*fallback_ptr)->name,
104
+ /* Force .bdrv_open() below to re-attach fallback_bs on fallback */
105
+ qdict_put_str(options, fallback->name,
106
bdrv_get_node_name(fallback_bs));
107
108
/* Now close bs, apply the snapshot on fallback_bs, and re-open bs */
109
@@ -XXX,XX +XXX,XX @@ int bdrv_snapshot_goto(BlockDriverState *bs,
110
}
111
112
/* .bdrv_open() will re-attach it */
113
- bdrv_unref_child(bs, *fallback_ptr);
114
+ bdrv_unref_child(bs, fallback);
115
116
ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp);
117
open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err);
118
--
119
2.37.3
diff view generated by jsdifflib
New patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
1
2
3
Now the function can remove any child, so give it more common name.
4
Drop assertions and drop bs argument which becomes unused. Function
5
would be reused in a further commit.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20220726201134.924743-16-vsementsov@yandex-team.ru>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block.c | 27 +++++++++------------------
13
1 file changed, 9 insertions(+), 18 deletions(-)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static bool bdrv_recurse_has_child(BlockDriverState *bs,
20
21
static void bdrv_replace_child_noperm(BdrvChild *child,
22
BlockDriverState *new_bs);
23
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
24
- BdrvChild *child,
25
- Transaction *tran);
26
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran);
27
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
28
Transaction *tran);
29
30
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
31
32
if (child) {
33
bdrv_unset_inherits_from(parent_bs, child, tran);
34
- bdrv_remove_file_or_backing_child(parent_bs, child, tran);
35
+ bdrv_remove_child(child, tran);
36
}
37
38
if (!child_bs) {
39
@@ -XXX,XX +XXX,XX @@ static bool should_update_child(BdrvChild *c, BlockDriverState *to)
40
return ret;
41
}
42
43
-static void bdrv_remove_filter_or_cow_child_commit(void *opaque)
44
+static void bdrv_remove_child_commit(void *opaque)
45
{
46
GLOBAL_STATE_CODE();
47
bdrv_child_free(opaque);
48
}
49
50
-static TransactionActionDrv bdrv_remove_filter_or_cow_child_drv = {
51
- .commit = bdrv_remove_filter_or_cow_child_commit,
52
+static TransactionActionDrv bdrv_remove_child_drv = {
53
+ .commit = bdrv_remove_child_commit,
54
};
55
56
-/*
57
- * A function to remove backing or file child of @bs.
58
- * Function doesn't update permissions, caller is responsible for this.
59
- */
60
-static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
61
- BdrvChild *child,
62
- Transaction *tran)
63
+/* Function doesn't update permissions, caller is responsible for this. */
64
+static void bdrv_remove_child(BdrvChild *child, Transaction *tran)
65
{
66
- assert(child == bs->backing || child == bs->file);
67
-
68
if (!child) {
69
return;
70
}
71
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
72
bdrv_replace_child_tran(child, NULL, tran);
73
}
74
75
- tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, child);
76
+ tran_add(tran, &bdrv_remove_child_drv, child);
77
}
78
79
/*
80
@@ -XXX,XX +XXX,XX @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
81
static void bdrv_remove_filter_or_cow_child(BlockDriverState *bs,
82
Transaction *tran)
83
{
84
- bdrv_remove_file_or_backing_child(bs, bdrv_filter_or_cow_child(bs), tran);
85
+ bdrv_remove_child(bdrv_filter_or_cow_child(bs), tran);
86
}
87
88
static int bdrv_replace_node_noperm(BlockDriverState *from,
89
--
90
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Also here ->aio_context is read by I/O threads and written
4
under BQL.
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Message-Id: <20221025084952.2139888-2-eesposit@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block.c | 2 ++
13
1 file changed, 2 insertions(+)
14
15
diff --git a/block.c b/block.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block.c
18
+++ b/block.c
19
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_aio_context(BlockDriverState *bs)
20
if (bs->quiesce_counter) {
21
aio_enable_external(bs->aio_context);
22
}
23
+ assert_bdrv_graph_writable(bs);
24
bs->aio_context = NULL;
25
}
26
27
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
28
aio_disable_external(new_context);
29
}
30
31
+ assert_bdrv_graph_writable(bs);
32
bs->aio_context = new_context;
33
34
if (bs->drv && bs->drv->bdrv_attach_aio_context) {
35
--
36
2.37.3
diff view generated by jsdifflib
New patch
1
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
3
Simplify the way the aiocontext can be changed in a BDS graph.
4
There are currently two problems in bdrv_try_set_aio_context:
5
- There is a confusion of AioContext locks taken and released, because
6
we assume that old aiocontext is always taken and new one is
7
taken inside.
8
9
- It doesn't look very safe to call bdrv_drained_begin while some
10
nodes have already switched to the new aiocontext and others haven't.
11
This could be especially dangerous because bdrv_drained_begin polls, so
12
something else could be executed while graph is in an inconsistent
13
state.
14
15
Additional minor nitpick: can_set and set_ callbacks both traverse the
16
graph, both using the ignored list of visited nodes in a different way.
17
18
Therefore, get rid of all of this and introduce a new callback,
19
change_aio_context, that uses transactions to efficiently, cleanly
20
and most importantly safely change the aiocontext of a graph.
21
22
This new callback is a "merge" of the two previous ones:
23
- Just like can_set_aio_context, recursively traverses the graph.
24
Marks all nodes that are visited using a GList, and checks if
25
they *could* change the aio_context.
26
- For each node that passes the above check, drain it and add a new transaction
27
that implements a callback that effectively changes the aiocontext.
28
- Once done, the recursive function returns if *all* nodes can change
29
the AioContext. If so, commit the above transactions.
30
Regardless of the outcome, call transaction.clean() to undo all drains
31
done in the recursion.
32
- The transaction list is scanned only after all nodes are being drained, so
33
we are sure that they all are in the same context, and then
34
we switch their AioContext, concluding the drain only after all nodes
35
switched to the new AioContext. In this way we make sure that
36
bdrv_drained_begin() is always called under the old AioContext, and
37
bdrv_drained_end() under the new one.
38
- Because of the above, we don't need to release and re-acquire the
39
old AioContext every time, as everything is done once (and not
40
per-node drain and aiocontext change).
41
42
Note that the "change" API is not yet invoked anywhere.
43
44
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
45
Message-Id: <20221025084952.2139888-3-eesposit@redhat.com>
46
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
47
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
48
---
49
include/block/block-global-state.h | 6 +
50
include/block/block_int-common.h | 3 +
51
block.c | 220 ++++++++++++++++++++++++++++-
52
3 files changed, 228 insertions(+), 1 deletion(-)
53
54
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
55
index XXXXXXX..XXXXXXX 100644
56
--- a/include/block/block-global-state.h
57
+++ b/include/block/block-global-state.h
58
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
59
GSList **ignore, Error **errp);
60
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
61
62
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
63
+ GSList **visited, Transaction *tran,
64
+ Error **errp);
65
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
66
+ BdrvChild *ignore_child, Error **errp);
67
+
68
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
69
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
70
71
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
72
index XXXXXXX..XXXXXXX 100644
73
--- a/include/block/block_int-common.h
74
+++ b/include/block/block_int-common.h
75
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
76
GSList **ignore, Error **errp);
77
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
78
79
+ bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
80
+ GSList **visited, Transaction *tran, Error **errp);
81
+
82
AioContext *(*get_parent_aio_context)(BdrvChild *child);
83
84
/*
85
diff --git a/block.c b/block.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/block.c
88
+++ b/block.c
89
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
90
91
static bool bdrv_backing_overridden(BlockDriverState *bs);
92
93
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
94
+ GSList **visited, Transaction *tran,
95
+ Error **errp);
96
+
97
/* If non-zero, use only whitelisted block drivers */
98
static int use_bdrv_whitelist;
99
100
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
101
* must not own the AioContext lock for new_context (unless new_context is the
102
* same as the current context of bs).
103
*
104
- * @ignore will accumulate all visited BdrvChild object. The caller is
105
+ * @ignore will accumulate all visited BdrvChild objects. The caller is
106
* responsible for freeing the list afterwards.
107
*/
108
void bdrv_set_aio_context_ignore(BlockDriverState *bs,
109
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
110
return true;
111
}
112
113
+typedef struct BdrvStateSetAioContext {
114
+ AioContext *new_ctx;
115
+ BlockDriverState *bs;
116
+} BdrvStateSetAioContext;
117
+
118
+static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
119
+ GSList **visited, Transaction *tran,
120
+ Error **errp)
121
+{
122
+ GLOBAL_STATE_CODE();
123
+ if (g_slist_find(*visited, c)) {
124
+ return true;
125
+ }
126
+ *visited = g_slist_prepend(*visited, c);
127
+
128
+ /*
129
+ * A BdrvChildClass that doesn't handle AioContext changes cannot
130
+ * tolerate any AioContext changes
131
+ */
132
+ if (!c->klass->change_aio_ctx) {
133
+ char *user = bdrv_child_user_desc(c);
134
+ error_setg(errp, "Changing iothreads is not supported by %s", user);
135
+ g_free(user);
136
+ return false;
137
+ }
138
+ if (!c->klass->change_aio_ctx(c, ctx, visited, tran, errp)) {
139
+ assert(!errp || *errp);
140
+ return false;
141
+ }
142
+ return true;
143
+}
144
+
145
bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
146
GSList **ignore, Error **errp)
147
{
148
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
149
return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
150
}
151
152
+bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
153
+ GSList **visited, Transaction *tran,
154
+ Error **errp)
155
+{
156
+ GLOBAL_STATE_CODE();
157
+ if (g_slist_find(*visited, c)) {
158
+ return true;
159
+ }
160
+ *visited = g_slist_prepend(*visited, c);
161
+ return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
162
+}
163
+
164
/* @ignore will accumulate all visited BdrvChild object. The caller is
165
* responsible for freeing the list afterwards. */
166
bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
167
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
168
return true;
169
}
170
171
+static void bdrv_set_aio_context_clean(void *opaque)
172
+{
173
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
174
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
175
+
176
+ /* Paired with bdrv_drained_begin in bdrv_change_aio_context() */
177
+ bdrv_drained_end(bs);
178
+
179
+ g_free(state);
180
+}
181
+
182
+static void bdrv_set_aio_context_commit(void *opaque)
183
+{
184
+ BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
185
+ BlockDriverState *bs = (BlockDriverState *) state->bs;
186
+ AioContext *new_context = state->new_ctx;
187
+ AioContext *old_context = bdrv_get_aio_context(bs);
188
+ assert_bdrv_graph_writable(bs);
189
+
190
+ /*
191
+ * Take the old AioContex when detaching it from bs.
192
+ * At this point, new_context lock is already acquired, and we are now
193
+ * also taking old_context. This is safe as long as bdrv_detach_aio_context
194
+ * does not call AIO_POLL_WHILE().
195
+ */
196
+ if (old_context != qemu_get_aio_context()) {
197
+ aio_context_acquire(old_context);
198
+ }
199
+ bdrv_detach_aio_context(bs);
200
+ if (old_context != qemu_get_aio_context()) {
201
+ aio_context_release(old_context);
202
+ }
203
+ bdrv_attach_aio_context(bs, new_context);
204
+}
205
+
206
+static TransactionActionDrv set_aio_context = {
207
+ .commit = bdrv_set_aio_context_commit,
208
+ .clean = bdrv_set_aio_context_clean,
209
+};
210
+
211
+/*
212
+ * Changes the AioContext used for fd handlers, timers, and BHs by this
213
+ * BlockDriverState and all its children and parents.
214
+ *
215
+ * Must be called from the main AioContext.
216
+ *
217
+ * The caller must own the AioContext lock for the old AioContext of bs, but it
218
+ * must not own the AioContext lock for new_context (unless new_context is the
219
+ * same as the current context of bs).
220
+ *
221
+ * @visited will accumulate all visited BdrvChild objects. The caller is
222
+ * responsible for freeing the list afterwards.
223
+ */
224
+static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
225
+ GSList **visited, Transaction *tran,
226
+ Error **errp)
227
+{
228
+ BdrvChild *c;
229
+ BdrvStateSetAioContext *state;
230
+
231
+ GLOBAL_STATE_CODE();
232
+
233
+ if (bdrv_get_aio_context(bs) == ctx) {
234
+ return true;
235
+ }
236
+
237
+ QLIST_FOREACH(c, &bs->parents, next_parent) {
238
+ if (!bdrv_parent_change_aio_context(c, ctx, visited, tran, errp)) {
239
+ return false;
240
+ }
241
+ }
242
+
243
+ QLIST_FOREACH(c, &bs->children, next) {
244
+ if (!bdrv_child_change_aio_context(c, ctx, visited, tran, errp)) {
245
+ return false;
246
+ }
247
+ }
248
+
249
+ state = g_new(BdrvStateSetAioContext, 1);
250
+ *state = (BdrvStateSetAioContext) {
251
+ .new_ctx = ctx,
252
+ .bs = bs,
253
+ };
254
+
255
+ /* Paired with bdrv_drained_end in bdrv_set_aio_context_clean() */
256
+ bdrv_drained_begin(bs);
257
+
258
+ tran_add(tran, &set_aio_context, state);
259
+
260
+ return true;
261
+}
262
+
263
int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
264
BdrvChild *ignore_child, Error **errp)
265
{
266
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
267
return 0;
268
}
269
270
+/*
271
+ * Change bs's and recursively all of its parents' and children's AioContext
272
+ * to the given new context, returning an error if that isn't possible.
273
+ *
274
+ * If ignore_child is not NULL, that child (and its subgraph) will not
275
+ * be touched.
276
+ *
277
+ * This function still requires the caller to take the bs current
278
+ * AioContext lock, otherwise draining will fail since AIO_WAIT_WHILE
279
+ * assumes the lock is always held if bs is in another AioContext.
280
+ * For the same reason, it temporarily also holds the new AioContext, since
281
+ * bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
282
+ * Therefore the new AioContext lock must not be taken by the caller.
283
+ */
284
+int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
285
+ BdrvChild *ignore_child, Error **errp)
286
+{
287
+ Transaction *tran;
288
+ GSList *visited;
289
+ int ret;
290
+ AioContext *old_context = bdrv_get_aio_context(bs);
291
+ GLOBAL_STATE_CODE();
292
+
293
+ /*
294
+ * Recursion phase: go through all nodes of the graph.
295
+ * Take care of checking that all nodes support changing AioContext
296
+ * and drain them, builing a linear list of callbacks to run if everything
297
+ * is successful (the transaction itself).
298
+ */
299
+ tran = tran_new();
300
+ visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
301
+ ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
302
+ g_slist_free(visited);
303
+
304
+ /*
305
+ * Linear phase: go through all callbacks collected in the transaction.
306
+ * Run all callbacks collected in the recursion to switch all nodes
307
+ * AioContext lock (transaction commit), or undo all changes done in the
308
+ * recursion (transaction abort).
309
+ */
310
+
311
+ if (!ret) {
312
+ /* Just run clean() callbacks. No AioContext changed. */
313
+ tran_abort(tran);
314
+ return -EPERM;
315
+ }
316
+
317
+ /*
318
+ * Release old AioContext, it won't be needed anymore, as all
319
+ * bdrv_drained_begin() have been called already.
320
+ */
321
+ if (qemu_get_aio_context() != old_context) {
322
+ aio_context_release(old_context);
323
+ }
324
+
325
+ /*
326
+ * Acquire new AioContext since bdrv_drained_end() is going to be called
327
+ * after we switched all nodes in the new AioContext, and the function
328
+ * assumes that the lock of the bs is always taken.
329
+ */
330
+ if (qemu_get_aio_context() != ctx) {
331
+ aio_context_acquire(ctx);
332
+ }
333
+
334
+ tran_commit(tran);
335
+
336
+ if (qemu_get_aio_context() != ctx) {
337
+ aio_context_release(ctx);
338
+ }
339
+
340
+ /* Re-acquire the old AioContext, since the caller takes and releases it. */
341
+ if (qemu_get_aio_context() != old_context) {
342
+ aio_context_acquire(old_context);
343
+ }
344
+
345
+ return 0;
346
+}
347
+
348
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
349
Error **errp)
350
{
351
--
352
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Minor performance improvement, but given that we have hash tables
4
available, avoid iterating in the visited nodes list every time just
5
to check if a node has been already visited.
6
7
The data structure is not actually a proper hash map, but an hash set,
8
as we are just adding nodes and not key,value pairs.
9
10
Suggested-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-4-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
include/block/block-global-state.h | 2 +-
17
include/block/block_int-common.h | 3 ++-
18
block.c | 28 ++++++++++++++++------------
19
3 files changed, 19 insertions(+), 14 deletions(-)
20
21
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/block/block-global-state.h
24
+++ b/include/block/block-global-state.h
25
@@ -XXX,XX +XXX,XX @@ bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
26
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
27
28
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
29
- GSList **visited, Transaction *tran,
30
+ GHashTable *visited, Transaction *tran,
31
Error **errp);
32
int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
33
BdrvChild *ignore_child, Error **errp);
34
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
35
index XXXXXXX..XXXXXXX 100644
36
--- a/include/block/block_int-common.h
37
+++ b/include/block/block_int-common.h
38
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
39
void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
40
41
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
42
- GSList **visited, Transaction *tran, Error **errp);
43
+ GHashTable *visited, Transaction *tran,
44
+ Error **errp);
45
46
AioContext *(*get_parent_aio_context)(BdrvChild *child);
47
48
diff --git a/block.c b/block.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block.c
51
+++ b/block.c
52
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_abort(BDRVReopenState *reopen_state);
53
static bool bdrv_backing_overridden(BlockDriverState *bs);
54
55
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
56
- GSList **visited, Transaction *tran,
57
+ GHashTable *visited, Transaction *tran,
58
Error **errp);
59
60
/* If non-zero, use only whitelisted block drivers */
61
@@ -XXX,XX +XXX,XX @@ typedef struct BdrvStateSetAioContext {
62
} BdrvStateSetAioContext;
63
64
static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
65
- GSList **visited, Transaction *tran,
66
+ GHashTable *visited,
67
+ Transaction *tran,
68
Error **errp)
69
{
70
GLOBAL_STATE_CODE();
71
- if (g_slist_find(*visited, c)) {
72
+ if (g_hash_table_contains(visited, c)) {
73
return true;
74
}
75
- *visited = g_slist_prepend(*visited, c);
76
+ g_hash_table_add(visited, c);
77
78
/*
79
* A BdrvChildClass that doesn't handle AioContext changes cannot
80
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
81
}
82
83
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
84
- GSList **visited, Transaction *tran,
85
+ GHashTable *visited, Transaction *tran,
86
Error **errp)
87
{
88
GLOBAL_STATE_CODE();
89
- if (g_slist_find(*visited, c)) {
90
+ if (g_hash_table_contains(visited, c)) {
91
return true;
92
}
93
- *visited = g_slist_prepend(*visited, c);
94
+ g_hash_table_add(visited, c);
95
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
96
}
97
98
@@ -XXX,XX +XXX,XX @@ static TransactionActionDrv set_aio_context = {
99
* responsible for freeing the list afterwards.
100
*/
101
static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
102
- GSList **visited, Transaction *tran,
103
+ GHashTable *visited, Transaction *tran,
104
Error **errp)
105
{
106
BdrvChild *c;
107
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
108
BdrvChild *ignore_child, Error **errp)
109
{
110
Transaction *tran;
111
- GSList *visited;
112
+ GHashTable *visited;
113
int ret;
114
AioContext *old_context = bdrv_get_aio_context(bs);
115
GLOBAL_STATE_CODE();
116
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
117
* is successful (the transaction itself).
118
*/
119
tran = tran_new();
120
- visited = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
121
- ret = bdrv_change_aio_context(bs, ctx, &visited, tran, errp);
122
- g_slist_free(visited);
123
+ visited = g_hash_table_new(NULL, NULL);
124
+ if (ignore_child) {
125
+ g_hash_table_add(visited, ignore_child);
126
+ }
127
+ ret = bdrv_change_aio_context(bs, ctx, visited, tran, errp);
128
+ g_hash_table_destroy(visited);
129
130
/*
131
* Linear phase: go through all callbacks collected in the transaction.
132
--
133
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
child_job_change_aio_ctx() is very similar to
4
child_job_can_set_aio_ctx(), but it implements a new transaction
5
so that if all check pass, the new transaction's .commit()
6
will take care of changin the BlockJob AioContext.
7
child_job_set_aio_ctx_commit() is similar to child_job_set_aio_ctx(),
8
but it doesn't need to invoke the recursion, as this is already
9
taken care by child_job_change_aio_ctx().
10
11
Note: bdrv_child_try_change_aio_context() is not called by
12
anyone at this point.
13
14
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Message-Id: <20221025084952.2139888-5-eesposit@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
---
20
blockjob.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
21
1 file changed, 45 insertions(+)
22
23
diff --git a/blockjob.c b/blockjob.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/blockjob.c
26
+++ b/blockjob.c
27
@@ -XXX,XX +XXX,XX @@ static void child_job_drained_end(BdrvChild *c, int *drained_end_counter)
28
job_resume(&job->job);
29
}
30
31
+typedef struct BdrvStateChildJobContext {
32
+ AioContext *new_ctx;
33
+ BlockJob *job;
34
+} BdrvStateChildJobContext;
35
+
36
+static void child_job_set_aio_ctx_commit(void *opaque)
37
+{
38
+ BdrvStateChildJobContext *s = opaque;
39
+ BlockJob *job = s->job;
40
+
41
+ job_set_aio_context(&job->job, s->new_ctx);
42
+}
43
+
44
+static TransactionActionDrv change_child_job_context = {
45
+ .commit = child_job_set_aio_ctx_commit,
46
+ .clean = g_free,
47
+};
48
+
49
+static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
50
+ GHashTable *visited, Transaction *tran,
51
+ Error **errp)
52
+{
53
+ BlockJob *job = c->opaque;
54
+ BdrvStateChildJobContext *s;
55
+ GSList *l;
56
+
57
+ for (l = job->nodes; l; l = l->next) {
58
+ BdrvChild *sibling = l->data;
59
+ if (!bdrv_child_change_aio_context(sibling, ctx, visited,
60
+ tran, errp)) {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ s = g_new(BdrvStateChildJobContext, 1);
66
+ *s = (BdrvStateChildJobContext) {
67
+ .new_ctx = ctx,
68
+ .job = job,
69
+ };
70
+
71
+ tran_add(tran, &change_child_job_context, s);
72
+ return true;
73
+}
74
+
75
static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
76
GSList **ignore, Error **errp)
77
{
78
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
79
.drained_end = child_job_drained_end,
80
.can_set_aio_ctx = child_job_can_set_aio_ctx,
81
.set_aio_ctx = child_job_set_aio_ctx,
82
+ .change_aio_ctx = child_job_change_aio_ctx,
83
.stay_at_node = true,
84
.get_parent_aio_context = child_job_get_parent_aio_context,
85
};
86
--
87
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
bdrv_child_cb_change_aio_ctx() is identical to
4
bdrv_child_cb_can_set_aio_ctx(), as we only need
5
to recursively go on the parent bs.
6
7
Note: bdrv_child_try_change_aio_context() is not called by
8
anyone at this point.
9
10
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-6-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block.c | 9 +++++++++
17
1 file changed, 9 insertions(+)
18
19
diff --git a/block.c b/block.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/block.c
22
+++ b/block.c
23
@@ -XXX,XX +XXX,XX @@ static int bdrv_child_cb_inactivate(BdrvChild *child)
24
return 0;
25
}
26
27
+static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
28
+ GHashTable *visited, Transaction *tran,
29
+ Error **errp)
30
+{
31
+ BlockDriverState *bs = child->opaque;
32
+ return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
33
+}
34
+
35
static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
36
GSList **ignore, Error **errp)
37
{
38
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
39
.inactivate = bdrv_child_cb_inactivate,
40
.can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
41
.set_aio_ctx = bdrv_child_cb_set_aio_ctx,
42
+ .change_aio_ctx = bdrv_child_cb_change_aio_ctx,
43
.update_filename = bdrv_child_cb_update_filename,
44
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
45
};
46
--
47
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
blk_root_change_aio_ctx() is very similar to blk_root_can_set_aio_ctx(),
4
but implements a new transaction so that if all check pass, the new
5
transaction's .commit will take care of changing the BlockBackend
6
AioContext. blk_root_set_aio_ctx_commit() is the same as
7
blk_root_set_aio_ctx().
8
9
Note: bdrv_child_try_change_aio_context() is not called by
10
anyone at this point.
11
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
14
Message-Id: <20221025084952.2139888-7-eesposit@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
16
---
17
block/block-backend.c | 52 +++++++++++++++++++++++++++++++++++++++++++
18
1 file changed, 52 insertions(+)
19
20
diff --git a/block/block-backend.c b/block/block-backend.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block/block-backend.c
23
+++ b/block/block-backend.c
24
@@ -XXX,XX +XXX,XX @@ static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
25
GSList **ignore, Error **errp);
26
static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
27
GSList **ignore);
28
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
29
+ GHashTable *visited, Transaction *tran,
30
+ Error **errp);
31
32
static char *blk_root_get_parent_desc(BdrvChild *child)
33
{
34
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
35
36
.can_set_aio_ctx = blk_root_can_set_aio_ctx,
37
.set_aio_ctx = blk_root_set_aio_ctx,
38
+ .change_aio_ctx = blk_root_change_aio_ctx,
39
40
.get_parent_aio_context = blk_root_get_parent_aio_context,
41
};
42
@@ -XXX,XX +XXX,XX @@ int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
43
return blk_do_set_aio_context(blk, new_context, true, errp);
44
}
45
46
+typedef struct BdrvStateBlkRootContext {
47
+ AioContext *new_ctx;
48
+ BlockBackend *blk;
49
+} BdrvStateBlkRootContext;
50
+
51
+static void blk_root_set_aio_ctx_commit(void *opaque)
52
+{
53
+ BdrvStateBlkRootContext *s = opaque;
54
+ BlockBackend *blk = s->blk;
55
+
56
+ blk_do_set_aio_context(blk, s->new_ctx, false, &error_abort);
57
+}
58
+
59
+static TransactionActionDrv set_blk_root_context = {
60
+ .commit = blk_root_set_aio_ctx_commit,
61
+ .clean = g_free,
62
+};
63
+
64
+static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
65
+ GHashTable *visited, Transaction *tran,
66
+ Error **errp)
67
+{
68
+ BlockBackend *blk = child->opaque;
69
+ BdrvStateBlkRootContext *s;
70
+
71
+ if (!blk->allow_aio_context_change) {
72
+ /*
73
+ * Manually created BlockBackends (those with a name) that are not
74
+ * attached to anything can change their AioContext without updating
75
+ * their user; return an error for others.
76
+ */
77
+ if (!blk->name || blk->dev) {
78
+ /* TODO Add BB name/QOM path */
79
+ error_setg(errp, "Cannot change iothread of active block backend");
80
+ return false;
81
+ }
82
+ }
83
+
84
+ s = g_new(BdrvStateBlkRootContext, 1);
85
+ *s = (BdrvStateBlkRootContext) {
86
+ .new_ctx = ctx,
87
+ .blk = blk,
88
+ };
89
+
90
+ tran_add(tran, &set_blk_root_context, s);
91
+ return true;
92
+}
93
+
94
static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
95
GSList **ignore, Error **errp)
96
{
97
--
98
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Replace all direct usage of ->can_set_aio_ctx and ->set_aio_ctx,
4
and call bdrv_child_try_change_aio_context() in
5
bdrv_try_set_aio_context(), the main function called through
6
the whole block layer.
7
8
From this point onwards, ->can_set_aio_ctx and ->set_aio_ctx
9
won't be used anymore.
10
11
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
12
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20221025084952.2139888-8-eesposit@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
---
16
block.c | 44 ++++++++++++++++++++++++-------------------
17
block/block-backend.c | 8 ++++++--
18
2 files changed, 31 insertions(+), 21 deletions(-)
19
20
diff --git a/block.c b/block.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/block.c
23
+++ b/block.c
24
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
25
}
26
27
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
28
- GSList *ignore;
29
+ Transaction *tran;
30
+ GHashTable *visited;
31
+ bool ret;
32
33
- /* No need to ignore `child`, because it has been detached already */
34
- ignore = NULL;
35
- s->child->klass->can_set_aio_ctx(s->child, s->old_parent_ctx, &ignore,
36
- &error_abort);
37
- g_slist_free(ignore);
38
+ tran = tran_new();
39
40
- ignore = NULL;
41
- s->child->klass->set_aio_ctx(s->child, s->old_parent_ctx, &ignore);
42
- g_slist_free(ignore);
43
+ /* No need to visit `child`, because it has been detached already */
44
+ visited = g_hash_table_new(NULL, NULL);
45
+ ret = s->child->klass->change_aio_ctx(s->child, s->old_parent_ctx,
46
+ visited, tran, &error_abort);
47
+ g_hash_table_destroy(visited);
48
+
49
+ /* transaction is supposed to always succeed */
50
+ assert(ret == true);
51
+ tran_commit(tran);
52
}
53
54
bdrv_unref(bs);
55
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
56
Error *local_err = NULL;
57
int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
58
59
- if (ret < 0 && child_class->can_set_aio_ctx) {
60
- GSList *ignore = g_slist_prepend(NULL, new_child);
61
- if (child_class->can_set_aio_ctx(new_child, child_ctx, &ignore,
62
- NULL))
63
- {
64
+ if (ret < 0 && child_class->change_aio_ctx) {
65
+ Transaction *tran = tran_new();
66
+ GHashTable *visited = g_hash_table_new(NULL, NULL);
67
+ bool ret_child;
68
+
69
+ g_hash_table_add(visited, new_child);
70
+ ret_child = child_class->change_aio_ctx(new_child, child_ctx,
71
+ visited, tran, NULL);
72
+ if (ret_child == true) {
73
error_free(local_err);
74
ret = 0;
75
- g_slist_free(ignore);
76
- ignore = g_slist_prepend(NULL, new_child);
77
- child_class->set_aio_ctx(new_child, child_ctx, &ignore);
78
}
79
- g_slist_free(ignore);
80
+ tran_finalize(tran, ret_child == true ? 0 : -1);
81
+ g_hash_table_destroy(visited);
82
}
83
84
if (ret < 0) {
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
86
Error **errp)
87
{
88
GLOBAL_STATE_CODE();
89
- return bdrv_child_try_set_aio_context(bs, ctx, NULL, errp);
90
+ return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
91
}
92
93
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
94
diff --git a/block/block-backend.c b/block/block-backend.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/block/block-backend.c
97
+++ b/block/block-backend.c
98
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
99
bdrv_ref(bs);
100
101
if (update_root_node) {
102
- ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root,
103
- errp);
104
+ /*
105
+ * update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
106
+ * as we are already in the commit function of a transaction.
107
+ */
108
+ ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
109
+ errp);
110
if (ret < 0) {
111
bdrv_unref(bs);
112
return ret;
113
--
114
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
Together with all _can_set_ and _set_ APIs, as they are not needed
4
anymore.
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Message-Id: <20221025084952.2139888-9-eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-global-state.h | 9 --
12
include/block/block_int-common.h | 4 -
13
block.c | 196 -----------------------------
14
block/block-backend.c | 33 -----
15
blockjob.c | 35 ------
16
5 files changed, 277 deletions(-)
17
18
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/include/block/block-global-state.h
21
+++ b/include/block/block-global-state.h
22
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
23
*/
24
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
25
26
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
27
- AioContext *new_context, GSList **ignore);
28
int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
29
Error **errp);
30
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
31
- BdrvChild *ignore_child, Error **errp);
32
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
33
- GSList **ignore, Error **errp);
34
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
35
- GSList **ignore, Error **errp);
36
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
37
-
38
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
39
GHashTable *visited, Transaction *tran,
40
Error **errp);
41
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/block/block_int-common.h
44
+++ b/include/block/block_int-common.h
45
@@ -XXX,XX +XXX,XX @@ struct BdrvChildClass {
46
int (*update_filename)(BdrvChild *child, BlockDriverState *new_base,
47
const char *filename, Error **errp);
48
49
- bool (*can_set_aio_ctx)(BdrvChild *child, AioContext *ctx,
50
- GSList **ignore, Error **errp);
51
- void (*set_aio_ctx)(BdrvChild *child, AioContext *ctx, GSList **ignore);
52
-
53
bool (*change_aio_ctx)(BdrvChild *child, AioContext *ctx,
54
GHashTable *visited, Transaction *tran,
55
Error **errp);
56
diff --git a/block.c b/block.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/block.c
59
+++ b/block.c
60
@@ -XXX,XX +XXX,XX @@ static bool bdrv_child_cb_change_aio_ctx(BdrvChild *child, AioContext *ctx,
61
return bdrv_change_aio_context(bs, ctx, visited, tran, errp);
62
}
63
64
-static bool bdrv_child_cb_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
65
- GSList **ignore, Error **errp)
66
-{
67
- BlockDriverState *bs = child->opaque;
68
- return bdrv_can_set_aio_context(bs, ctx, ignore, errp);
69
-}
70
-
71
-static void bdrv_child_cb_set_aio_ctx(BdrvChild *child, AioContext *ctx,
72
- GSList **ignore)
73
-{
74
- BlockDriverState *bs = child->opaque;
75
- return bdrv_set_aio_context_ignore(bs, ctx, ignore);
76
-}
77
-
78
/*
79
* Returns the options and flags that a temporary snapshot should get, based on
80
* the originally requested flags (the originally requested image will have
81
@@ -XXX,XX +XXX,XX @@ const BdrvChildClass child_of_bds = {
82
.attach = bdrv_child_cb_attach,
83
.detach = bdrv_child_cb_detach,
84
.inactivate = bdrv_child_cb_inactivate,
85
- .can_set_aio_ctx = bdrv_child_cb_can_set_aio_ctx,
86
- .set_aio_ctx = bdrv_child_cb_set_aio_ctx,
87
.change_aio_ctx = bdrv_child_cb_change_aio_ctx,
88
.update_filename = bdrv_child_cb_update_filename,
89
.get_parent_aio_context = child_of_bds_get_parent_aio_context,
90
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_aio_context(BlockDriverState *bs,
91
bs->walking_aio_notifiers = false;
92
}
93
94
-/*
95
- * Changes the AioContext used for fd handlers, timers, and BHs by this
96
- * BlockDriverState and all its children and parents.
97
- *
98
- * Must be called from the main AioContext.
99
- *
100
- * The caller must own the AioContext lock for the old AioContext of bs, but it
101
- * must not own the AioContext lock for new_context (unless new_context is the
102
- * same as the current context of bs).
103
- *
104
- * @ignore will accumulate all visited BdrvChild objects. The caller is
105
- * responsible for freeing the list afterwards.
106
- */
107
-void bdrv_set_aio_context_ignore(BlockDriverState *bs,
108
- AioContext *new_context, GSList **ignore)
109
-{
110
- AioContext *old_context = bdrv_get_aio_context(bs);
111
- GSList *children_to_process = NULL;
112
- GSList *parents_to_process = NULL;
113
- GSList *entry;
114
- BdrvChild *child, *parent;
115
-
116
- g_assert(qemu_get_current_aio_context() == qemu_get_aio_context());
117
- GLOBAL_STATE_CODE();
118
-
119
- if (old_context == new_context) {
120
- return;
121
- }
122
-
123
- bdrv_drained_begin(bs);
124
-
125
- QLIST_FOREACH(child, &bs->children, next) {
126
- if (g_slist_find(*ignore, child)) {
127
- continue;
128
- }
129
- *ignore = g_slist_prepend(*ignore, child);
130
- children_to_process = g_slist_prepend(children_to_process, child);
131
- }
132
-
133
- QLIST_FOREACH(parent, &bs->parents, next_parent) {
134
- if (g_slist_find(*ignore, parent)) {
135
- continue;
136
- }
137
- *ignore = g_slist_prepend(*ignore, parent);
138
- parents_to_process = g_slist_prepend(parents_to_process, parent);
139
- }
140
-
141
- for (entry = children_to_process;
142
- entry != NULL;
143
- entry = g_slist_next(entry)) {
144
- child = entry->data;
145
- bdrv_set_aio_context_ignore(child->bs, new_context, ignore);
146
- }
147
- g_slist_free(children_to_process);
148
-
149
- for (entry = parents_to_process;
150
- entry != NULL;
151
- entry = g_slist_next(entry)) {
152
- parent = entry->data;
153
- assert(parent->klass->set_aio_ctx);
154
- parent->klass->set_aio_ctx(parent, new_context, ignore);
155
- }
156
- g_slist_free(parents_to_process);
157
-
158
- bdrv_detach_aio_context(bs);
159
-
160
- /* Acquire the new context, if necessary */
161
- if (qemu_get_aio_context() != new_context) {
162
- aio_context_acquire(new_context);
163
- }
164
-
165
- bdrv_attach_aio_context(bs, new_context);
166
-
167
- /*
168
- * If this function was recursively called from
169
- * bdrv_set_aio_context_ignore(), there may be nodes in the
170
- * subtree that have not yet been moved to the new AioContext.
171
- * Release the old one so bdrv_drained_end() can poll them.
172
- */
173
- if (qemu_get_aio_context() != old_context) {
174
- aio_context_release(old_context);
175
- }
176
-
177
- bdrv_drained_end(bs);
178
-
179
- if (qemu_get_aio_context() != old_context) {
180
- aio_context_acquire(old_context);
181
- }
182
- if (qemu_get_aio_context() != new_context) {
183
- aio_context_release(new_context);
184
- }
185
-}
186
-
187
-static bool bdrv_parent_can_set_aio_context(BdrvChild *c, AioContext *ctx,
188
- GSList **ignore, Error **errp)
189
-{
190
- GLOBAL_STATE_CODE();
191
- if (g_slist_find(*ignore, c)) {
192
- return true;
193
- }
194
- *ignore = g_slist_prepend(*ignore, c);
195
-
196
- /*
197
- * A BdrvChildClass that doesn't handle AioContext changes cannot
198
- * tolerate any AioContext changes
199
- */
200
- if (!c->klass->can_set_aio_ctx) {
201
- char *user = bdrv_child_user_desc(c);
202
- error_setg(errp, "Changing iothreads is not supported by %s", user);
203
- g_free(user);
204
- return false;
205
- }
206
- if (!c->klass->can_set_aio_ctx(c, ctx, ignore, errp)) {
207
- assert(!errp || *errp);
208
- return false;
209
- }
210
- return true;
211
-}
212
-
213
typedef struct BdrvStateSetAioContext {
214
AioContext *new_ctx;
215
BlockDriverState *bs;
216
@@ -XXX,XX +XXX,XX @@ static bool bdrv_parent_change_aio_context(BdrvChild *c, AioContext *ctx,
217
return true;
218
}
219
220
-bool bdrv_child_can_set_aio_context(BdrvChild *c, AioContext *ctx,
221
- GSList **ignore, Error **errp)
222
-{
223
- GLOBAL_STATE_CODE();
224
- if (g_slist_find(*ignore, c)) {
225
- return true;
226
- }
227
- *ignore = g_slist_prepend(*ignore, c);
228
- return bdrv_can_set_aio_context(c->bs, ctx, ignore, errp);
229
-}
230
-
231
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
232
GHashTable *visited, Transaction *tran,
233
Error **errp)
234
@@ -XXX,XX +XXX,XX @@ bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
235
return bdrv_change_aio_context(c->bs, ctx, visited, tran, errp);
236
}
237
238
-/* @ignore will accumulate all visited BdrvChild object. The caller is
239
- * responsible for freeing the list afterwards. */
240
-bool bdrv_can_set_aio_context(BlockDriverState *bs, AioContext *ctx,
241
- GSList **ignore, Error **errp)
242
-{
243
- BdrvChild *c;
244
-
245
- if (bdrv_get_aio_context(bs) == ctx) {
246
- return true;
247
- }
248
-
249
- GLOBAL_STATE_CODE();
250
-
251
- QLIST_FOREACH(c, &bs->parents, next_parent) {
252
- if (!bdrv_parent_can_set_aio_context(c, ctx, ignore, errp)) {
253
- return false;
254
- }
255
- }
256
- QLIST_FOREACH(c, &bs->children, next) {
257
- if (!bdrv_child_can_set_aio_context(c, ctx, ignore, errp)) {
258
- return false;
259
- }
260
- }
261
-
262
- return true;
263
-}
264
-
265
static void bdrv_set_aio_context_clean(void *opaque)
266
{
267
BdrvStateSetAioContext *state = (BdrvStateSetAioContext *) opaque;
268
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
269
return true;
270
}
271
272
-int bdrv_child_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
273
- BdrvChild *ignore_child, Error **errp)
274
-{
275
- GSList *ignore;
276
- bool ret;
277
-
278
- GLOBAL_STATE_CODE();
279
-
280
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
281
- ret = bdrv_can_set_aio_context(bs, ctx, &ignore, errp);
282
- g_slist_free(ignore);
283
-
284
- if (!ret) {
285
- return -EPERM;
286
- }
287
-
288
- ignore = ignore_child ? g_slist_prepend(NULL, ignore_child) : NULL;
289
- bdrv_set_aio_context_ignore(bs, ctx, &ignore);
290
- g_slist_free(ignore);
291
-
292
- return 0;
293
-}
294
-
295
/*
296
* Change bs's and recursively all of its parents' and children's AioContext
297
* to the given new context, returning an error if that isn't possible.
298
diff --git a/block/block-backend.c b/block/block-backend.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/block/block-backend.c
301
+++ b/block/block-backend.c
302
@@ -XXX,XX +XXX,XX @@ static void blk_root_drained_end(BdrvChild *child, int *drained_end_counter);
303
static void blk_root_change_media(BdrvChild *child, bool load);
304
static void blk_root_resize(BdrvChild *child);
305
306
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
307
- GSList **ignore, Error **errp);
308
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
309
- GSList **ignore);
310
static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
311
GHashTable *visited, Transaction *tran,
312
Error **errp);
313
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_root = {
314
.attach = blk_root_attach,
315
.detach = blk_root_detach,
316
317
- .can_set_aio_ctx = blk_root_can_set_aio_ctx,
318
- .set_aio_ctx = blk_root_set_aio_ctx,
319
.change_aio_ctx = blk_root_change_aio_ctx,
320
321
.get_parent_aio_context = blk_root_get_parent_aio_context,
322
@@ -XXX,XX +XXX,XX @@ static bool blk_root_change_aio_ctx(BdrvChild *child, AioContext *ctx,
323
return true;
324
}
325
326
-static bool blk_root_can_set_aio_ctx(BdrvChild *child, AioContext *ctx,
327
- GSList **ignore, Error **errp)
328
-{
329
- BlockBackend *blk = child->opaque;
330
-
331
- if (blk->allow_aio_context_change) {
332
- return true;
333
- }
334
-
335
- /* Only manually created BlockBackends that are not attached to anything
336
- * can change their AioContext without updating their user. */
337
- if (!blk->name || blk->dev) {
338
- /* TODO Add BB name/QOM path */
339
- error_setg(errp, "Cannot change iothread of active block backend");
340
- return false;
341
- }
342
-
343
- return true;
344
-}
345
-
346
-static void blk_root_set_aio_ctx(BdrvChild *child, AioContext *ctx,
347
- GSList **ignore)
348
-{
349
- BlockBackend *blk = child->opaque;
350
- blk_do_set_aio_context(blk, ctx, false, &error_abort);
351
-}
352
-
353
void blk_add_aio_context_notifier(BlockBackend *blk,
354
void (*attached_aio_context)(AioContext *new_context, void *opaque),
355
void (*detach_aio_context)(void *opaque), void *opaque)
356
diff --git a/blockjob.c b/blockjob.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/blockjob.c
359
+++ b/blockjob.c
360
@@ -XXX,XX +XXX,XX @@ static bool child_job_change_aio_ctx(BdrvChild *c, AioContext *ctx,
361
return true;
362
}
363
364
-static bool child_job_can_set_aio_ctx(BdrvChild *c, AioContext *ctx,
365
- GSList **ignore, Error **errp)
366
-{
367
- BlockJob *job = c->opaque;
368
- GSList *l;
369
-
370
- for (l = job->nodes; l; l = l->next) {
371
- BdrvChild *sibling = l->data;
372
- if (!bdrv_child_can_set_aio_context(sibling, ctx, ignore, errp)) {
373
- return false;
374
- }
375
- }
376
- return true;
377
-}
378
-
379
-static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx,
380
- GSList **ignore)
381
-{
382
- BlockJob *job = c->opaque;
383
- GSList *l;
384
-
385
- for (l = job->nodes; l; l = l->next) {
386
- BdrvChild *sibling = l->data;
387
- if (g_slist_find(*ignore, sibling)) {
388
- continue;
389
- }
390
- *ignore = g_slist_prepend(*ignore, sibling);
391
- bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore);
392
- }
393
-
394
- job_set_aio_context(&job->job, ctx);
395
-}
396
-
397
static AioContext *child_job_get_parent_aio_context(BdrvChild *c)
398
{
399
BlockJob *job = c->opaque;
400
@@ -XXX,XX +XXX,XX @@ static const BdrvChildClass child_job = {
401
.drained_begin = child_job_drained_begin,
402
.drained_poll = child_job_drained_poll,
403
.drained_end = child_job_drained_end,
404
- .can_set_aio_ctx = child_job_can_set_aio_ctx,
405
- .set_aio_ctx = child_job_set_aio_ctx,
406
.change_aio_ctx = child_job_change_aio_ctx,
407
.stay_at_node = true,
408
.get_parent_aio_context = child_job_get_parent_aio_context,
409
--
410
2.37.3
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
No functional changes intended.
4
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Message-Id: <20221025084952.2139888-10-eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
include/block/block-global-state.h | 4 ++--
11
block.c | 6 +++---
12
block/block-backend.c | 3 +--
13
3 files changed, 6 insertions(+), 7 deletions(-)
14
15
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block-global-state.h
18
+++ b/include/block/block-global-state.h
19
@@ -XXX,XX +XXX,XX @@ AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
20
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
21
GHashTable *visited, Transaction *tran,
22
Error **errp);
23
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
24
- BdrvChild *ignore_child, Error **errp);
25
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
26
+ BdrvChild *ignore_child, Error **errp);
27
28
int bdrv_probe_blocksizes(BlockDriverState *bs, BlockSizes *bsz);
29
int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo);
30
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
33
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
35
* bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
36
* Therefore the new AioContext lock must not be taken by the caller.
37
*/
38
-int bdrv_child_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
39
- BdrvChild *ignore_child, Error **errp)
40
+int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
41
+ BdrvChild *ignore_child, Error **errp)
42
{
43
Transaction *tran;
44
GHashTable *visited;
45
@@ -XXX,XX +XXX,XX @@ int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
46
Error **errp)
47
{
48
GLOBAL_STATE_CODE();
49
- return bdrv_child_try_change_aio_context(bs, ctx, NULL, errp);
50
+ return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
51
}
52
53
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
54
diff --git a/block/block-backend.c b/block/block-backend.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/block-backend.c
57
+++ b/block/block-backend.c
58
@@ -XXX,XX +XXX,XX @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context,
59
* update_root_node MUST be false for blk_root_set_aio_ctx_commit(),
60
* as we are already in the commit function of a transaction.
61
*/
62
- ret = bdrv_child_try_change_aio_context(bs, new_context, blk->root,
63
- errp);
64
+ ret = bdrv_try_change_aio_context(bs, new_context, blk->root, errp);
65
if (ret < 0) {
66
bdrv_unref(bs);
67
return ret;
68
--
69
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
bdrv_try_set_aio_context() requires that the old context is held, and
3
No functional change intended.
4
the new context is not held. Fix all the occurrences where it's not
5
done this way.
6
4
7
Suggested-by: Max Reitz <mreitz@redhat.com>
5
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Sergio Lopez <slp@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Message-Id: <20221025084952.2139888-11-eesposit@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
9
---
11
blockdev.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-------
10
docs/devel/multiple-iothreads.txt | 4 ++--
12
1 file changed, 60 insertions(+), 8 deletions(-)
11
include/block/block-global-state.h | 2 --
12
block.c | 14 ++++----------
13
block/export/export.c | 2 +-
14
blockdev.c | 22 +++++++++++-----------
15
job.c | 2 +-
16
tests/unit/test-bdrv-drain.c | 6 +++---
17
tests/unit/test-block-iothread.c | 10 +++++-----
18
8 files changed, 27 insertions(+), 35 deletions(-)
13
19
20
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
21
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/devel/multiple-iothreads.txt
23
+++ b/docs/devel/multiple-iothreads.txt
24
@@ -XXX,XX +XXX,XX @@ The AioContext originates from the QEMU block layer, even though nowadays
25
AioContext is a generic event loop that can be used by any QEMU subsystem.
26
27
The block layer has support for AioContext integrated. Each BlockDriverState
28
-is associated with an AioContext using bdrv_try_set_aio_context() and
29
+is associated with an AioContext using bdrv_try_change_aio_context() and
30
bdrv_get_aio_context(). This allows block layer code to process I/O inside the
31
right AioContext. Other subsystems may wish to follow a similar approach.
32
33
@@ -XXX,XX +XXX,XX @@ Long-running jobs (usually in the form of coroutines) are best scheduled in
34
the BlockDriverState's AioContext to avoid the need to acquire/release around
35
each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
36
or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
37
-can be used to get a notification whenever bdrv_try_set_aio_context() moves a
38
+can be used to get a notification whenever bdrv_try_change_aio_context() moves a
39
BlockDriverState to a different AioContext.
40
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block-global-state.h
43
+++ b/include/block/block-global-state.h
44
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
45
*/
46
void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
47
48
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
49
- Error **errp);
50
AioContext *bdrv_child_get_parent_aio_context(BdrvChild *c);
51
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
52
GHashTable *visited, Transaction *tran,
53
diff --git a/block.c b/block.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block.c
56
+++ b/block.c
57
@@ -XXX,XX +XXX,XX @@ static void bdrv_attach_child_common_abort(void *opaque)
58
bdrv_replace_child_noperm(s->child, NULL);
59
60
if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
61
- bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
62
+ bdrv_try_change_aio_context(bs, s->old_child_ctx, NULL, &error_abort);
63
}
64
65
if (bdrv_child_get_parent_aio_context(s->child) != s->old_parent_ctx) {
66
@@ -XXX,XX +XXX,XX @@ static BdrvChild *bdrv_attach_child_common(BlockDriverState *child_bs,
67
parent_ctx = bdrv_child_get_parent_aio_context(new_child);
68
if (child_ctx != parent_ctx) {
69
Error *local_err = NULL;
70
- int ret = bdrv_try_set_aio_context(child_bs, parent_ctx, &local_err);
71
+ int ret = bdrv_try_change_aio_context(child_bs, parent_ctx, NULL,
72
+ &local_err);
73
74
if (ret < 0 && child_class->change_aio_ctx) {
75
Transaction *tran = tran_new();
76
@@ -XXX,XX +XXX,XX @@ static void bdrv_detach_child(BdrvChild *child)
77
* When the parent requiring a non-default AioContext is removed, the
78
* node moves back to the main AioContext
79
*/
80
- bdrv_try_set_aio_context(old_bs, qemu_get_aio_context(), NULL);
81
+ bdrv_try_change_aio_context(old_bs, qemu_get_aio_context(), NULL, NULL);
82
}
83
}
84
85
@@ -XXX,XX +XXX,XX @@ int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
86
return 0;
87
}
88
89
-int bdrv_try_set_aio_context(BlockDriverState *bs, AioContext *ctx,
90
- Error **errp)
91
-{
92
- GLOBAL_STATE_CODE();
93
- return bdrv_try_change_aio_context(bs, ctx, NULL, errp);
94
-}
95
-
96
void bdrv_add_aio_context_notifier(BlockDriverState *bs,
97
void (*attached_aio_context)(AioContext *new_context, void *opaque),
98
void (*detach_aio_context)(void *opaque), void *opaque)
99
diff --git a/block/export/export.c b/block/export/export.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/export/export.c
102
+++ b/block/export/export.c
103
@@ -XXX,XX +XXX,XX @@ BlockExport *blk_exp_add(BlockExportOptions *export, Error **errp)
104
105
/* Ignore errors with fixed-iothread=false */
106
set_context_errp = fixed_iothread ? errp : NULL;
107
- ret = bdrv_try_set_aio_context(bs, new_ctx, set_context_errp);
108
+ ret = bdrv_try_change_aio_context(bs, new_ctx, NULL, set_context_errp);
109
if (ret == 0) {
110
aio_context_release(ctx);
111
aio_context_acquire(new_ctx);
14
diff --git a/blockdev.c b/blockdev.c
112
diff --git a/blockdev.c b/blockdev.c
15
index XXXXXXX..XXXXXXX 100644
113
index XXXXXXX..XXXXXXX 100644
16
--- a/blockdev.c
114
--- a/blockdev.c
17
+++ b/blockdev.c
115
+++ b/blockdev.c
18
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
116
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_abort(BlkActionState *common)
19
DO_UPCAST(ExternalSnapshotState, common, common);
117
aio_context_release(aio_context);
20
TransactionAction *action = common->action;
118
aio_context_acquire(tmp_context);
21
AioContext *aio_context;
119
22
+ AioContext *old_context;
120
- ret = bdrv_try_set_aio_context(state->old_bs,
23
int ret;
121
- aio_context, NULL);
24
122
+ ret = bdrv_try_change_aio_context(state->old_bs,
25
/* 'blockdev-snapshot' and 'blockdev-snapshot-sync' have similar
123
+ aio_context, NULL, NULL);
26
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_prepare(BlkActionState *common,
124
assert(ret == 0);
27
goto out;
125
28
}
126
aio_context_release(tmp_context);
29
30
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
31
+ old_context = bdrv_get_aio_context(state->new_bs);
32
+ aio_context_release(aio_context);
33
+ aio_context_acquire(old_context);
34
+
35
ret = bdrv_try_set_aio_context(state->new_bs, aio_context, errp);
36
+
37
+ aio_context_release(old_context);
38
+ aio_context_acquire(aio_context);
39
+
40
if (ret < 0) {
41
goto out;
42
}
43
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
44
BlockDriverState *target_bs;
45
BlockDriverState *source = NULL;
46
AioContext *aio_context;
47
+ AioContext *old_context;
48
QDict *options;
49
Error *local_err = NULL;
50
int flags;
51
int64_t size;
52
bool set_backing_hd = false;
53
+ int ret;
54
55
assert(common->action->type == TRANSACTION_ACTION_KIND_DRIVE_BACKUP);
56
backup = common->action->u.drive_backup.data;
57
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
127
@@ -XXX,XX +XXX,XX @@ static void drive_backup_prepare(BlkActionState *common, Error **errp)
58
goto out;
128
goto out;
59
}
129
}
60
130
61
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
131
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
62
+ old_context = bdrv_get_aio_context(target_bs);
132
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
63
+ aio_context_release(aio_context);
133
old_context = bdrv_get_aio_context(target_bs);
64
+ aio_context_acquire(old_context);
134
aio_context_release(aio_context);
65
+
135
aio_context_acquire(old_context);
66
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
136
67
+ if (ret < 0) {
137
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
68
+ bdrv_unref(target_bs);
138
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
69
+ aio_context_release(old_context);
139
if (ret < 0) {
70
+ return;
140
bdrv_unref(target_bs);
71
+ }
141
aio_context_release(old_context);
72
+
73
+ aio_context_release(old_context);
74
+ aio_context_acquire(aio_context);
75
+
76
if (set_backing_hd) {
77
bdrv_set_backing_hd(target_bs, source, &local_err);
78
if (local_err) {
79
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
80
BlockDriverState *bs;
81
BlockDriverState *target_bs;
82
AioContext *aio_context;
83
+ AioContext *old_context;
84
+ int ret;
85
86
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
87
backup = common->action->u.blockdev_backup.data;
88
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
142
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
89
return;
143
return;
90
}
144
}
91
145
92
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
146
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
147
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
93
aio_context = bdrv_get_aio_context(bs);
148
aio_context = bdrv_get_aio_context(bs);
94
+ old_context = bdrv_get_aio_context(target_bs);
149
old_context = bdrv_get_aio_context(target_bs);
95
+ aio_context_acquire(old_context);
150
aio_context_acquire(old_context);
96
+
151
97
+ ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
152
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
98
+ if (ret < 0) {
153
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
99
+ aio_context_release(old_context);
154
if (ret < 0) {
100
+ return;
155
aio_context_release(old_context);
101
+ }
156
return;
102
+
103
+ aio_context_release(old_context);
104
aio_context_acquire(aio_context);
105
state->bs = bs;
106
107
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
108
BlockJob *job = NULL;
109
BdrvDirtyBitmap *bmap = NULL;
110
int job_flags = JOB_DEFAULT;
111
- int ret;
112
113
if (!backup->has_speed) {
114
backup->speed = 0;
115
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_backup_common(BackupCommon *backup,
116
backup->compress = false;
117
}
118
119
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
120
- if (ret < 0) {
121
- return NULL;
122
- }
123
-
124
if ((backup->sync == MIRROR_SYNC_MODE_BITMAP) ||
125
(backup->sync == MIRROR_SYNC_MODE_INCREMENTAL)) {
126
/* done before desugaring 'incremental' to print the right message */
127
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
157
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
128
BlockDriverState *bs;
129
BlockDriverState *source, *target_bs;
130
AioContext *aio_context;
131
+ AioContext *old_context;
132
BlockMirrorBackingMode backing_mode;
133
Error *local_err = NULL;
134
QDict *options = NULL;
135
@@ -XXX,XX +XXX,XX @@ void qmp_drive_mirror(DriveMirror *arg, Error **errp)
136
(arg->mode == NEW_IMAGE_MODE_EXISTING ||
137
!bdrv_has_zero_init(target_bs)));
158
!bdrv_has_zero_init(target_bs)));
138
159
139
+
160
140
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
161
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
141
+ old_context = bdrv_get_aio_context(target_bs);
162
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
142
+ aio_context_release(aio_context);
163
old_context = bdrv_get_aio_context(target_bs);
143
+ aio_context_acquire(old_context);
164
aio_context_release(aio_context);
144
+
165
aio_context_acquire(old_context);
145
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
166
167
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
168
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
146
if (ret < 0) {
169
if (ret < 0) {
147
bdrv_unref(target_bs);
170
bdrv_unref(target_bs);
148
- goto out;
171
aio_context_release(old_context);
149
+ aio_context_release(old_context);
150
+ return;
151
}
152
153
+ aio_context_release(old_context);
154
+ aio_context_acquire(aio_context);
155
+
156
blockdev_mirror_common(arg->has_job_id ? arg->job_id : NULL, bs, target_bs,
157
arg->has_replaces, arg->replaces, arg->sync,
158
backing_mode, zero_target,
159
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
172
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
160
BlockDriverState *bs;
161
BlockDriverState *target_bs;
162
AioContext *aio_context;
163
+ AioContext *old_context;
164
BlockMirrorBackingMode backing_mode = MIRROR_LEAVE_BACKING_CHAIN;
165
Error *local_err = NULL;
166
bool zero_target;
167
@@ -XXX,XX +XXX,XX @@ void qmp_blockdev_mirror(bool has_job_id, const char *job_id,
168
173
169
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
174
zero_target = (sync == MIRROR_SYNC_MODE_FULL);
170
175
171
+ /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
176
- /* Honor bdrv_try_set_aio_context() context acquisition requirements. */
172
+ old_context = bdrv_get_aio_context(target_bs);
177
+ /* Honor bdrv_try_change_aio_context() context acquisition requirements. */
178
old_context = bdrv_get_aio_context(target_bs);
173
aio_context = bdrv_get_aio_context(bs);
179
aio_context = bdrv_get_aio_context(bs);
174
- aio_context_acquire(aio_context);
180
aio_context_acquire(old_context);
175
+ aio_context_acquire(old_context);
181
176
182
- ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
177
ret = bdrv_try_set_aio_context(target_bs, aio_context, errp);
183
+ ret = bdrv_try_change_aio_context(target_bs, aio_context, NULL, errp);
178
+
184
179
+ aio_context_release(old_context);
185
aio_context_release(old_context);
180
+ aio_context_acquire(aio_context);
186
aio_context_acquire(aio_context);
181
+
187
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
182
if (ret < 0) {
188
old_context = bdrv_get_aio_context(bs);
183
goto out;
189
aio_context_acquire(old_context);
184
}
190
191
- bdrv_try_set_aio_context(bs, new_context, errp);
192
+ bdrv_try_change_aio_context(bs, new_context, NULL, errp);
193
194
aio_context_release(old_context);
195
}
196
diff --git a/job.c b/job.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/job.c
199
+++ b/job.c
200
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns)
201
next_aio_context = job->aio_context;
202
/*
203
* Coroutine has resumed, but in the meanwhile the job AioContext
204
- * might have changed via bdrv_try_set_aio_context(), so we need to move
205
+ * might have changed via bdrv_try_change_aio_context(), so we need to move
206
* the coroutine too in the new aiocontext.
207
*/
208
while (qemu_get_current_aio_context() != next_aio_context) {
209
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
210
index XXXXXXX..XXXXXXX 100644
211
--- a/tests/unit/test-bdrv-drain.c
212
+++ b/tests/unit/test-bdrv-drain.c
213
@@ -XXX,XX +XXX,XX @@ static void test_set_aio_context(void)
214
&error_abort);
215
216
bdrv_drained_begin(bs);
217
- bdrv_try_set_aio_context(bs, ctx_a, &error_abort);
218
+ bdrv_try_change_aio_context(bs, ctx_a, NULL, &error_abort);
219
220
aio_context_acquire(ctx_a);
221
bdrv_drained_end(bs);
222
223
bdrv_drained_begin(bs);
224
- bdrv_try_set_aio_context(bs, ctx_b, &error_abort);
225
+ bdrv_try_change_aio_context(bs, ctx_b, NULL, &error_abort);
226
aio_context_release(ctx_a);
227
aio_context_acquire(ctx_b);
228
- bdrv_try_set_aio_context(bs, qemu_get_aio_context(), &error_abort);
229
+ bdrv_try_change_aio_context(bs, qemu_get_aio_context(), NULL, &error_abort);
230
aio_context_release(ctx_b);
231
bdrv_drained_end(bs);
232
233
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/tests/unit/test-block-iothread.c
236
+++ b/tests/unit/test-block-iothread.c
237
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
238
filter = bdrv_find_node("filter_node");
239
240
/* Change the AioContext of src */
241
- bdrv_try_set_aio_context(src, ctx, &error_abort);
242
+ bdrv_try_change_aio_context(src, ctx, NULL, &error_abort);
243
g_assert(bdrv_get_aio_context(src) == ctx);
244
g_assert(bdrv_get_aio_context(target) == ctx);
245
g_assert(bdrv_get_aio_context(filter) == ctx);
246
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
247
248
/* Change the AioContext of target */
249
aio_context_acquire(ctx);
250
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
251
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
252
aio_context_release(ctx);
253
g_assert(bdrv_get_aio_context(src) == main_ctx);
254
g_assert(bdrv_get_aio_context(target) == main_ctx);
255
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
256
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
257
blk_insert_bs(blk, src, &error_abort);
258
259
- bdrv_try_set_aio_context(target, ctx, &local_err);
260
+ bdrv_try_change_aio_context(target, ctx, NULL, &local_err);
261
error_free_or_abort(&local_err);
262
263
g_assert(blk_get_aio_context(blk) == main_ctx);
264
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
265
/* ...unless we explicitly allow it */
266
aio_context_acquire(ctx);
267
blk_set_allow_aio_context_change(blk, true);
268
- bdrv_try_set_aio_context(target, ctx, &error_abort);
269
+ bdrv_try_change_aio_context(target, ctx, NULL, &error_abort);
270
aio_context_release(ctx);
271
272
g_assert(blk_get_aio_context(blk) == ctx);
273
@@ -XXX,XX +XXX,XX @@ static void test_propagate_mirror(void)
274
275
aio_context_acquire(ctx);
276
blk_set_aio_context(blk, main_ctx, &error_abort);
277
- bdrv_try_set_aio_context(target, main_ctx, &error_abort);
278
+ bdrv_try_change_aio_context(target, main_ctx, NULL, &error_abort);
279
aio_context_release(ctx);
280
281
blk_unref(blk);
185
--
282
--
186
2.20.1
283
2.37.3
187
188
diff view generated by jsdifflib
New patch
1
From: Bin Meng <bin.meng@windriver.com>
1
2
3
libnfs.h declares nfs_fstat() as the following for win32:
4
5
int nfs_fstat(struct nfs_context *nfs, struct nfsfh *nfsfh,
6
struct __stat64 *st);
7
8
The 'st' parameter should be of type 'struct __stat64'. The
9
codes happen to build successfully for 64-bit Windows, but it
10
does not build for 32-bit Windows.
11
12
Fixes: 6542aa9c75bc ("block: add native support for NFS")
13
Fixes: 18a8056e0bc7 ("block/nfs: cache allocated filesize for read-only files")
14
Signed-off-by: Bin Meng <bin.meng@windriver.com>
15
Message-Id: <20220908132817.1831008-6-bmeng.cn@gmail.com>
16
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
---
19
block/nfs.c | 8 ++++++++
20
1 file changed, 8 insertions(+)
21
22
diff --git a/block/nfs.c b/block/nfs.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/nfs.c
25
+++ b/block/nfs.c
26
@@ -XXX,XX +XXX,XX @@ static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
27
int flags, int open_flags, Error **errp)
28
{
29
int64_t ret = -EINVAL;
30
+#ifdef _WIN32
31
+ struct __stat64 st;
32
+#else
33
struct stat st;
34
+#endif
35
char *file = NULL, *strp = NULL;
36
37
qemu_mutex_init(&client->mutex);
38
@@ -XXX,XX +XXX,XX @@ static int nfs_reopen_prepare(BDRVReopenState *state,
39
BlockReopenQueue *queue, Error **errp)
40
{
41
NFSClient *client = state->bs->opaque;
42
+#ifdef _WIN32
43
+ struct __stat64 st;
44
+#else
45
struct stat st;
46
+#endif
47
int ret = 0;
48
49
if (state->flags & BDRV_O_RDWR && bdrv_is_read_only(state->bs)) {
50
--
51
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
All paths that lead to bdrv_backup_top_drop(), except for the call
3
The .set_speed callback is not called from coroutine.
4
from backup_clean(), imply that the BDS AioContext has already been
5
acquired, so doing it there too can potentially lead to QEMU hanging
6
on AIO_WAIT_WHILE().
7
4
8
An easy way to trigger this situation is by issuing a two actions
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
9
transaction, with a proper and a bogus blockdev-backup, so the second
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
one will trigger a rollback. This will trigger a hang with an stack
7
Message-Id: <20221013123711.620631-2-pbonzini@redhat.com>
11
trace like this one:
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
12
13
#0 0x00007fb680c75016 in __GI_ppoll (fds=0x55e74580f7c0, nfds=1, timeout=<optimized out>,
14
timeout@entry=0x0, sigmask=sigmask@entry=0x0) at ../sysdeps/unix/sysv/linux/ppoll.c:39
15
#1 0x000055e743386e09 in ppoll (__ss=0x0, __timeout=0x0, __nfds=<optimized out>, __fds=<optimized out>)
16
at /usr/include/bits/poll2.h:77
17
#2 0x000055e743386e09 in qemu_poll_ns
18
(fds=<optimized out>, nfds=<optimized out>, timeout=<optimized out>) at util/qemu-timer.c:336
19
#3 0x000055e743388dc4 in aio_poll (ctx=0x55e7458925d0, blocking=blocking@entry=true)
20
at util/aio-posix.c:669
21
#4 0x000055e743305dea in bdrv_flush (bs=bs@entry=0x55e74593c0d0) at block/io.c:2878
22
#5 0x000055e7432be58e in bdrv_close (bs=0x55e74593c0d0) at block.c:4017
23
#6 0x000055e7432be58e in bdrv_delete (bs=<optimized out>) at block.c:4262
24
#7 0x000055e7432be58e in bdrv_unref (bs=bs@entry=0x55e74593c0d0) at block.c:5644
25
#8 0x000055e743316b9b in bdrv_backup_top_drop (bs=bs@entry=0x55e74593c0d0) at block/backup-top.c:273
26
#9 0x000055e74331461f in backup_job_create
27
(job_id=0x0, bs=bs@entry=0x55e7458d5820, target=target@entry=0x55e74589f640, speed=0, sync_mode=MIRROR_SYNC_MODE_FULL, sync_bitmap=sync_bitmap@entry=0x0, bitmap_mode=BITMAP_SYNC_MODE_ON_SUCCESS, compress=false, filter_node_name=0x0, on_source_error=BLOCKDEV_ON_ERROR_REPORT, on_target_error=BLOCKDEV_ON_ERROR_REPORT, creation_flags=0, cb=0x0, opaque=0x0, txn=0x0, errp=0x7ffddfd1efb0) at block/backup.c:478
28
#10 0x000055e74315bc52 in do_backup_common
29
(backup=backup@entry=0x55e746c066d0, bs=bs@entry=0x55e7458d5820, target_bs=target_bs@entry=0x55e74589f640, aio_context=aio_context@entry=0x55e7458a91e0, txn=txn@entry=0x0, errp=errp@entry=0x7ffddfd1efb0)
30
at blockdev.c:3580
31
#11 0x000055e74315c37c in do_blockdev_backup
32
(backup=backup@entry=0x55e746c066d0, txn=0x0, errp=errp@entry=0x7ffddfd1efb0)
33
at /usr/src/debug/qemu-kvm-4.2.0-2.module+el8.2.0+5135+ed3b2489.x86_64/./qapi/qapi-types-block-core.h:1492
34
#12 0x000055e74315c449 in blockdev_backup_prepare (common=0x55e746a8de90, errp=0x7ffddfd1f018)
35
at blockdev.c:1885
36
#13 0x000055e743160152 in qmp_transaction
37
(dev_list=<optimized out>, has_props=<optimized out>, props=0x55e7467fe2c0, errp=errp@entry=0x7ffddfd1f088) at blockdev.c:2340
38
#14 0x000055e743287ff5 in qmp_marshal_transaction
39
(args=<optimized out>, ret=<optimized out>, errp=0x7ffddfd1f0f8)
40
at qapi/qapi-commands-transaction.c:44
41
#15 0x000055e74333de6c in do_qmp_dispatch
42
(errp=0x7ffddfd1f0f0, allow_oob=<optimized out>, request=<optimized out>, cmds=0x55e743c28d60 <qmp_commands>) at qapi/qmp-dispatch.c:132
43
#16 0x000055e74333de6c in qmp_dispatch
44
(cmds=0x55e743c28d60 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>)
45
at qapi/qmp-dispatch.c:175
46
#17 0x000055e74325c061 in monitor_qmp_dispatch (mon=0x55e745908030, req=<optimized out>)
47
at monitor/qmp.c:145
48
#18 0x000055e74325c6fa in monitor_qmp_bh_dispatcher (data=<optimized out>) at monitor/qmp.c:234
49
#19 0x000055e743385866 in aio_bh_call (bh=0x55e745807ae0) at util/async.c:117
50
#20 0x000055e743385866 in aio_bh_poll (ctx=ctx@entry=0x55e7458067a0) at util/async.c:117
51
#21 0x000055e743388c54 in aio_dispatch (ctx=0x55e7458067a0) at util/aio-posix.c:459
52
#22 0x000055e743385742 in aio_ctx_dispatch
53
(source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
54
#23 0x00007fb68543e67d in g_main_dispatch (context=0x55e745893a40) at gmain.c:3176
55
#24 0x00007fb68543e67d in g_main_context_dispatch (context=context@entry=0x55e745893a40) at gmain.c:3829
56
#25 0x000055e743387d08 in glib_pollfds_poll () at util/main-loop.c:219
57
#26 0x000055e743387d08 in os_host_main_loop_wait (timeout=<optimized out>) at util/main-loop.c:242
58
#27 0x000055e743387d08 in main_loop_wait (nonblocking=<optimized out>) at util/main-loop.c:518
59
#28 0x000055e74316a3c1 in main_loop () at vl.c:1828
60
#29 0x000055e743016a72 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)
61
at vl.c:4504
62
63
Fix this by not acquiring the AioContext there, and ensuring all paths
64
leading to it have it already acquired (backup_clean()).
65
66
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1782111
67
Signed-off-by: Sergio Lopez <slp@redhat.com>
68
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
69
---
10
---
70
block/backup-top.c | 5 -----
11
block/backup.c | 2 +-
71
block/backup.c | 3 +++
12
1 file changed, 1 insertion(+), 1 deletion(-)
72
2 files changed, 3 insertions(+), 5 deletions(-)
73
13
74
diff --git a/block/backup-top.c b/block/backup-top.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/block/backup-top.c
77
+++ b/block/backup-top.c
78
@@ -XXX,XX +XXX,XX @@ append_failed:
79
void bdrv_backup_top_drop(BlockDriverState *bs)
80
{
81
BDRVBackupTopState *s = bs->opaque;
82
- AioContext *aio_context = bdrv_get_aio_context(bs);
83
-
84
- aio_context_acquire(aio_context);
85
86
bdrv_drained_begin(bs);
87
88
@@ -XXX,XX +XXX,XX @@ void bdrv_backup_top_drop(BlockDriverState *bs)
89
bdrv_drained_end(bs);
90
91
bdrv_unref(bs);
92
-
93
- aio_context_release(aio_context);
94
}
95
diff --git a/block/backup.c b/block/backup.c
14
diff --git a/block/backup.c b/block/backup.c
96
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
97
--- a/block/backup.c
16
--- a/block/backup.c
98
+++ b/block/backup.c
17
+++ b/block/backup.c
99
@@ -XXX,XX +XXX,XX @@ static void backup_abort(Job *job)
18
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn backup_pause(Job *job)
100
static void backup_clean(Job *job)
19
}
20
}
21
22
-static void coroutine_fn backup_set_speed(BlockJob *job, int64_t speed)
23
+static void backup_set_speed(BlockJob *job, int64_t speed)
101
{
24
{
102
BackupBlockJob *s = container_of(job, BackupBlockJob, common.job);
25
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
103
+ AioContext *aio_context = bdrv_get_aio_context(s->backup_top);
26
104
105
+ aio_context_acquire(aio_context);
106
bdrv_backup_top_drop(s->backup_top);
107
+ aio_context_release(aio_context);
108
}
109
110
void backup_do_checkpoint(BlockJob *job, Error **errp)
111
--
27
--
112
2.20.1
28
2.37.3
113
114
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-3-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/io.c | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/block/io.c b/block/io.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/io.c
15
+++ b/block/io.c
16
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
17
return (pnum == bytes) && (ret & BDRV_BLOCK_ZERO);
18
}
19
20
-int coroutine_fn bdrv_is_allocated(BlockDriverState *bs, int64_t offset,
21
- int64_t bytes, int64_t *pnum)
22
+int bdrv_is_allocated(BlockDriverState *bs, int64_t offset, int64_t bytes,
23
+ int64_t *pnum)
24
{
25
int ret;
26
int64_t dummy;
27
--
28
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
hmp_block_resize and hmp_screendump are defined as a ".coroutine = true" command,
4
so they must be coroutine_fn.
5
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-Id: <20221013123711.620631-4-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
include/block/block-hmp-cmds.h | 2 +-
13
include/monitor/hmp.h | 3 ++-
14
block/monitor/block-hmp-cmds.c | 2 +-
15
3 files changed, 4 insertions(+), 3 deletions(-)
16
17
diff --git a/include/block/block-hmp-cmds.h b/include/block/block-hmp-cmds.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block-hmp-cmds.h
20
+++ b/include/block/block-hmp-cmds.h
21
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
22
void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict);
23
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
24
25
-void hmp_block_resize(Monitor *mon, const QDict *qdict);
26
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict);
27
void hmp_block_stream(Monitor *mon, const QDict *qdict);
28
void hmp_block_passwd(Monitor *mon, const QDict *qdict);
29
void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
30
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/monitor/hmp.h
33
+++ b/include/monitor/hmp.h
34
@@ -XXX,XX +XXX,XX @@
35
#define HMP_H
36
37
#include "qemu/readline.h"
38
+#include "qemu/coroutine.h"
39
#include "qapi/qapi-types-common.h"
40
41
bool hmp_handle_error(Monitor *mon, Error *err);
42
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict);
43
void hmp_getfd(Monitor *mon, const QDict *qdict);
44
void hmp_closefd(Monitor *mon, const QDict *qdict);
45
void hmp_sendkey(Monitor *mon, const QDict *qdict);
46
-void hmp_screendump(Monitor *mon, const QDict *qdict);
47
+void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
48
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
49
void hmp_chardev_change(Monitor *mon, const QDict *qdict);
50
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
51
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/monitor/block-hmp-cmds.c
54
+++ b/block/monitor/block-hmp-cmds.c
55
@@ -XXX,XX +XXX,XX @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict)
56
hmp_handle_error(mon, err);
57
}
58
59
-void hmp_block_resize(Monitor *mon, const QDict *qdict)
60
+void coroutine_fn hmp_block_resize(Monitor *mon, const QDict *qdict)
61
{
62
const char *device = qdict_get_str(qdict, "device");
63
int64_t size = qdict_get_int(qdict, "size");
64
--
65
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
ssh_write is only called from ssh_co_writev.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-5-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/ssh.c | 6 +++---
12
1 file changed, 3 insertions(+), 3 deletions(-)
13
14
diff --git a/block/ssh.c b/block/ssh.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/ssh.c
17
+++ b/block/ssh.c
18
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int ssh_co_readv(BlockDriverState *bs,
19
return ret;
20
}
21
22
-static int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
23
- int64_t offset, size_t size,
24
- QEMUIOVector *qiov)
25
+static coroutine_fn int ssh_write(BDRVSSHState *s, BlockDriverState *bs,
26
+ int64_t offset, size_t size,
27
+ QEMUIOVector *qiov)
28
{
29
ssize_t r;
30
size_t written;
31
--
32
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
The functions are marked coroutine_fn in the definition.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-6-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/block/block-io.h | 5 +++--
12
1 file changed, 3 insertions(+), 2 deletions(-)
13
14
diff --git a/include/block/block-io.h b/include/block/block-io.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/block/block-io.h
17
+++ b/include/block/block-io.h
18
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb);
19
void bdrv_aio_cancel_async(BlockAIOCB *acb);
20
21
/* sg packet commands */
22
-int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
23
+int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf);
24
25
/* Ensure contents are flushed to disk. */
26
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
27
28
-int bdrv_co_pdiscard(BdrvChild *child, int64_t offset, int64_t bytes);
29
+int coroutine_fn bdrv_co_pdiscard(BdrvChild *child, int64_t offset,
30
+ int64_t bytes);
31
bool bdrv_can_write_zeroes_with_unmap(BlockDriverState *bs);
32
int bdrv_block_status(BlockDriverState *bs, int64_t offset,
33
int64_t bytes, int64_t *pnum, int64_t *map,
34
--
35
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
The functions are marked coroutine_fn in the definition.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20221013123711.620631-7-pbonzini@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
include/qemu/coroutine.h | 10 +++++-----
12
1 file changed, 5 insertions(+), 5 deletions(-)
13
14
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/qemu/coroutine.h
17
+++ b/include/qemu/coroutine.h
18
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock);
19
* of a parallel writer, control is transferred to the caller of the current
20
* coroutine.
21
*/
22
-void qemu_co_rwlock_rdlock(CoRwlock *lock);
23
+void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock);
24
25
/**
26
* Write Locks the CoRwlock from a reader. This is a bit more efficient than
27
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock);
28
* to the caller of the current coroutine; another writer might run while
29
* @qemu_co_rwlock_upgrade blocks.
30
*/
31
-void qemu_co_rwlock_upgrade(CoRwlock *lock);
32
+void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock);
33
34
/**
35
* Downgrades a write-side critical section to a reader. Downgrading with
36
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_upgrade(CoRwlock *lock);
37
* followed by @qemu_co_rwlock_rdlock. This makes it more efficient, but
38
* may also sometimes be necessary for correctness.
39
*/
40
-void qemu_co_rwlock_downgrade(CoRwlock *lock);
41
+void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock);
42
43
/**
44
* Write Locks the mutex. If the lock cannot be taken immediately because
45
* of a parallel reader, control is transferred to the caller of the current
46
* coroutine.
47
*/
48
-void qemu_co_rwlock_wrlock(CoRwlock *lock);
49
+void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock);
50
51
/**
52
* Unlocks the read/write lock and schedules the next coroutine that was
53
* waiting for this lock to be run.
54
*/
55
-void qemu_co_rwlock_unlock(CoRwlock *lock);
56
+void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock);
57
58
typedef struct QemuCoSleep {
59
Coroutine *to_wake;
60
--
61
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-8-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
include/qemu/coroutine.h | 8 +++++---
10
1 file changed, 5 insertions(+), 3 deletions(-)
11
12
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/qemu/coroutine.h
15
+++ b/include/qemu/coroutine.h
16
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_dec_pool_size(unsigned int additional_pool_size);
17
* The same interface as qemu_sendv_recvv(), with added yielding.
18
* XXX should mark these as coroutine_fn
19
*/
20
-ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
21
- size_t offset, size_t bytes, bool do_send);
22
+ssize_t coroutine_fn qemu_co_sendv_recvv(int sockfd, struct iovec *iov,
23
+ unsigned iov_cnt, size_t offset,
24
+ size_t bytes, bool do_send);
25
#define qemu_co_recvv(sockfd, iov, iov_cnt, offset, bytes) \
26
qemu_co_sendv_recvv(sockfd, iov, iov_cnt, offset, bytes, false)
27
#define qemu_co_sendv(sockfd, iov, iov_cnt, offset, bytes) \
28
@@ -XXX,XX +XXX,XX @@ ssize_t qemu_co_sendv_recvv(int sockfd, struct iovec *iov, unsigned iov_cnt,
29
/**
30
* The same as above, but with just a single buffer
31
*/
32
-ssize_t qemu_co_send_recv(int sockfd, void *buf, size_t bytes, bool do_send);
33
+ssize_t coroutine_fn qemu_co_send_recv(int sockfd, void *buf, size_t bytes,
34
+ bool do_send);
35
#define qemu_co_recv(sockfd, buf, bytes) \
36
qemu_co_send_recv(sockfd, buf, bytes, false)
37
#define qemu_co_send(sockfd, buf, bytes) \
38
--
39
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-9-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2.h | 14 +++++++-------
10
include/block/block_int-common.h | 12 +++++-------
11
2 files changed, 12 insertions(+), 14 deletions(-)
12
13
diff --git a/block/qcow2.h b/block/qcow2.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2.h
16
+++ b/block/qcow2.h
17
@@ -XXX,XX +XXX,XX @@ int qcow2_truncate_bitmaps_check(BlockDriverState *bs, Error **errp);
18
bool qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs,
19
bool release_stored, Error **errp);
20
int qcow2_reopen_bitmaps_ro(BlockDriverState *bs, Error **errp);
21
-bool qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
22
- const char *name,
23
- uint32_t granularity,
24
- Error **errp);
25
-int qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
26
- const char *name,
27
- Error **errp);
28
+bool coroutine_fn qcow2_co_can_store_new_dirty_bitmap(BlockDriverState *bs,
29
+ const char *name,
30
+ uint32_t granularity,
31
+ Error **errp);
32
+int coroutine_fn qcow2_co_remove_persistent_dirty_bitmap(BlockDriverState *bs,
33
+ const char *name,
34
+ Error **errp);
35
bool qcow2_supports_persistent_dirty_bitmap(BlockDriverState *bs);
36
uint64_t qcow2_get_persistent_dirty_bitmap_size(BlockDriverState *bs,
37
uint32_t cluster_size);
38
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/include/block/block_int-common.h
41
+++ b/include/block/block_int-common.h
42
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
43
void coroutine_fn (*bdrv_co_drain_end)(BlockDriverState *bs);
44
45
bool (*bdrv_supports_persistent_dirty_bitmap)(BlockDriverState *bs);
46
- bool (*bdrv_co_can_store_new_dirty_bitmap)(BlockDriverState *bs,
47
- const char *name,
48
- uint32_t granularity,
49
- Error **errp);
50
- int (*bdrv_co_remove_persistent_dirty_bitmap)(BlockDriverState *bs,
51
- const char *name,
52
- Error **errp);
53
+ bool coroutine_fn (*bdrv_co_can_store_new_dirty_bitmap)(
54
+ BlockDriverState *bs, const char *name, uint32_t granularity,
55
+ Error **errp);
56
+ int coroutine_fn (*bdrv_co_remove_persistent_dirty_bitmap)(
57
+ BlockDriverState *bs, const char *name, Error **errp);
58
};
59
60
static inline bool block_driver_can_compress(BlockDriver *drv)
61
--
62
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-10-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2.c | 8 ++++----
10
1 file changed, 4 insertions(+), 4 deletions(-)
11
12
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ static int64_t qcow2_check_vmstate_request(BlockDriverState *bs,
17
return pos;
18
}
19
20
-static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
21
- int64_t pos)
22
+static coroutine_fn int qcow2_save_vmstate(BlockDriverState *bs,
23
+ QEMUIOVector *qiov, int64_t pos)
24
{
25
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
26
if (offset < 0) {
27
@@ -XXX,XX +XXX,XX @@ static int qcow2_save_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
28
return bs->drv->bdrv_co_pwritev_part(bs, offset, qiov->size, qiov, 0, 0);
29
}
30
31
-static int qcow2_load_vmstate(BlockDriverState *bs, QEMUIOVector *qiov,
32
- int64_t pos)
33
+static coroutine_fn int qcow2_load_vmstate(BlockDriverState *bs,
34
+ QEMUIOVector *qiov, int64_t pos)
35
{
36
int64_t offset = qcow2_check_vmstate_request(bs, qiov, pos);
37
if (offset < 0) {
38
--
39
2.37.3
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
4
Message-Id: <20221013123711.620631-11-pbonzini@redhat.com>
5
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
---
8
block/blkdebug.c | 2 +-
9
1 file changed, 1 insertion(+), 1 deletion(-)
10
11
diff --git a/block/blkdebug.c b/block/blkdebug.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/block/blkdebug.c
14
+++ b/block/blkdebug.c
15
@@ -XXX,XX +XXX,XX @@ blkdebug_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
16
return bdrv_co_pwritev(bs->file, offset, bytes, qiov, flags);
17
}
18
19
-static int blkdebug_co_flush(BlockDriverState *bs)
20
+static int coroutine_fn blkdebug_co_flush(BlockDriverState *bs)
21
{
22
int err = rule_check(bs, 0, 0, BLKDEBUG_IO_TYPE_FLUSH);
23
24
--
25
2.37.3
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
get_cluster_offset() and decompress_cluster() are only called from
4
the read and write paths.
5
6
The validity of these was double-checked with Alberto Faria's static analyzer.
7
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-Id: <20221013123711.620631-12-pbonzini@redhat.com>
10
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/qcow.c | 15 +++++++++------
14
1 file changed, 9 insertions(+), 6 deletions(-)
15
16
diff --git a/block/qcow.c b/block/qcow.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow.c
19
+++ b/block/qcow.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcowState {
21
22
static QemuOptsList qcow_create_opts;
23
24
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
25
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
26
+ uint64_t cluster_offset);
27
28
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
29
{
30
@@ -XXX,XX +XXX,XX @@ static int qcow_reopen_prepare(BDRVReopenState *state,
31
* return 0 if not allocated, 1 if *result is assigned, and negative
32
* errno on failure.
33
*/
34
-static int get_cluster_offset(BlockDriverState *bs,
35
- uint64_t offset, int allocate,
36
- int compressed_size,
37
- int n_start, int n_end, uint64_t *result)
38
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
39
+ uint64_t offset, int allocate,
40
+ int compressed_size,
41
+ int n_start, int n_end,
42
+ uint64_t *result)
43
{
44
BDRVQcowState *s = bs->opaque;
45
int min_index, i, j, l1_index, l2_index, ret;
46
@@ -XXX,XX +XXX,XX @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
47
return 0;
48
}
49
50
-static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
51
+static int coroutine_fn decompress_cluster(BlockDriverState *bs,
52
+ uint64_t cluster_offset)
53
{
54
BDRVQcowState *s = bs->opaque;
55
int ret, csize;
56
--
57
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Issuing a blockdev-backup from qmp_blockdev_backup takes a slightly
3
The validity of these was double-checked with Alberto Faria's static
4
different path than when it's issued from a transaction. In the code,
4
analyzer.
5
this is manifested as some redundancy between do_blockdev_backup() and
6
blockdev_backup_prepare().
7
5
8
This change unifies both paths, merging do_blockdev_backup() and
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
blockdev_backup_prepare(), and changing qmp_blockdev_backup() to
7
Message-Id: <20221013123711.620631-13-pbonzini@redhat.com>
10
create a transaction instead of calling do_backup_common() direcly.
11
12
As a side-effect, now qmp_blockdev_backup() is executed inside a
13
drained section, as it happens when creating a blockdev-backup
14
transaction. This change is visible from the user's perspective, as
15
the job gets paused and immediately resumed before starting the actual
16
work.
17
18
Signed-off-by: Sergio Lopez <slp@redhat.com>
19
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
10
---
23
blockdev.c | 60 ++++++++++++------------------------------------------
11
block/qcow2.h | 18 +++++++++---------
24
1 file changed, 13 insertions(+), 47 deletions(-)
12
block/qcow2-bitmap.c | 4 ++--
13
block/qcow2-cluster.c | 21 ++++++++++++---------
14
block/qcow2-refcount.c | 8 ++++----
15
4 files changed, 27 insertions(+), 24 deletions(-)
25
16
26
diff --git a/blockdev.c b/blockdev.c
17
diff --git a/block/qcow2.h b/block/qcow2.h
27
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
28
--- a/blockdev.c
19
--- a/block/qcow2.h
29
+++ b/blockdev.c
20
+++ b/block/qcow2.h
30
@@ -XXX,XX +XXX,XX @@ typedef struct BlockdevBackupState {
21
@@ -XXX,XX +XXX,XX @@ int qcow2_validate_table(BlockDriverState *bs, uint64_t offset,
31
BlockJob *job;
22
Error **errp);
32
} BlockdevBackupState;
23
33
24
/* qcow2-refcount.c functions */
34
-static BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
25
-int qcow2_refcount_init(BlockDriverState *bs);
35
- Error **errp);
26
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs);
36
-
27
void qcow2_refcount_close(BlockDriverState *bs);
37
static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
28
29
int qcow2_get_refcount(BlockDriverState *bs, int64_t cluster_index,
30
@@ -XXX,XX +XXX,XX @@ int qcow2_inc_refcounts_imrt(BlockDriverState *bs, BdrvCheckResult *res,
31
int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
32
BlockDriverAmendStatusCB *status_cb,
33
void *cb_opaque, Error **errp);
34
-int qcow2_shrink_reftable(BlockDriverState *bs);
35
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs);
36
int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
37
int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
38
39
/* qcow2-cluster.c functions */
40
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
41
bool exact_size);
42
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
43
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
44
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
45
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
46
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
47
@@ -XXX,XX +XXX,XX @@ int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset,
48
int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset,
49
unsigned int *bytes,
50
uint64_t *host_offset, QCowL2Meta **m);
51
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
52
- uint64_t offset,
53
- int compressed_size,
54
- uint64_t *host_offset);
55
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
56
+ uint64_t offset,
57
+ int compressed_size,
58
+ uint64_t *host_offset);
59
void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry,
60
uint64_t *coffset, int *csize);
61
62
@@ -XXX,XX +XXX,XX @@ void qcow2_cache_discard(Qcow2Cache *c, void *table);
63
int qcow2_check_bitmaps_refcounts(BlockDriverState *bs, BdrvCheckResult *res,
64
void **refcount_table,
65
int64_t *refcount_table_size);
66
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
67
- Error **errp);
68
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
69
+ bool *header_updated, Error **errp);
70
bool qcow2_get_bitmap_info_list(BlockDriverState *bs,
71
Qcow2BitmapInfoList **info_list, Error **errp);
72
int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp);
73
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/qcow2-bitmap.c
76
+++ b/block/qcow2-bitmap.c
77
@@ -XXX,XX +XXX,XX @@ static void set_readonly_helper(gpointer bitmap, gpointer value)
78
* If header_updated is not NULL then it is set appropriately regardless of
79
* the return value.
80
*/
81
-bool qcow2_load_dirty_bitmaps(BlockDriverState *bs, bool *header_updated,
82
- Error **errp)
83
+bool coroutine_fn qcow2_load_dirty_bitmaps(BlockDriverState *bs,
84
+ bool *header_updated, Error **errp)
38
{
85
{
39
BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common);
86
BDRVQcow2State *s = bs->opaque;
40
BlockdevBackup *backup;
87
Qcow2BitmapList *bm_list;
41
- BlockDriverState *bs, *target;
88
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
42
+ BlockDriverState *bs;
89
index XXXXXXX..XXXXXXX 100644
43
+ BlockDriverState *target_bs;
90
--- a/block/qcow2-cluster.c
44
AioContext *aio_context;
91
+++ b/block/qcow2-cluster.c
45
- Error *local_err = NULL;
92
@@ -XXX,XX +XXX,XX @@
46
93
#include "qemu/memalign.h"
47
assert(common->action->type == TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP);
94
#include "trace.h"
48
backup = common->action->u.blockdev_backup.data;
95
49
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
96
-int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
50
return;
97
+int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
51
}
98
+ uint64_t exact_size)
52
99
{
53
- target = bdrv_lookup_bs(backup->target, backup->target, errp);
100
BDRVQcow2State *s = bs->opaque;
54
- if (!target) {
101
int new_l1_size, i, ret;
55
+ target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
102
@@ -XXX,XX +XXX,XX @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
56
+ if (!target_bs) {
103
*
57
return;
104
* Return 0 on success and -errno in error cases
58
}
105
*/
59
106
-int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
60
@@ -XXX,XX +XXX,XX @@ static void blockdev_backup_prepare(BlkActionState *common, Error **errp)
107
- uint64_t offset,
61
/* Paired with .clean() */
108
- int compressed_size,
62
bdrv_drained_begin(state->bs);
109
- uint64_t *host_offset)
63
110
+int coroutine_fn qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
64
- state->job = do_blockdev_backup(backup, common->block_job_txn, &local_err);
111
+ uint64_t offset,
65
- if (local_err) {
112
+ int compressed_size,
66
- error_propagate(errp, local_err);
113
+ uint64_t *host_offset)
67
- goto out;
114
{
68
- }
115
BDRVQcow2State *s = bs->opaque;
69
+ state->job = do_backup_common(qapi_BlockdevBackup_base(backup),
116
int l2_index, ret;
70
+ bs, target_bs, aio_context,
117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn handle_dependencies(BlockDriverState *bs,
71
+ common->block_job_txn, errp);
118
*
72
119
* -errno: in error cases
73
-out:
120
*/
74
aio_context_release(aio_context);
121
-static int handle_copied(BlockDriverState *bs, uint64_t guest_offset,
122
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
123
+static int coroutine_fn handle_copied(BlockDriverState *bs,
124
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
125
+ QCowL2Meta **m)
126
{
127
BDRVQcow2State *s = bs->opaque;
128
int l2_index;
129
@@ -XXX,XX +XXX,XX @@ static int do_alloc_cluster_offset(BlockDriverState *bs, uint64_t guest_offset,
130
*
131
* -errno: in error cases
132
*/
133
-static int handle_alloc(BlockDriverState *bs, uint64_t guest_offset,
134
- uint64_t *host_offset, uint64_t *bytes, QCowL2Meta **m)
135
+static int coroutine_fn handle_alloc(BlockDriverState *bs,
136
+ uint64_t guest_offset, uint64_t *host_offset, uint64_t *bytes,
137
+ QCowL2Meta **m)
138
{
139
BDRVQcow2State *s = bs->opaque;
140
int l2_index;
141
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/block/qcow2-refcount.c
144
+++ b/block/qcow2-refcount.c
145
@@ -XXX,XX +XXX,XX @@ static void update_max_refcount_table_index(BDRVQcow2State *s)
146
s->max_refcount_table_index = i;
75
}
147
}
76
148
77
@@ -XXX,XX +XXX,XX @@ XDbgBlockGraph *qmp_x_debug_query_block_graph(Error **errp)
149
-int qcow2_refcount_init(BlockDriverState *bs)
78
return bdrv_get_xdbg_block_graph(errp);
150
+int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
151
{
152
BDRVQcow2State *s = bs->opaque;
153
unsigned int refcount_table_size2, i;
154
@@ -XXX,XX +XXX,XX @@ static int64_t get_refblock_offset(BlockDriverState *bs, uint64_t offset)
155
return covering_refblock_offset;
79
}
156
}
80
157
81
-BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
158
-static int qcow2_discard_refcount_block(BlockDriverState *bs,
82
- Error **errp)
159
- uint64_t discard_block_offs)
83
+void qmp_blockdev_backup(BlockdevBackup *backup, Error **errp)
160
+static int coroutine_fn
161
+qcow2_discard_refcount_block(BlockDriverState *bs, uint64_t discard_block_offs)
84
{
162
{
85
- BlockDriverState *bs;
163
BDRVQcow2State *s = bs->opaque;
86
- BlockDriverState *target_bs;
164
int64_t refblock_offs;
87
- AioContext *aio_context;
165
@@ -XXX,XX +XXX,XX @@ static int qcow2_discard_refcount_block(BlockDriverState *bs,
88
- BlockJob *job;
166
return 0;
89
-
90
- bs = bdrv_lookup_bs(backup->device, backup->device, errp);
91
- if (!bs) {
92
- return NULL;
93
- }
94
-
95
- target_bs = bdrv_lookup_bs(backup->target, backup->target, errp);
96
- if (!target_bs) {
97
- return NULL;
98
- }
99
-
100
- aio_context = bdrv_get_aio_context(bs);
101
- aio_context_acquire(aio_context);
102
-
103
- job = do_backup_common(qapi_BlockdevBackup_base(backup),
104
- bs, target_bs, aio_context, txn, errp);
105
-
106
- aio_context_release(aio_context);
107
- return job;
108
-}
109
-
110
-void qmp_blockdev_backup(BlockdevBackup *arg, Error **errp)
111
-{
112
- BlockJob *job;
113
- job = do_blockdev_backup(arg, NULL, errp);
114
- if (job) {
115
- job_start(&job->job);
116
- }
117
+ TransactionAction action = {
118
+ .type = TRANSACTION_ACTION_KIND_BLOCKDEV_BACKUP,
119
+ .u.blockdev_backup.data = backup,
120
+ };
121
+ blockdev_do_action(&action, errp);
122
}
167
}
123
168
124
/* Parameter check and block job starting for drive mirroring.
169
-int qcow2_shrink_reftable(BlockDriverState *bs)
170
+int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
171
{
172
BDRVQcow2State *s = bs->opaque;
173
uint64_t *reftable_tmp =
125
--
174
--
126
2.20.1
175
2.37.3
127
128
diff view generated by jsdifflib
New patch
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
2
3
The validity of these was double-checked with Alberto Faria's static analyzer.
4
5
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Message-Id: <20221013123711.620631-14-pbonzini@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/vmdk.c | 34 +++++++++++++++++-----------------
11
1 file changed, 17 insertions(+), 17 deletions(-)
12
13
diff --git a/block/vmdk.c b/block/vmdk.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/vmdk.c
16
+++ b/block/vmdk.c
17
@@ -XXX,XX +XXX,XX @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
18
* [@skip_start_sector, @skip_end_sector) is not copied or written, and leave
19
* it for call to write user data in the request.
20
*/
21
-static int get_whole_cluster(BlockDriverState *bs,
22
- VmdkExtent *extent,
23
- uint64_t cluster_offset,
24
- uint64_t offset,
25
- uint64_t skip_start_bytes,
26
- uint64_t skip_end_bytes,
27
- bool zeroed)
28
+static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
29
+ VmdkExtent *extent,
30
+ uint64_t cluster_offset,
31
+ uint64_t offset,
32
+ uint64_t skip_start_bytes,
33
+ uint64_t skip_end_bytes,
34
+ bool zeroed)
35
{
36
int ret = VMDK_OK;
37
int64_t cluster_bytes;
38
@@ -XXX,XX +XXX,XX @@ exit:
39
return ret;
40
}
41
42
-static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
43
- uint32_t offset)
44
+static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
45
+ uint32_t offset)
46
{
47
offset = cpu_to_le32(offset);
48
/* update L2 table */
49
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
50
* VMDK_UNALLOC if cluster is not mapped and @allocate is false.
51
* VMDK_ERROR if failed.
52
*/
53
-static int get_cluster_offset(BlockDriverState *bs,
54
- VmdkExtent *extent,
55
- VmdkMetaData *m_data,
56
- uint64_t offset,
57
- bool allocate,
58
- uint64_t *cluster_offset,
59
- uint64_t skip_start_bytes,
60
- uint64_t skip_end_bytes)
61
+static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
62
+ VmdkExtent *extent,
63
+ VmdkMetaData *m_data,
64
+ uint64_t offset,
65
+ bool allocate,
66
+ uint64_t *cluster_offset,
67
+ uint64_t skip_start_bytes,
68
+ uint64_t skip_end_bytes)
69
{
70
unsigned int l1_index, l2_offset, l2_index;
71
int min_index, i, j;
72
--
73
2.37.3
diff view generated by jsdifflib
1
From: Eiichi Tsukata <devel@etsukata.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
bdrv_open_driver() allocates bs->opaque according to drv->instance_size.
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
There is no need to allocate it and overwrite opaque in
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
bdrv_backup_top_append().
5
Message-Id: <20221013123711.620631-15-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Reproducer:
8
9
$ QTEST_QEMU_BINARY=./x86_64-softmmu/qemu-system-x86_64 valgrind -q --leak-check=full tests/test-replication -p /replication/secondary/start
10
==29792== 24 bytes in 1 blocks are definitely lost in loss record 52 of 226
11
==29792== at 0x483AB1A: calloc (vg_replace_malloc.c:762)
12
==29792== by 0x4B07CE0: g_malloc0 (in /usr/lib64/libglib-2.0.so.0.6000.7)
13
==29792== by 0x12BAB9: bdrv_open_driver (block.c:1289)
14
==29792== by 0x12BEA9: bdrv_new_open_driver (block.c:1359)
15
==29792== by 0x1D15CB: bdrv_backup_top_append (backup-top.c:190)
16
==29792== by 0x1CC11A: backup_job_create (backup.c:439)
17
==29792== by 0x1CD542: replication_start (replication.c:544)
18
==29792== by 0x1401B9: replication_start_all (replication.c:52)
19
==29792== by 0x128B50: test_secondary_start (test-replication.c:427)
20
...
21
22
Fixes: 7df7868b9640 ("block: introduce backup-top filter driver")
23
Signed-off-by: Eiichi Tsukata <devel@etsukata.com>
24
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
---
8
---
27
block/backup-top.c | 2 +-
9
block/commit.c | 2 +-
28
1 file changed, 1 insertion(+), 1 deletion(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
29
11
30
diff --git a/block/backup-top.c b/block/backup-top.c
12
diff --git a/block/commit.c b/block/commit.c
31
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
32
--- a/block/backup-top.c
14
--- a/block/commit.c
33
+++ b/block/backup-top.c
15
+++ b/block/commit.c
34
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_backup_top_append(BlockDriverState *source,
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn commit_run(Job *job, Error **errp)
35
}
17
}
36
18
37
top->total_sectors = source->total_sectors;
19
if (base_len < len) {
38
- top->opaque = state = g_new0(BDRVBackupTopState, 1);
20
- ret = blk_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
39
+ state = top->opaque;
21
+ ret = blk_co_truncate(s->base, len, false, PREALLOC_MODE_OFF, 0, NULL);
40
22
if (ret) {
41
bdrv_ref(target);
23
return ret;
42
state->target = bdrv_attach_child(top, target, "target", &child_file, errp);
24
}
43
--
25
--
44
2.20.1
26
2.37.3
45
46
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-16-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block.c | 2 +-
10
block/io.c | 4 ++--
11
2 files changed, 3 insertions(+), 3 deletions(-)
12
13
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
16
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ create_file_fallback_zero_first_sector(BlockBackend *blk,
18
19
bytes_to_clear = MIN(current_size, BDRV_SECTOR_SIZE);
20
if (bytes_to_clear) {
21
- ret = blk_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
22
+ ret = blk_co_pwrite_zeroes(blk, 0, bytes_to_clear, BDRV_REQ_MAY_UNMAP);
23
if (ret < 0) {
24
error_setg_errno(errp, -ret,
25
"Failed to clear the new image's first sector");
26
diff --git a/block/io.c b/block/io.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/io.c
29
+++ b/block/io.c
30
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_is_zero_fast(BlockDriverState *bs, int64_t offset,
31
return 1;
32
}
33
34
- ret = bdrv_common_block_status_above(bs, NULL, false, false, offset,
35
- bytes, &pnum, NULL, NULL, NULL);
36
+ ret = bdrv_co_common_block_status_above(bs, NULL, false, false, offset,
37
+ bytes, &pnum, NULL, NULL, NULL);
38
39
if (ret < 0) {
40
return ret;
41
--
42
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-17-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/mirror.c | 4 ++--
10
1 file changed, 2 insertions(+), 2 deletions(-)
11
12
diff --git a/block/mirror.c b/block/mirror.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/mirror.c
15
+++ b/block/mirror.c
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
17
* active layer. */
18
if (s->base == blk_bs(s->target)) {
19
if (s->bdev_length > target_length) {
20
- ret = blk_truncate(s->target, s->bdev_length, false,
21
- PREALLOC_MODE_OFF, 0, NULL);
22
+ ret = blk_co_truncate(s->target, s->bdev_length, false,
23
+ PREALLOC_MODE_OFF, 0, NULL);
24
if (ret < 0) {
25
goto immediate_exit;
26
}
27
--
28
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-18-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/parallels.c | 28 ++++++++++++++--------------
10
1 file changed, 14 insertions(+), 14 deletions(-)
11
12
diff --git a/block/parallels.c b/block/parallels.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/parallels.c
15
+++ b/block/parallels.c
16
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs,
17
* force the safer-but-slower fallocate.
18
*/
19
if (s->prealloc_mode == PRL_PREALLOC_MODE_TRUNCATE) {
20
- ret = bdrv_truncate(bs->file,
21
- (s->data_end + space) << BDRV_SECTOR_BITS,
22
- false, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE,
23
- NULL);
24
+ ret = bdrv_co_truncate(bs->file,
25
+ (s->data_end + space) << BDRV_SECTOR_BITS,
26
+ false, PREALLOC_MODE_OFF,
27
+ BDRV_REQ_ZERO_WRITE, NULL);
28
if (ret == -ENOTSUP) {
29
s->prealloc_mode = PRL_PREALLOC_MODE_FALLOCATE;
30
}
31
}
32
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
33
- ret = bdrv_pwrite_zeroes(bs->file,
34
- s->data_end << BDRV_SECTOR_BITS,
35
- space << BDRV_SECTOR_BITS, 0);
36
+ ret = bdrv_co_pwrite_zeroes(bs->file,
37
+ s->data_end << BDRV_SECTOR_BITS,
38
+ space << BDRV_SECTOR_BITS, 0);
39
}
40
if (ret < 0) {
41
return ret;
42
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
43
if (off + to_write > s->header_size) {
44
to_write = s->header_size - off;
45
}
46
- ret = bdrv_pwrite(bs->file, off, to_write, (uint8_t *)s->header + off,
47
- 0);
48
+ ret = bdrv_co_pwrite(bs->file, off, to_write,
49
+ (uint8_t *)s->header + off, 0);
50
if (ret < 0) {
51
qemu_co_mutex_unlock(&s->lock);
52
return ret;
53
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
54
* In order to really repair the image, we must shrink it.
55
* That means we have to pass exact=true.
56
*/
57
- ret = bdrv_truncate(bs->file, res->image_end_offset, true,
58
- PREALLOC_MODE_OFF, 0, &local_err);
59
+ ret = bdrv_co_truncate(bs->file, res->image_end_offset, true,
60
+ PREALLOC_MODE_OFF, 0, &local_err);
61
if (ret < 0) {
62
error_report_err(local_err);
63
res->check_errors++;
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
65
memset(tmp, 0, sizeof(tmp));
66
memcpy(tmp, &header, sizeof(header));
67
68
- ret = blk_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
69
+ ret = blk_co_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
70
if (ret < 0) {
71
goto exit;
72
}
73
- ret = blk_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
74
- (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
75
+ ret = blk_co_pwrite_zeroes(blk, BDRV_SECTOR_SIZE,
76
+ (bat_sectors - 1) << BDRV_SECTOR_BITS, 0);
77
if (ret < 0) {
78
goto exit;
79
}
80
--
81
2.37.3
diff view generated by jsdifflib
1
From: Felipe Franciosi <felipe@nutanix.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
When querying an iSCSI server for the provisioning status of blocks (via
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
GET LBA STATUS), Qemu only validates that the response descriptor zero's
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
LBA matches the one requested. Given the SCSI spec allows servers to
5
Message-Id: <20221013123711.620631-19-pbonzini@redhat.com>
6
respond with the status of blocks beyond the end of the LUN, Qemu may
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
have its heap corrupted by clearing/setting too many bits at the end of
8
its allocmap for the LUN.
9
10
A malicious guest in control of the iSCSI server could carefully program
11
Qemu's heap (by selectively setting the bitmap) and then smash it.
12
13
This limits the number of bits that iscsi_co_block_status() will try to
14
update in the allocmap so it can't overflow the bitmap.
15
16
Fixes: CVE-2020-1711
17
Cc: qemu-stable@nongnu.org
18
Signed-off-by: Felipe Franciosi <felipe@nutanix.com>
19
Signed-off-by: Peter Turschmid <peter.turschm@nutanix.com>
20
Signed-off-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
8
---
23
block/iscsi.c | 5 +++--
9
block/qcow.c | 45 +++++++++++++++++++++++----------------------
24
1 file changed, 3 insertions(+), 2 deletions(-)
10
1 file changed, 23 insertions(+), 22 deletions(-)
25
11
26
diff --git a/block/iscsi.c b/block/iscsi.c
12
diff --git a/block/qcow.c b/block/qcow.c
27
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
28
--- a/block/iscsi.c
14
--- a/block/qcow.c
29
+++ b/block/iscsi.c
15
+++ b/block/qcow.c
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
31
struct scsi_get_lba_status *lbas = NULL;
17
s->l1_table[l1_index] = l2_offset;
32
struct scsi_lba_status_descriptor *lbasd = NULL;
18
tmp = cpu_to_be64(l2_offset);
33
struct IscsiTask iTask;
19
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
34
- uint64_t lba;
20
- ret = bdrv_pwrite_sync(bs->file,
35
+ uint64_t lba, max_bytes;
21
- s->l1_table_offset + l1_index * sizeof(tmp),
36
int ret;
22
- sizeof(tmp), &tmp, 0);
37
23
+ ret = bdrv_co_pwrite_sync(bs->file,
38
iscsi_co_init_iscsitask(iscsilun, &iTask);
24
+ s->l1_table_offset + l1_index * sizeof(tmp),
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
25
+ sizeof(tmp), &tmp, 0);
26
if (ret < 0) {
27
return ret;
28
}
29
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
30
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
31
if (new_l2_table) {
32
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
33
- ret = bdrv_pwrite_sync(bs->file, l2_offset,
34
- s->l2_size * sizeof(uint64_t), l2_table, 0);
35
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset,
36
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
37
if (ret < 0) {
38
return ret;
39
}
40
} else {
41
- ret = bdrv_pread(bs->file, l2_offset, s->l2_size * sizeof(uint64_t),
42
- l2_table, 0);
43
+ ret = bdrv_co_pread(bs->file, l2_offset,
44
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
45
if (ret < 0) {
46
return ret;
47
}
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
49
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
50
/* write the cluster content */
51
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
52
- ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_size,
53
- s->cluster_cache, 0);
54
+ ret = bdrv_co_pwrite(bs->file, cluster_offset, s->cluster_size,
55
+ s->cluster_cache, 0);
56
if (ret < 0) {
57
return ret;
58
}
59
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
60
if (cluster_offset + s->cluster_size > INT64_MAX) {
61
return -E2BIG;
62
}
63
- ret = bdrv_truncate(bs->file, cluster_offset + s->cluster_size,
64
- false, PREALLOC_MODE_OFF, 0, NULL);
65
+ ret = bdrv_co_truncate(bs->file,
66
+ cluster_offset + s->cluster_size,
67
+ false, PREALLOC_MODE_OFF, 0, NULL);
68
if (ret < 0) {
69
return ret;
70
}
71
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
72
return -EIO;
73
}
74
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
75
- ret = bdrv_pwrite(bs->file, cluster_offset + i,
76
- BDRV_SECTOR_SIZE,
77
- s->cluster_data, 0);
78
+ ret = bdrv_co_pwrite(bs->file, cluster_offset + i,
79
+ BDRV_SECTOR_SIZE,
80
+ s->cluster_data, 0);
81
if (ret < 0) {
82
return ret;
83
}
84
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
85
} else {
86
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
87
}
88
- ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
89
- sizeof(tmp), &tmp, 0);
90
+ ret = bdrv_co_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
91
+ sizeof(tmp), &tmp, 0);
92
if (ret < 0) {
93
return ret;
94
}
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn decompress_cluster(BlockDriverState *bs,
96
csize = cluster_offset >> (63 - s->cluster_bits);
97
csize &= (s->cluster_size - 1);
98
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
99
- ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
100
+ ret = bdrv_co_pread(bs->file, coffset, csize, s->cluster_data, 0);
101
if (ret < 0)
102
return -1;
103
if (decompress_buffer(s->cluster_cache, s->cluster_size,
104
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
40
}
105
}
41
106
42
lba = offset / iscsilun->block_size;
107
/* write all the data */
43
+ max_bytes = (iscsilun->num_blocks - lba) * iscsilun->block_size;
108
- ret = blk_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
44
109
+ ret = blk_co_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
45
qemu_mutex_lock(&iscsilun->mutex);
110
if (ret < 0) {
46
retry:
111
goto exit;
47
@@ -XXX,XX +XXX,XX @@ retry:
48
goto out_unlock;
49
}
112
}
50
113
51
- *pnum = (int64_t) lbasd->num_blocks * iscsilun->block_size;
114
if (qcow_opts->has_backing_file) {
52
+ *pnum = MIN((int64_t) lbasd->num_blocks * iscsilun->block_size, max_bytes);
115
- ret = blk_pwrite(qcow_blk, sizeof(header), backing_filename_len,
53
116
- qcow_opts->backing_file, 0);
54
if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
117
+ ret = blk_co_pwrite(qcow_blk, sizeof(header), backing_filename_len,
55
lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
118
+ qcow_opts->backing_file, 0);
119
if (ret < 0) {
120
goto exit;
121
}
122
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
123
tmp = g_malloc0(BDRV_SECTOR_SIZE);
124
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
125
i++) {
126
- ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
127
- BDRV_SECTOR_SIZE, tmp, 0);
128
+ ret = blk_co_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
129
+ BDRV_SECTOR_SIZE, tmp, 0);
130
if (ret < 0) {
131
g_free(tmp);
132
goto exit;
56
--
133
--
57
2.20.1
134
2.37.3
58
59
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Dirty map addition and removal functions are not acquiring to BDS
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
AioContext, while they may call to code that expects it to be
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
acquired.
5
Message-Id: <20221013123711.620631-20-pbonzini@redhat.com>
6
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
This may trigger a crash with a stack trace like this one:
8
9
#0 0x00007f0ef146370f in __GI_raise (sig=sig@entry=6)
10
at ../sysdeps/unix/sysv/linux/raise.c:50
11
#1 0x00007f0ef144db25 in __GI_abort () at abort.c:79
12
#2 0x0000565022294dce in error_exit
13
(err=<optimized out>, msg=msg@entry=0x56502243a730 <__func__.16350> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36
14
#3 0x00005650222950ba in qemu_mutex_unlock_impl
15
(mutex=mutex@entry=0x5650244b0240, file=file@entry=0x565022439adf "util/async.c", line=line@entry=526) at util/qemu-thread-posix.c:108
16
#4 0x0000565022290029 in aio_context_release
17
(ctx=ctx@entry=0x5650244b01e0) at util/async.c:526
18
#5 0x000056502221cd08 in bdrv_can_store_new_dirty_bitmap
19
(bs=bs@entry=0x5650244dc820, name=name@entry=0x56502481d360 "bitmap1", granularity=granularity@entry=65536, errp=errp@entry=0x7fff22831718)
20
at block/dirty-bitmap.c:542
21
#6 0x000056502206ae53 in qmp_block_dirty_bitmap_add
22
(errp=0x7fff22831718, disabled=false, has_disabled=<optimized out>, persistent=<optimized out>, has_persistent=true, granularity=65536, has_granularity=<optimized out>, name=0x56502481d360 "bitmap1", node=<optimized out>) at blockdev.c:2894
23
#7 0x000056502206ae53 in qmp_block_dirty_bitmap_add
24
(node=<optimized out>, name=0x56502481d360 "bitmap1", has_granularity=<optimized out>, granularity=<optimized out>, has_persistent=true, persistent=<optimized out>, has_disabled=false, disabled=false, errp=0x7fff22831718) at blockdev.c:2856
25
#8 0x00005650221847a3 in qmp_marshal_block_dirty_bitmap_add
26
(args=<optimized out>, ret=<optimized out>, errp=0x7fff22831798)
27
at qapi/qapi-commands-block-core.c:651
28
#9 0x0000565022247e6c in do_qmp_dispatch
29
(errp=0x7fff22831790, allow_oob=<optimized out>, request=<optimized out>, cmds=0x565022b32d60 <qmp_commands>) at qapi/qmp-dispatch.c:132
30
#10 0x0000565022247e6c in qmp_dispatch
31
(cmds=0x565022b32d60 <qmp_commands>, request=<optimized out>, allow_oob=<optimized out>) at qapi/qmp-dispatch.c:175
32
#11 0x0000565022166061 in monitor_qmp_dispatch
33
(mon=0x56502450faa0, req=<optimized out>) at monitor/qmp.c:145
34
#12 0x00005650221666fa in monitor_qmp_bh_dispatcher
35
(data=<optimized out>) at monitor/qmp.c:234
36
#13 0x000056502228f866 in aio_bh_call (bh=0x56502440eae0)
37
at util/async.c:117
38
#14 0x000056502228f866 in aio_bh_poll (ctx=ctx@entry=0x56502440d7a0)
39
at util/async.c:117
40
#15 0x0000565022292c54 in aio_dispatch (ctx=0x56502440d7a0)
41
at util/aio-posix.c:459
42
#16 0x000056502228f742 in aio_ctx_dispatch
43
(source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:260
44
#17 0x00007f0ef5ce667d in g_main_dispatch (context=0x56502449aa40)
45
at gmain.c:3176
46
#18 0x00007f0ef5ce667d in g_main_context_dispatch
47
(context=context@entry=0x56502449aa40) at gmain.c:3829
48
#19 0x0000565022291d08 in glib_pollfds_poll () at util/main-loop.c:219
49
#20 0x0000565022291d08 in os_host_main_loop_wait
50
(timeout=<optimized out>) at util/main-loop.c:242
51
#21 0x0000565022291d08 in main_loop_wait (nonblocking=<optimized out>)
52
at util/main-loop.c:518
53
#22 0x00005650220743c1 in main_loop () at vl.c:1828
54
#23 0x0000565021f20a72 in main
55
(argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)
56
at vl.c:4504
57
58
Fix this by acquiring the AioContext at qmp_block_dirty_bitmap_add()
59
and qmp_block_dirty_bitmap_add().
60
61
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1782175
62
Signed-off-by: Sergio Lopez <slp@redhat.com>
63
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
64
---
8
---
65
blockdev.c | 22 ++++++++++++++++++----
9
block/qcow2-cluster.c | 8 ++++----
66
1 file changed, 18 insertions(+), 4 deletions(-)
10
block/qcow2-refcount.c | 10 +++++-----
11
block/qcow2-snapshot.c | 6 +++---
12
block/qcow2.c | 24 ++++++++++++------------
13
4 files changed, 24 insertions(+), 24 deletions(-)
67
14
68
diff --git a/blockdev.c b/blockdev.c
15
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
69
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
70
--- a/blockdev.c
17
--- a/block/qcow2-cluster.c
71
+++ b/blockdev.c
18
+++ b/block/qcow2-cluster.c
72
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
19
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_l1_table(BlockDriverState *bs,
73
{
20
#endif
74
BlockDriverState *bs;
21
75
BdrvDirtyBitmap *bitmap;
22
BLKDBG_EVENT(bs->file, BLKDBG_L1_SHRINK_WRITE_TABLE);
76
+ AioContext *aio_context;
23
- ret = bdrv_pwrite_zeroes(bs->file, s->l1_table_offset +
77
24
- new_l1_size * L1E_SIZE,
78
if (!name || name[0] == '\0') {
25
- (s->l1_size - new_l1_size) * L1E_SIZE, 0);
79
error_setg(errp, "Bitmap name cannot be empty");
26
+ ret = bdrv_co_pwrite_zeroes(bs->file,
80
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
27
+ s->l1_table_offset + new_l1_size * L1E_SIZE,
81
return;
28
+ (s->l1_size - new_l1_size) * L1E_SIZE, 0);
29
if (ret < 0) {
30
goto fail;
82
}
31
}
83
32
84
+ aio_context = bdrv_get_aio_context(bs);
33
- ret = bdrv_flush(bs->file->bs);
85
+ aio_context_acquire(aio_context);
34
+ ret = bdrv_co_flush(bs->file->bs);
86
+
35
if (ret < 0) {
87
if (has_granularity) {
36
goto fail;
88
if (granularity < 512 || !is_power_of_2(granularity)) {
37
}
89
error_setg(errp, "Granularity must be power of 2 "
38
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
90
"and at least 512");
39
index XXXXXXX..XXXXXXX 100644
91
- return;
40
--- a/block/qcow2-refcount.c
92
+ goto out;
41
+++ b/block/qcow2-refcount.c
42
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_refcount_init(BlockDriverState *bs)
43
goto fail;
93
}
44
}
94
} else {
45
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
95
/* Default to cluster size, if available: */
46
- ret = bdrv_pread(bs->file, s->refcount_table_offset,
96
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
47
- refcount_table_size2, s->refcount_table, 0);
97
if (persistent &&
48
+ ret = bdrv_co_pread(bs->file, s->refcount_table_offset,
98
!bdrv_can_store_new_dirty_bitmap(bs, name, granularity, errp))
49
+ refcount_table_size2, s->refcount_table, 0);
99
{
50
if (ret < 0) {
100
- return;
51
goto fail;
101
+ goto out;
52
}
53
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_shrink_reftable(BlockDriverState *bs)
54
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
102
}
55
}
103
56
104
bitmap = bdrv_create_dirty_bitmap(bs, granularity, name, errp);
57
- ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset,
105
if (bitmap == NULL) {
58
- s->refcount_table_size * REFTABLE_ENTRY_SIZE,
106
- return;
59
- reftable_tmp, 0);
107
+ goto out;
60
+ ret = bdrv_co_pwrite_sync(bs->file, s->refcount_table_offset,
61
+ s->refcount_table_size * REFTABLE_ENTRY_SIZE,
62
+ reftable_tmp, 0);
63
/*
64
* If the write in the reftable failed the image may contain a partially
65
* overwritten reftable. In this case it would be better to clear the
66
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/qcow2-snapshot.c
69
+++ b/block/qcow2-snapshot.c
70
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
71
} QEMU_PACKED snapshot_table_pointer;
72
73
/* qcow2_do_open() discards this information in check mode */
74
- ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
75
- sizeof(snapshot_table_pointer), &snapshot_table_pointer,
76
- 0);
77
+ ret = bdrv_co_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
78
+ sizeof(snapshot_table_pointer), &snapshot_table_pointer,
79
+ 0);
80
if (ret < 0) {
81
result->check_errors++;
82
fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
83
diff --git a/block/qcow2.c b/block/qcow2.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/block/qcow2.c
86
+++ b/block/qcow2.c
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
88
uint64_t l1_vm_state_index;
89
bool update_header = false;
90
91
- ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
92
+ ret = bdrv_co_pread(bs->file, 0, sizeof(header), &header, 0);
93
if (ret < 0) {
94
error_setg_errno(errp, -ret, "Could not read qcow2 header");
95
goto fail;
96
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
97
if (header.header_length > sizeof(header)) {
98
s->unknown_header_fields_size = header.header_length - sizeof(header);
99
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
100
- ret = bdrv_pread(bs->file, sizeof(header),
101
- s->unknown_header_fields_size,
102
- s->unknown_header_fields, 0);
103
+ ret = bdrv_co_pread(bs->file, sizeof(header),
104
+ s->unknown_header_fields_size,
105
+ s->unknown_header_fields, 0);
106
if (ret < 0) {
107
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
108
"fields");
109
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
110
ret = -ENOMEM;
111
goto fail;
112
}
113
- ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
114
- s->l1_table, 0);
115
+ ret = bdrv_co_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
116
+ s->l1_table, 0);
117
if (ret < 0) {
118
error_setg_errno(errp, -ret, "Could not read L1 table");
119
goto fail;
120
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
121
}
122
123
s->image_backing_file = g_malloc(len + 1);
124
- ret = bdrv_pread(bs->file, header.backing_file_offset, len,
125
- s->image_backing_file, 0);
126
+ ret = bdrv_co_pread(bs->file, header.backing_file_offset, len,
127
+ s->image_backing_file, 0);
128
if (ret < 0) {
129
error_setg_errno(errp, -ret, "Could not read backing file name");
130
goto fail;
131
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
132
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
108
}
133
}
109
134
110
if (disabled) {
135
- ret = blk_pwrite(blk, 0, cluster_size, header, 0);
111
@@ -XXX,XX +XXX,XX @@ void qmp_block_dirty_bitmap_add(const char *node, const char *name,
136
+ ret = blk_co_pwrite(blk, 0, cluster_size, header, 0);
137
g_free(header);
138
if (ret < 0) {
139
error_setg_errno(errp, -ret, "Could not write qcow2 header");
140
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
141
/* Write a refcount table with one refcount block */
142
refcount_table = g_malloc0(2 * cluster_size);
143
refcount_table[0] = cpu_to_be64(2 * cluster_size);
144
- ret = blk_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
145
+ ret = blk_co_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
146
g_free(refcount_table);
147
148
if (ret < 0) {
149
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
112
}
150
}
113
151
114
bdrv_dirty_bitmap_set_persistence(bitmap, persistent);
152
/* Okay, now that we have a valid image, let's give it the right size */
115
+
153
- ret = blk_truncate(blk, qcow2_opts->size, false, qcow2_opts->preallocation,
116
+out:
154
- 0, errp);
117
+ aio_context_release(aio_context);
155
+ ret = blk_co_truncate(blk, qcow2_opts->size, false,
118
}
156
+ qcow2_opts->preallocation, 0, errp);
119
157
if (ret < 0) {
120
static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
158
error_prepend(errp, "Could not resize image: ");
121
@@ -XXX,XX +XXX,XX @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
159
goto out;
122
{
123
BlockDriverState *bs;
124
BdrvDirtyBitmap *bitmap;
125
+ AioContext *aio_context;
126
127
bitmap = block_dirty_bitmap_lookup(node, name, &bs, errp);
128
if (!bitmap || !bs) {
129
return NULL;
130
}
131
132
+ aio_context = bdrv_get_aio_context(bs);
133
+ aio_context_acquire(aio_context);
134
+
135
if (bdrv_dirty_bitmap_check(bitmap, BDRV_BITMAP_BUSY | BDRV_BITMAP_RO,
136
errp)) {
137
+ aio_context_release(aio_context);
138
return NULL;
139
}
140
141
if (bdrv_dirty_bitmap_get_persistence(bitmap) &&
142
bdrv_remove_persistent_dirty_bitmap(bs, name, errp) < 0)
143
{
144
- return NULL;
145
+ aio_context_release(aio_context);
146
+ return NULL;
147
}
148
149
if (release) {
150
@@ -XXX,XX +XXX,XX @@ static BdrvDirtyBitmap *do_block_dirty_bitmap_remove(
151
*bitmap_bs = bs;
152
}
153
154
+ aio_context_release(aio_context);
155
return release ? NULL : bitmap;
156
}
157
158
--
160
--
159
2.20.1
161
2.37.3
160
161
diff view generated by jsdifflib
1
In iscsi_co_block_status(), we may have received num_descriptors == 0
1
From: Alberto Faria <afaria@redhat.com>
2
from the iscsi server. Therefore, we can't unconditionally access
3
lbas->descriptors[0]. Add the missing check.
4
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-21-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Felipe Franciosi <felipe@nutanix.com>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Reviewed-by: John Snow <jsnow@redhat.com>
9
Reviewed-by: Peter Lieven <pl@kamp.de>
10
---
8
---
11
block/iscsi.c | 2 +-
9
block/qed-table.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
10
block/qed.c | 12 ++++++------
11
2 files changed, 7 insertions(+), 7 deletions(-)
13
12
14
diff --git a/block/iscsi.c b/block/iscsi.c
13
diff --git a/block/qed-table.c b/block/qed-table.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/block/iscsi.c
15
--- a/block/qed-table.c
17
+++ b/block/iscsi.c
16
+++ b/block/qed-table.c
18
@@ -XXX,XX +XXX,XX @@ retry:
17
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qed_write_table(BDRVQEDState *s, uint64_t offset,
19
}
18
}
20
19
21
lbas = scsi_datain_unmarshall(iTask.task);
20
if (flush) {
22
- if (lbas == NULL) {
21
- ret = bdrv_flush(s->bs);
23
+ if (lbas == NULL || lbas->num_descriptors == 0) {
22
+ ret = bdrv_co_flush(s->bs);
24
ret = -EIO;
23
if (ret < 0) {
25
goto out_unlock;
24
goto out;
25
}
26
diff --git a/block/qed.c b/block/qed.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/block/qed.c
29
+++ b/block/qed.c
30
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
31
int64_t file_size;
32
int ret;
33
34
- ret = bdrv_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
35
+ ret = bdrv_co_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
36
if (ret < 0) {
37
error_setg(errp, "Failed to read QED header");
38
return ret;
39
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
40
}
41
42
/* From here on only known autoclear feature bits are valid */
43
- bdrv_flush(bs->file->bs);
44
+ bdrv_co_flush(bs->file->bs);
45
}
46
47
s->l1_table = qed_alloc_table(s);
48
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
49
* The QED format associates file length with allocation status,
50
* so a new file (which is empty) must have a length of 0.
51
*/
52
- ret = blk_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
53
+ ret = blk_co_truncate(blk, 0, true, PREALLOC_MODE_OFF, 0, errp);
54
if (ret < 0) {
55
goto out;
56
}
57
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
58
}
59
60
qed_header_cpu_to_le(&header, &le_header);
61
- ret = blk_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
62
+ ret = blk_co_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
63
if (ret < 0) {
64
goto out;
65
}
66
- ret = blk_pwrite(blk, sizeof(le_header), header.backing_filename_size,
67
+ ret = blk_co_pwrite(blk, sizeof(le_header), header.backing_filename_size,
68
qed_opts->backing_file, 0);
69
if (ret < 0) {
70
goto out;
71
}
72
73
l1_table = g_malloc0(l1_size);
74
- ret = blk_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
75
+ ret = blk_co_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
76
if (ret < 0) {
77
goto out;
26
}
78
}
27
--
79
--
28
2.20.1
80
2.37.3
29
30
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-22-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vdi.c | 17 +++++++++--------
10
1 file changed, 9 insertions(+), 8 deletions(-)
11
12
diff --git a/block/vdi.c b/block/vdi.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vdi.c
15
+++ b/block/vdi.c
16
@@ -XXX,XX +XXX,XX @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
17
* so this full-cluster write does not overlap a partial write
18
* of the same cluster, issued from the "else" branch.
19
*/
20
- ret = bdrv_pwrite(bs->file, data_offset, s->block_size, block, 0);
21
+ ret = bdrv_co_pwrite(bs->file, data_offset, s->block_size, block,
22
+ 0);
23
qemu_co_rwlock_unlock(&s->bmap_lock);
24
} else {
25
nonallocating_write:
26
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
27
assert(VDI_IS_ALLOCATED(bmap_first));
28
*header = s->header;
29
vdi_header_to_le(header);
30
- ret = bdrv_pwrite(bs->file, 0, sizeof(*header), header, 0);
31
+ ret = bdrv_co_pwrite(bs->file, 0, sizeof(*header), header, 0);
32
g_free(header);
33
34
if (ret < 0) {
35
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
36
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
37
logout("will write %u block map sectors starting from entry %u\n",
38
n_sectors, bmap_first);
39
- ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE,
40
- n_sectors * SECTOR_SIZE, base, 0);
41
+ ret = bdrv_co_pwrite(bs->file, offset * SECTOR_SIZE,
42
+ n_sectors * SECTOR_SIZE, base, 0);
43
}
44
45
return ret;
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
47
vdi_header_print(&header);
48
}
49
vdi_header_to_le(&header);
50
- ret = blk_pwrite(blk, offset, sizeof(header), &header, 0);
51
+ ret = blk_co_pwrite(blk, offset, sizeof(header), &header, 0);
52
if (ret < 0) {
53
error_setg(errp, "Error writing header");
54
goto exit;
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
56
bmap[i] = VDI_UNALLOCATED;
57
}
58
}
59
- ret = blk_pwrite(blk, offset, bmap_size, bmap, 0);
60
+ ret = blk_co_pwrite(blk, offset, bmap_size, bmap, 0);
61
if (ret < 0) {
62
error_setg(errp, "Error writing bmap");
63
goto exit;
64
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
65
}
66
67
if (image_type == VDI_TYPE_STATIC) {
68
- ret = blk_truncate(blk, offset + blocks * block_size, false,
69
- PREALLOC_MODE_OFF, 0, errp);
70
+ ret = blk_co_truncate(blk, offset + blocks * block_size, false,
71
+ PREALLOC_MODE_OFF, 0, errp);
72
if (ret < 0) {
73
error_prepend(errp, "Failed to statically allocate file");
74
goto exit;
75
--
76
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-23-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vhdx.c | 8 ++++----
10
1 file changed, 4 insertions(+), 4 deletions(-)
11
12
diff --git a/block/vhdx.c b/block/vhdx.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vhdx.c
15
+++ b/block/vhdx.c
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
17
creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
18
&creator_items, NULL);
19
signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
20
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
21
- 0);
22
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
23
+ 0);
24
if (ret < 0) {
25
error_setg_errno(errp, -ret, "Failed to write file signature");
26
goto delete_and_exit;
27
}
28
if (creator) {
29
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
30
- creator_items * sizeof(gunichar2), creator, 0);
31
+ ret = blk_co_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
32
+ creator_items * sizeof(gunichar2), creator, 0);
33
if (ret < 0) {
34
error_setg_errno(errp, -ret, "Failed to write creator field");
35
goto delete_and_exit;
36
--
37
2.37.3
diff view generated by jsdifflib
New patch
1
From: Alberto Faria <afaria@redhat.com>
1
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Message-Id: <20221013123711.620631-24-pbonzini@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/vmdk.c | 54 ++++++++++++++++++++++++++--------------------------
10
1 file changed, 27 insertions(+), 27 deletions(-)
11
12
diff --git a/block/vmdk.c b/block/vmdk.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/block/vmdk.c
15
+++ b/block/vmdk.c
16
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
17
if (copy_from_backing) {
18
/* qcow2 emits this on bs->file instead of bs->backing */
19
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
20
- ret = bdrv_pread(bs->backing, offset, skip_start_bytes,
21
- whole_grain, 0);
22
+ ret = bdrv_co_pread(bs->backing, offset, skip_start_bytes,
23
+ whole_grain, 0);
24
if (ret < 0) {
25
ret = VMDK_ERROR;
26
goto exit;
27
}
28
}
29
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
30
- ret = bdrv_pwrite(extent->file, cluster_offset, skip_start_bytes,
31
- whole_grain, 0);
32
+ ret = bdrv_co_pwrite(extent->file, cluster_offset, skip_start_bytes,
33
+ whole_grain, 0);
34
if (ret < 0) {
35
ret = VMDK_ERROR;
36
goto exit;
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_whole_cluster(BlockDriverState *bs,
38
if (copy_from_backing) {
39
/* qcow2 emits this on bs->file instead of bs->backing */
40
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
41
- ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
42
- cluster_bytes - skip_end_bytes,
43
- whole_grain + skip_end_bytes, 0);
44
+ ret = bdrv_co_pread(bs->backing, offset + skip_end_bytes,
45
+ cluster_bytes - skip_end_bytes,
46
+ whole_grain + skip_end_bytes, 0);
47
if (ret < 0) {
48
ret = VMDK_ERROR;
49
goto exit;
50
}
51
}
52
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
53
- ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
54
- cluster_bytes - skip_end_bytes,
55
- whole_grain + skip_end_bytes, 0);
56
+ ret = bdrv_co_pwrite(extent->file, cluster_offset + skip_end_bytes,
57
+ cluster_bytes - skip_end_bytes,
58
+ whole_grain + skip_end_bytes, 0);
59
if (ret < 0) {
60
ret = VMDK_ERROR;
61
goto exit;
62
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
63
offset = cpu_to_le32(offset);
64
/* update L2 table */
65
BLKDBG_EVENT(extent->file, BLKDBG_L2_UPDATE);
66
- if (bdrv_pwrite(extent->file,
67
- ((int64_t)m_data->l2_offset * 512)
68
- + (m_data->l2_index * sizeof(offset)),
69
- sizeof(offset), &offset, 0) < 0) {
70
+ if (bdrv_co_pwrite(extent->file,
71
+ ((int64_t)m_data->l2_offset * 512)
72
+ + (m_data->l2_index * sizeof(offset)),
73
+ sizeof(offset), &offset, 0) < 0) {
74
return VMDK_ERROR;
75
}
76
/* update backup L2 table */
77
if (extent->l1_backup_table_offset != 0) {
78
m_data->l2_offset = extent->l1_backup_table[m_data->l1_index];
79
- if (bdrv_pwrite(extent->file,
80
- ((int64_t)m_data->l2_offset * 512)
81
- + (m_data->l2_index * sizeof(offset)),
82
- sizeof(offset), &offset, 0) < 0) {
83
+ if (bdrv_co_pwrite(extent->file,
84
+ ((int64_t)m_data->l2_offset * 512)
85
+ + (m_data->l2_index * sizeof(offset)),
86
+ sizeof(offset), &offset, 0) < 0) {
87
return VMDK_ERROR;
88
}
89
}
90
- if (bdrv_flush(extent->file->bs) < 0) {
91
+ if (bdrv_co_flush(extent->file->bs) < 0) {
92
return VMDK_ERROR;
93
}
94
if (m_data->l2_cache_entry) {
95
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn get_cluster_offset(BlockDriverState *bs,
96
}
97
l2_table = (char *)extent->l2_cache + (min_index * l2_size_bytes);
98
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
99
- if (bdrv_pread(extent->file,
100
+ if (bdrv_co_pread(extent->file,
101
(int64_t)l2_offset * 512,
102
l2_size_bytes,
103
- l2_table,
104
- 0
105
+ l2_table, 0
106
) < 0) {
107
return VMDK_ERROR;
108
}
109
@@ -XXX,XX +XXX,XX @@ vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
110
cluster_buf = g_malloc(buf_bytes);
111
uncomp_buf = g_malloc(cluster_bytes);
112
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
113
- ret = bdrv_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, 0);
114
+ ret = bdrv_co_pread(extent->file, cluster_offset, buf_bytes, cluster_buf,
115
+ 0);
116
if (ret < 0) {
117
goto out;
118
}
119
@@ -XXX,XX +XXX,XX @@ vmdk_co_pwritev_compressed(BlockDriverState *bs, int64_t offset, int64_t bytes,
120
return length;
121
}
122
length = QEMU_ALIGN_UP(length, BDRV_SECTOR_SIZE);
123
- ret = bdrv_truncate(s->extents[i].file, length, false,
124
- PREALLOC_MODE_OFF, 0, NULL);
125
+ ret = bdrv_co_truncate(s->extents[i].file, length, false,
126
+ PREALLOC_MODE_OFF, 0, NULL);
127
if (ret < 0) {
128
return ret;
129
}
130
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
131
desc_offset = 0x200;
132
}
133
134
- ret = blk_pwrite(blk, desc_offset, desc_len, desc, 0);
135
+ ret = blk_co_pwrite(blk, desc_offset, desc_len, desc, 0);
136
if (ret < 0) {
137
error_setg_errno(errp, -ret, "Could not write description");
138
goto exit;
139
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
140
/* bdrv_pwrite write padding zeros to align to sector, we don't need that
141
* for description file */
142
if (desc_offset == 0) {
143
- ret = blk_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
144
+ ret = blk_co_truncate(blk, desc_len, false, PREALLOC_MODE_OFF, 0, errp);
145
if (ret < 0) {
146
goto exit;
147
}
148
--
149
2.37.3
diff view generated by jsdifflib
1
From: Sergio Lopez <slp@redhat.com>
1
From: Alberto Faria <afaria@redhat.com>
2
2
3
Fix a couple of minor coding style issues in drive_backup_prepare.
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
4
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Signed-off-by: Sergio Lopez <slp@redhat.com>
5
Message-Id: <20221013123711.620631-25-pbonzini@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
8
---
10
blockdev.c | 8 +++++---
9
blockdev.c | 2 +-
11
1 file changed, 5 insertions(+), 3 deletions(-)
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
11
13
diff --git a/blockdev.c b/blockdev.c
12
diff --git a/blockdev.c b/blockdev.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/blockdev.c
14
--- a/blockdev.c
16
+++ b/blockdev.c
15
+++ b/blockdev.c
17
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
16
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(bool has_device, const char *device,
18
17
bdrv_co_unlock(bs);
19
if (!backup->has_format) {
18
20
backup->format = backup->mode == NEW_IMAGE_MODE_EXISTING ?
19
old_ctx = bdrv_co_enter(bs);
21
- NULL : (char*) bs->drv->format_name;
20
- blk_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
22
+ NULL : (char *) bs->drv->format_name;
21
+ blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
23
}
22
bdrv_co_leave(bs, old_ctx);
24
23
25
/* Early check to avoid creating target */
24
bdrv_co_lock(bs);
26
@@ -XXX,XX +XXX,XX @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
27
28
flags = bs->open_flags | BDRV_O_RDWR;
29
30
- /* See if we have a backing HD we can use to create our new image
31
- * on top of. */
32
+ /*
33
+ * See if we have a backing HD we can use to create our new image
34
+ * on top of.
35
+ */
36
if (backup->sync == MIRROR_SYNC_MODE_TOP) {
37
source = backing_bs(bs);
38
if (!source) {
39
--
25
--
40
2.20.1
26
2.37.3
41
42
diff view generated by jsdifflib
New patch
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
1
2
3
blk_set_enable_write_cache() is defined as GLOBAL_STATE_CODE
4
but can be invoked from iothreads when handling scsi requests.
5
This triggers an assertion failure:
6
7
0x00007fd6c3515ce1 in raise () from /lib/x86_64-linux-gnu/libc.so.6
8
0x00007fd6c34ff537 in abort () from /lib/x86_64-linux-gnu/libc.so.6
9
0x00007fd6c34ff40f in ?? () from /lib/x86_64-linux-gnu/libc.so.6
10
0x00007fd6c350e662 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
11
0x000056149e2cea03 in blk_set_enable_write_cache (wce=true, blk=0x5614a01c27f0)
12
at ../src/block/block-backend.c:1949
13
0x000056149e2d0a67 in blk_set_enable_write_cache (blk=0x5614a01c27f0,
14
wce=<optimized out>) at ../src/block/block-backend.c:1951
15
0x000056149dfe9c59 in scsi_disk_apply_mode_select (p=0x7fd6b400c00e "\004",
16
page=<optimized out>, s=<optimized out>) at ../src/hw/scsi/scsi-disk.c:1520
17
mode_select_pages (change=true, len=18, p=0x7fd6b400c00e "\004", r=0x7fd6b4001ff0)
18
at ../src/hw/scsi/scsi-disk.c:1570
19
scsi_disk_emulate_mode_select (inbuf=<optimized out>, r=0x7fd6b4001ff0) at
20
../src/hw/scsi/scsi-disk.c:1640
21
scsi_disk_emulate_write_data (req=0x7fd6b4001ff0) at ../src/hw/scsi/scsi-disk.c:1934
22
0x000056149e18ff16 in virtio_scsi_handle_cmd_req_submit (req=<optimized out>,
23
req=<optimized out>, s=0x5614a12f16b0) at ../src/hw/scsi/virtio-scsi.c:719
24
virtio_scsi_handle_cmd_vq (vq=0x7fd6bab92140, s=0x5614a12f16b0) at
25
../src/hw/scsi/virtio-scsi.c:761
26
virtio_scsi_handle_cmd (vq=<optimized out>, vdev=<optimized out>) at
27
../src/hw/scsi/virtio-scsi.c:775
28
virtio_scsi_handle_cmd (vdev=0x5614a12f16b0, vq=0x7fd6bab92140) at
29
../src/hw/scsi/virtio-scsi.c:765
30
0x000056149e1a8aa6 in virtio_queue_notify_vq (vq=0x7fd6bab92140) at
31
../src/hw/virtio/virtio.c:2365
32
0x000056149e3ccea5 in aio_dispatch_handler (ctx=ctx@entry=0x5614a01babe0,
33
node=<optimized out>) at ../src/util/aio-posix.c:369
34
0x000056149e3cd868 in aio_dispatch_ready_handlers (ready_list=0x7fd6c09b2680,
35
ctx=0x5614a01babe0) at ../src/util/aio-posix.c:399
36
aio_poll (ctx=0x5614a01babe0, blocking=blocking@entry=true) at
37
../src/util/aio-posix.c:713
38
0x000056149e2a7796 in iothread_run (opaque=opaque@entry=0x56149ffde500) at
39
../src/iothread.c:67
40
0x000056149e3d0859 in qemu_thread_start (args=0x7fd6c09b26f0) at
41
../src/util/qemu-thread-posix.c:504
42
0x00007fd6c36b9ea7 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
43
0x00007fd6c35d9aef in clone () from /lib/x86_64-linux-gnu/libc.so.6
44
45
Changing GLOBAL_STATE_CODE in IO_CODE is allowed, since GSC callers are
46
allowed to call IO_CODE.
47
48
Resolves: #1272
49
50
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
51
Message-Id: <20221027072726.2681500-1-eesposit@redhat.com>
52
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
53
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
54
Tested-by: Antoine Damhet <antoine.damhet@shadow.tech>
55
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
56
---
57
block/block-backend.c | 2 +-
58
1 file changed, 1 insertion(+), 1 deletion(-)
59
60
diff --git a/block/block-backend.c b/block/block-backend.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/block/block-backend.c
63
+++ b/block/block-backend.c
64
@@ -XXX,XX +XXX,XX @@ bool blk_enable_write_cache(BlockBackend *blk)
65
66
void blk_set_enable_write_cache(BlockBackend *blk, bool wce)
67
{
68
- GLOBAL_STATE_CODE();
69
+ IO_CODE();
70
blk->enable_write_cache = wce;
71
}
72
73
--
74
2.37.3
diff view generated by jsdifflib