1
The following changes since commit bb9bf94b3e8926553290bc9a7cb84315af422086:
1
The following changes since commit b2896c1b09878fd1c4b485b3662f8beecbe0fef4:
2
2
3
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging (2018-12-11 19:18:58 +0000)
3
Merge tag 'vfio-updates-20230509.0' of https://gitlab.com/alex.williamson/qemu into staging (2023-05-10 11:20:35 +0100)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
git://repo.or.cz/qemu/kevin.git tags/for-upstream
7
https://repo.or.cz/qemu/kevin.git tags/for-upstream
8
8
9
for you to fetch changes up to 14a8882c0d6660684a0ec7e90cc75d4f38b07f0d:
9
for you to fetch changes up to 58a2e3f5c37be02dac3086b81bdda9414b931edf:
10
10
11
iotests: make 235 work on s390 (and others) (2018-12-12 12:22:31 +0100)
11
block: compile out assert_bdrv_graph_readable() by default (2023-05-10 14:16:54 +0200)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block layer patches:
14
Block layer patches
15
15
16
- qcow2: Decompression worker threads
16
- Graph locking, part 3 (more block drivers)
17
- dmg: lzfse compression support
17
- Compile out assert_bdrv_graph_readable() by default
18
- file-posix: Simplify delegation to worker thread
18
- Add configure options for vmdk, vhdx and vpc
19
- Don't pass flags to bdrv_reopen_queue()
19
- Fix use after free in blockdev_mark_auto_del()
20
- iotests: make 235 work on s390 (and others)
20
- migration: Attempt disk reactivation in more failure scenarios
21
- Coroutine correctness fixes
21
22
22
----------------------------------------------------------------
23
----------------------------------------------------------------
23
Alberto Garcia (15):
24
Emanuele Giuseppe Esposito (5):
24
block: Add bdrv_reopen_set_read_only()
25
nbd: Mark nbd_co_do_establish_connection() and callers GRAPH_RDLOCK
25
block: Use bdrv_reopen_set_read_only() in bdrv_backing_update_filename()
26
block: Mark bdrv_co_get_allocated_file_size() and callers GRAPH_RDLOCK
26
block: Use bdrv_reopen_set_read_only() in commit_start/complete()
27
block: Mark bdrv_co_get_info() and callers GRAPH_RDLOCK
27
block: Use bdrv_reopen_set_read_only() in bdrv_commit()
28
block: Mark bdrv_co_debug_event() GRAPH_RDLOCK
28
block: Use bdrv_reopen_set_read_only() in stream_start/complete()
29
block: Mark BlockDriver callbacks for amend job GRAPH_RDLOCK
29
block: Use bdrv_reopen_set_read_only() in qmp_change_backing_file()
30
block: Use bdrv_reopen_set_read_only() in external_snapshot_commit()
31
block: Use bdrv_reopen_set_read_only() in the mirror driver
32
block: Drop bdrv_reopen()
33
qemu-io: Put flag changes in the options QDict in reopen_f()
34
block: Clean up reopen_backing_file() in block/replication.c
35
block: Remove flags parameter from bdrv_reopen_queue()
36
block: Stop passing flags to bdrv_reopen_queue_child()
37
block: Remove assertions from update_flags_from_options()
38
block: Assert that flags are up-to-date in bdrv_reopen_prepare()
39
30
40
Christian Borntraeger (1):
31
Eric Blake (1):
41
iotests: make 235 work on s390 (and others)
32
migration: Attempt disk reactivation in more failure scenarios
42
33
43
Julio Faracco (4):
34
Kevin Wolf (18):
44
block: adding lzfse decompressing support as a module.
35
block: Fix use after free in blockdev_mark_auto_del()
45
configure: adding support to lzfse library.
36
iotests/nbd-reconnect-on-open: Fix NBD socket path
46
dmg: including dmg-lzfse module inside dmg block driver.
37
qcow2: Don't call bdrv_getlength() in coroutine_fns
47
dmg: exchanging hardcoded dmg UDIF block types to enum.
38
block: Consistently call bdrv_activate() outside coroutine
39
block: bdrv/blk_co_unref() for calls in coroutine context
40
block: Don't call no_coroutine_fns in qmp_block_resize()
41
iotests: Test resizing image attached to an iothread
42
test-bdrv-drain: Don't modify the graph in coroutines
43
graph-lock: Add GRAPH_UNLOCKED(_PTR)
44
graph-lock: Fix GRAPH_RDLOCK_GUARD*() to be reader lock
45
block: .bdrv_open is non-coroutine and unlocked
46
nbd: Remove nbd_co_flush() wrapper function
47
vhdx: Require GRAPH_RDLOCK for accessing a node's parent list
48
mirror: Require GRAPH_RDLOCK for accessing a node's parent list
49
block: Mark bdrv_query_bds_stats() and callers GRAPH_RDLOCK
50
block: Mark bdrv_query_block_graph_info() and callers GRAPH_RDLOCK
51
block: Mark bdrv_recurse_can_replace() and callers GRAPH_RDLOCK
52
block: Mark bdrv_refresh_limits() and callers GRAPH_RDLOCK
48
53
49
Kevin Wolf (12):
54
Paolo Bonzini (1):
50
file-posix: Reorganise RawPosixAIOData
55
block: add missing coroutine_fn annotations
51
file-posix: Factor out raw_thread_pool_submit()
52
file-posix: Avoid aio_worker() for QEMU_AIO_TRUNCATE
53
file-posix: Avoid aio_worker() for QEMU_AIO_COPY_RANGE
54
file-posix: Avoid aio_worker() for QEMU_AIO_WRITE_ZEROES
55
file-posix: Avoid aio_worker() for QEMU_AIO_DISCARD
56
file-posix: Avoid aio_worker() for QEMU_AIO_FLUSH
57
file-posix: Move read/write operation logic out of aio_worker()
58
file-posix: Avoid aio_worker() for QEMU_AIO_READ/WRITE
59
file-posix: Remove paio_submit_co()
60
file-posix: Switch to .bdrv_co_ioctl
61
file-posix: Avoid aio_worker() for QEMU_AIO_IOCTL
62
56
63
Vladimir Sementsov-Ogievskiy (9):
57
Stefan Hajnoczi (2):
64
block/replication: drop extra synchronization
58
aio-wait: avoid AioContext lock in aio_wait_bh_oneshot()
65
block/backup: drop unused synchronization interface
59
block: compile out assert_bdrv_graph_readable() by default
66
qcow2: use Z_OK instead of 0 for deflateInit2 return code check
67
qcow2: make more generic interface for qcow2_compress
68
qcow2: move decompression from qcow2-cluster.c to qcow2.c
69
qcow2: refactor decompress_buffer
70
qcow2: use byte-based read in qcow2_decompress_cluster
71
qcow2: aio support for compressed cluster read
72
qcow2: do decompression in threads
73
60
74
configure | 31 ++++
61
Vladimir Sementsov-Ogievskiy (1):
75
block/dmg.h | 3 +
62
block: add configure options for excluding vmdk, vhdx and vpc
76
block/qcow2.h | 4 -
77
include/block/block.h | 6 +-
78
include/block/block_backup.h | 13 --
79
include/scsi/pr-manager.h | 8 +-
80
block.c | 89 +++++-----
81
block/backup.c | 38 +----
82
block/commit.c | 23 +--
83
block/dmg-lzfse.c | 49 ++++++
84
block/dmg.c | 65 ++++++--
85
block/file-posix.c | 380 ++++++++++++++++++++++---------------------
86
block/mirror.c | 19 ++-
87
block/qcow2-cluster.c | 70 --------
88
block/qcow2.c | 170 ++++++++++++++++---
89
block/replication.c | 67 +++-----
90
block/stream.c | 20 +--
91
blockdev.c | 11 +-
92
qemu-io-cmds.c | 29 +++-
93
scsi/pr-manager.c | 21 +--
94
block/Makefile.objs | 2 +
95
scsi/trace-events | 2 +-
96
tests/qemu-iotests/133 | 18 ++
97
tests/qemu-iotests/133.out | 15 ++
98
tests/qemu-iotests/235 | 4 +-
99
25 files changed, 658 insertions(+), 499 deletions(-)
100
create mode 100644 block/dmg-lzfse.c
101
63
64
meson_options.txt | 8 ++
65
configure | 1 +
66
block/coroutines.h | 5 +-
67
block/qcow2.h | 4 +-
68
include/block/aio-wait.h | 2 +-
69
include/block/block-global-state.h | 19 +++-
70
include/block/block-io.h | 23 +++--
71
include/block/block_int-common.h | 37 +++----
72
include/block/block_int-global-state.h | 4 +-
73
include/block/graph-lock.h | 20 ++--
74
include/block/qapi.h | 7 +-
75
include/sysemu/block-backend-global-state.h | 5 +-
76
block.c | 25 ++++-
77
block/amend.c | 8 +-
78
block/blkverify.c | 5 +-
79
block/block-backend.c | 10 +-
80
block/crypto.c | 8 +-
81
block/graph-lock.c | 3 +
82
block/io.c | 12 +--
83
block/mirror.c | 18 +++-
84
block/nbd.c | 50 +++++----
85
block/parallels.c | 6 +-
86
block/qapi.c | 6 +-
87
block/qcow.c | 6 +-
88
block/qcow2-refcount.c | 2 +-
89
block/qcow2.c | 48 ++++-----
90
block/qed.c | 24 ++---
91
block/quorum.c | 4 +-
92
block/raw-format.c | 2 +-
93
block/vdi.c | 6 +-
94
block/vhdx.c | 15 +--
95
block/vmdk.c | 20 ++--
96
block/vpc.c | 6 +-
97
blockdev.c | 25 +++--
98
hw/block/dataplane/virtio-blk.c | 3 +-
99
hw/scsi/virtio-scsi-dataplane.c | 2 -
100
migration/migration.c | 24 +++--
101
qemu-img.c | 2 +
102
tests/unit/test-bdrv-drain.c | 112 ++++++++++++++-------
103
util/aio-wait.c | 2 +-
104
block/meson.build | 18 +++-
105
meson.build | 5 +
106
scripts/meson-buildoptions.sh | 13 +++
107
tests/qemu-iotests/tests/iothreads-resize | 71 +++++++++++++
108
tests/qemu-iotests/tests/iothreads-resize.out | 11 ++
109
tests/qemu-iotests/tests/nbd-reconnect-on-open | 3 +-
110
tests/qemu-iotests/tests/nbd-reconnect-on-open.out | 4 +-
111
47 files changed, 474 insertions(+), 240 deletions(-)
112
create mode 100755 tests/qemu-iotests/tests/iothreads-resize
113
create mode 100644 tests/qemu-iotests/tests/iothreads-resize.out
diff view generated by jsdifflib
1
From: Christian Borntraeger <borntraeger@de.ibm.com>
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
2
2
3
"-machine pc" will not work all architectures. Lets fall back to the
3
Let's add --enable / --disable configure options for these formats,
4
default machine by not specifying it.
4
so that those who don't need them may not build them.
5
5
6
In addition we also need to specify -no-shutdown on s390 as qemu will
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
7
exit otherwise.
7
Message-Id: <20230421092758.814122-1-vsementsov@yandex-team.ru>
8
8
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
9
Cc: qemu-stable@nongnu.org
10
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
10
---
14
tests/qemu-iotests/235 | 4 +++-
11
meson_options.txt | 6 ++++++
15
1 file changed, 3 insertions(+), 1 deletion(-)
12
block/meson.build | 18 +++++++++++++-----
13
meson.build | 3 +++
14
scripts/meson-buildoptions.sh | 9 +++++++++
15
4 files changed, 31 insertions(+), 5 deletions(-)
16
16
17
diff --git a/tests/qemu-iotests/235 b/tests/qemu-iotests/235
17
diff --git a/meson_options.txt b/meson_options.txt
18
index XXXXXXX..XXXXXXX 100755
18
index XXXXXXX..XXXXXXX 100644
19
--- a/tests/qemu-iotests/235
19
--- a/meson_options.txt
20
+++ b/tests/qemu-iotests/235
20
+++ b/meson_options.txt
21
@@ -XXX,XX +XXX,XX @@ qemu_img_create('-f', iotests.imgfmt, '-o', 'preallocation=metadata', disk,
21
@@ -XXX,XX +XXX,XX @@ option('qcow1', type: 'feature', value: 'auto',
22
str(size))
22
description: 'qcow1 image format support')
23
23
option('vdi', type: 'feature', value: 'auto',
24
vm = QEMUMachine(iotests.qemu_prog)
24
description: 'vdi image format support')
25
-vm.add_args('-machine', 'pc,accel=kvm')
25
+option('vhdx', type: 'feature', value: 'auto',
26
+vm.add_args('-machine', 'accel=kvm')
26
+ description: 'vhdx image format support')
27
+if iotests.qemu_default_machine == 's390-ccw-virtio':
27
+option('vmdk', type: 'feature', value: 'auto',
28
+ vm.add_args('-no-shutdown')
28
+ description: 'vmdk image format support')
29
vm.add_args('-drive', 'id=src,file=' + disk)
29
+option('vpc', type: 'feature', value: 'auto',
30
vm.launch()
30
+ description: 'vpc image format support')
31
31
option('vvfat', type: 'feature', value: 'auto',
32
description: 'vvfat image format support')
33
option('qed', type: 'feature', value: 'auto',
34
diff --git a/block/meson.build b/block/meson.build
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/meson.build
37
+++ b/block/meson.build
38
@@ -XXX,XX +XXX,XX @@ block_ss.add(files(
39
'snapshot-access.c',
40
'throttle-groups.c',
41
'throttle.c',
42
- 'vhdx-endian.c',
43
- 'vhdx-log.c',
44
- 'vhdx.c',
45
- 'vmdk.c',
46
- 'vpc.c',
47
'write-threshold.c',
48
), zstd, zlib, gnutls)
49
50
@@ -XXX,XX +XXX,XX @@ endif
51
if get_option('vdi').allowed()
52
block_ss.add(files('vdi.c'))
53
endif
54
+if get_option('vhdx').allowed()
55
+ block_ss.add(files(
56
+ 'vhdx-endian.c',
57
+ 'vhdx-log.c',
58
+ 'vhdx.c'
59
+ ))
60
+endif
61
+if get_option('vmdk').allowed()
62
+ block_ss.add(files('vmdk.c'))
63
+endif
64
+if get_option('vpc').allowed()
65
+ block_ss.add(files('vpc.c'))
66
+endif
67
if get_option('cloop').allowed()
68
block_ss.add(files('cloop.c'))
69
endif
70
diff --git a/meson.build b/meson.build
71
index XXXXXXX..XXXXXXX 100644
72
--- a/meson.build
73
+++ b/meson.build
74
@@ -XXX,XX +XXX,XX @@ if have_block
75
summary_info += {'dmg support': get_option('dmg').allowed()}
76
summary_info += {'qcow v1 support': get_option('qcow1').allowed()}
77
summary_info += {'vdi support': get_option('vdi').allowed()}
78
+ summary_info += {'vhdx support': get_option('vhdx').allowed()}
79
+ summary_info += {'vmdk support': get_option('vmdk').allowed()}
80
+ summary_info += {'vpc support': get_option('vpc').allowed()}
81
summary_info += {'vvfat support': get_option('vvfat').allowed()}
82
summary_info += {'qed support': get_option('qed').allowed()}
83
summary_info += {'parallels support': get_option('parallels').allowed()}
84
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
85
index XXXXXXX..XXXXXXX 100644
86
--- a/scripts/meson-buildoptions.sh
87
+++ b/scripts/meson-buildoptions.sh
88
@@ -XXX,XX +XXX,XX @@ meson_options_help() {
89
printf "%s\n" ' VDUSE block export support'
90
printf "%s\n" ' vfio-user-server'
91
printf "%s\n" ' vfio-user server support'
92
+ printf "%s\n" ' vhdx vhdx image format support'
93
printf "%s\n" ' vhost-crypto vhost-user crypto backend support'
94
printf "%s\n" ' vhost-kernel vhost kernel backend support'
95
printf "%s\n" ' vhost-net vhost-net kernel acceleration support'
96
@@ -XXX,XX +XXX,XX @@ meson_options_help() {
97
printf "%s\n" ' vhost-vdpa vhost-vdpa kernel backend support'
98
printf "%s\n" ' virglrenderer virgl rendering support'
99
printf "%s\n" ' virtfs virtio-9p support'
100
+ printf "%s\n" ' vmdk vmdk image format support'
101
printf "%s\n" ' vmnet vmnet.framework network backend support'
102
printf "%s\n" ' vnc VNC server'
103
printf "%s\n" ' vnc-jpeg JPEG lossy compression for VNC server'
104
printf "%s\n" ' vnc-sasl SASL authentication for VNC server'
105
+ printf "%s\n" ' vpc vpc image format support'
106
printf "%s\n" ' vte vte support for the gtk UI'
107
printf "%s\n" ' vvfat vvfat image format support'
108
printf "%s\n" ' whpx WHPX acceleration support'
109
@@ -XXX,XX +XXX,XX @@ _meson_option_parse() {
110
--disable-vduse-blk-export) printf "%s" -Dvduse_blk_export=disabled ;;
111
--enable-vfio-user-server) printf "%s" -Dvfio_user_server=enabled ;;
112
--disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;;
113
+ --enable-vhdx) printf "%s" -Dvhdx=enabled ;;
114
+ --disable-vhdx) printf "%s" -Dvhdx=disabled ;;
115
--enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;;
116
--disable-vhost-crypto) printf "%s" -Dvhost_crypto=disabled ;;
117
--enable-vhost-kernel) printf "%s" -Dvhost_kernel=enabled ;;
118
@@ -XXX,XX +XXX,XX @@ _meson_option_parse() {
119
--disable-virglrenderer) printf "%s" -Dvirglrenderer=disabled ;;
120
--enable-virtfs) printf "%s" -Dvirtfs=enabled ;;
121
--disable-virtfs) printf "%s" -Dvirtfs=disabled ;;
122
+ --enable-vmdk) printf "%s" -Dvmdk=enabled ;;
123
+ --disable-vmdk) printf "%s" -Dvmdk=disabled ;;
124
--enable-vmnet) printf "%s" -Dvmnet=enabled ;;
125
--disable-vmnet) printf "%s" -Dvmnet=disabled ;;
126
--enable-vnc) printf "%s" -Dvnc=enabled ;;
127
@@ -XXX,XX +XXX,XX @@ _meson_option_parse() {
128
--disable-vnc-jpeg) printf "%s" -Dvnc_jpeg=disabled ;;
129
--enable-vnc-sasl) printf "%s" -Dvnc_sasl=enabled ;;
130
--disable-vnc-sasl) printf "%s" -Dvnc_sasl=disabled ;;
131
+ --enable-vpc) printf "%s" -Dvpc=enabled ;;
132
+ --disable-vpc) printf "%s" -Dvpc=disabled ;;
133
--enable-vte) printf "%s" -Dvte=enabled ;;
134
--disable-vte) printf "%s" -Dvte=disabled ;;
135
--enable-vvfat) printf "%s" -Dvvfat=enabled ;;
32
--
136
--
33
2.19.2
137
2.40.1
34
35
diff view generated by jsdifflib
1
aio_worker() doesn't add anything interesting, it's only a useless
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
indirection. Call the handler function directly instead.
3
2
4
As we know that this handler function is only called from coroutine
3
After the recent introduction of many new coroutine callbacks,
5
context and the coroutine stays around until the worker thread finishes,
4
a couple calls from non-coroutine_fn to coroutine_fn have sneaked
6
we can keep RawPosixAIOData on the stack.
5
in; fix them.
7
6
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Message-Id: <20230406101752.242125-1-pbonzini@redhat.com>
9
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
block/file-posix.c | 32 ++++++++++++++++++++++++--------
12
include/block/graph-lock.h | 4 ++--
11
1 file changed, 24 insertions(+), 8 deletions(-)
13
block/mirror.c | 4 ++--
14
2 files changed, 4 insertions(+), 4 deletions(-)
12
15
13
diff --git a/block/file-posix.c b/block/file-posix.c
16
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
18
--- a/include/block/graph-lock.h
16
+++ b/block/file-posix.c
19
+++ b/include/block/graph-lock.h
17
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_copy_range(void *opaque)
20
@@ -XXX,XX +XXX,XX @@ typedef struct GraphLockable { } GraphLockable;
18
return 0;
21
* unlocked. TSA_ASSERT() makes sure that the following calls know that we
22
* hold the lock while unlocking is left unchecked.
23
*/
24
-static inline GraphLockable * TSA_ASSERT(graph_lock) TSA_NO_TSA
25
+static inline GraphLockable * TSA_ASSERT(graph_lock) TSA_NO_TSA coroutine_fn
26
graph_lockable_auto_lock(GraphLockable *x)
27
{
28
bdrv_graph_co_rdlock();
29
return x;
19
}
30
}
20
31
21
-static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
32
-static inline void TSA_NO_TSA
22
+static int handle_aiocb_discard(void *opaque)
33
+static inline void TSA_NO_TSA coroutine_fn
34
graph_lockable_auto_unlock(GraphLockable *x)
23
{
35
{
24
+ RawPosixAIOData *aiocb = opaque;
36
bdrv_graph_co_rdunlock();
25
int ret = -EOPNOTSUPP;
37
diff --git a/block/mirror.c b/block/mirror.c
26
BDRVRawState *s = aiocb->bs->opaque;
38
index XXXXXXX..XXXXXXX 100644
27
39
--- a/block/mirror.c
28
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
40
+++ b/block/mirror.c
29
ret = handle_aiocb_ioctl(aiocb);
41
@@ -XXX,XX +XXX,XX @@ static inline int64_t mirror_clip_bytes(MirrorBlockJob *s,
30
break;
42
31
case QEMU_AIO_DISCARD:
43
/* Round offset and/or bytes to target cluster if COW is needed, and
32
- ret = handle_aiocb_discard(aiocb);
44
* return the offset of the adjusted tail against original. */
33
- break;
45
-static int mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
34
case QEMU_AIO_WRITE_ZEROES:
46
- uint64_t *bytes)
35
case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
47
+static int coroutine_fn mirror_cow_align(MirrorBlockJob *s, int64_t *offset,
36
case QEMU_AIO_COPY_RANGE:
48
+ uint64_t *bytes)
37
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn raw_co_invalidate_cache(BlockDriverState *bs,
38
}
39
40
static coroutine_fn int
41
-raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
42
+raw_do_pdiscard(BlockDriverState *bs, int64_t offset, int bytes, bool blkdev)
43
{
49
{
44
BDRVRawState *s = bs->opaque;
50
bool need_cow;
45
+ RawPosixAIOData acb;
51
int ret = 0;
46
+
47
+ acb = (RawPosixAIOData) {
48
+ .bs = bs,
49
+ .aio_fildes = s->fd,
50
+ .aio_type = QEMU_AIO_DISCARD,
51
+ .aio_offset = offset,
52
+ .aio_nbytes = bytes,
53
+ };
54
55
- return paio_submit_co(bs, s->fd, offset, NULL, bytes, QEMU_AIO_DISCARD);
56
+ if (blkdev) {
57
+ acb.aio_type |= QEMU_AIO_BLKDEV;
58
+ }
59
+
60
+ return raw_thread_pool_submit(bs, handle_aiocb_discard, &acb);
61
+}
62
+
63
+static coroutine_fn int
64
+raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
65
+{
66
+ return raw_do_pdiscard(bs, offset, bytes, false);
67
}
68
69
static int coroutine_fn
70
@@ -XXX,XX +XXX,XX @@ static int fd_open(BlockDriverState *bs)
71
static coroutine_fn int
72
hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
73
{
74
- BDRVRawState *s = bs->opaque;
75
int ret;
76
77
ret = fd_open(bs);
78
if (ret < 0) {
79
return ret;
80
}
81
- return paio_submit_co(bs, s->fd, offset, NULL, bytes,
82
- QEMU_AIO_DISCARD | QEMU_AIO_BLKDEV);
83
+ return raw_do_pdiscard(bs, offset, bytes, true);
84
}
85
86
static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
87
--
52
--
88
2.19.2
53
2.40.1
89
90
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
This patch replaces the bdrv_reopen() calls that set and remove the
3
There is no need for the AioContext lock in aio_wait_bh_oneshot().
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
4
It's easy to remove the lock from existing callers and then switch from
5
AIO_WAIT_WHILE() to AIO_WAIT_WHILE_UNLOCKED() in aio_wait_bh_oneshot().
5
6
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Document that the AioContext lock should not be held across
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
aio_wait_bh_oneshot(). Holding a lock across aio_poll() can cause
9
deadlock so we don't want callers to do that.
10
11
This is a step towards getting rid of the AioContext lock.
12
13
Cc: Paolo Bonzini <pbonzini@redhat.com>
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-Id: <20230404153307.458883-1-stefanha@redhat.com>
16
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
17
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
18
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
20
---
10
block/stream.c | 20 ++++++++++----------
21
include/block/aio-wait.h | 2 +-
11
1 file changed, 10 insertions(+), 10 deletions(-)
22
hw/block/dataplane/virtio-blk.c | 3 ++-
23
hw/scsi/virtio-scsi-dataplane.c | 2 --
24
util/aio-wait.c | 2 +-
25
4 files changed, 4 insertions(+), 5 deletions(-)
12
26
13
diff --git a/block/stream.c b/block/stream.c
27
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
14
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
15
--- a/block/stream.c
29
--- a/include/block/aio-wait.h
16
+++ b/block/stream.c
30
+++ b/include/block/aio-wait.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct StreamBlockJob {
31
@@ -XXX,XX +XXX,XX @@ void aio_wait_kick(void);
18
BlockDriverState *base;
32
*
19
BlockdevOnError on_error;
33
* Run a BH in @ctx and wait for it to complete.
20
char *backing_file_str;
34
*
21
- int bs_flags;
35
- * Must be called from the main loop thread with @ctx acquired exactly once.
22
+ bool bs_read_only;
36
+ * Must be called from the main loop thread without @ctx acquired.
23
} StreamBlockJob;
37
* Note that main loop event processing may occur.
24
38
*/
25
static int coroutine_fn stream_populate(BlockBackend *blk,
39
void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
26
@@ -XXX,XX +XXX,XX @@ static void stream_clean(Job *job)
40
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
27
BlockDriverState *bs = blk_bs(bjob->blk);
41
index XXXXXXX..XXXXXXX 100644
28
42
--- a/hw/block/dataplane/virtio-blk.c
29
/* Reopen the image back in read-only mode if necessary */
43
+++ b/hw/block/dataplane/virtio-blk.c
30
- if (s->bs_flags != bdrv_get_flags(bs)) {
44
@@ -XXX,XX +XXX,XX @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev)
31
+ if (s->bs_read_only) {
45
s->stopping = true;
32
/* Give up write permissions before making it read-only */
46
trace_virtio_blk_data_plane_stop(s);
33
blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
47
34
- bdrv_reopen(bs, s->bs_flags, NULL);
48
- aio_context_acquire(s->ctx);
35
+ bdrv_reopen_set_read_only(bs, true, NULL);
49
aio_wait_bh_oneshot(s->ctx, virtio_blk_data_plane_stop_bh, s);
50
51
+ aio_context_acquire(s->ctx);
52
+
53
/* Wait for virtio_blk_dma_restart_bh() and in flight I/O to complete */
54
blk_drain(s->conf->conf.blk);
55
56
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/scsi/virtio-scsi-dataplane.c
59
+++ b/hw/scsi/virtio-scsi-dataplane.c
60
@@ -XXX,XX +XXX,XX @@ void virtio_scsi_dataplane_stop(VirtIODevice *vdev)
36
}
61
}
37
62
s->dataplane_stopping = true;
38
g_free(s->backing_file_str);
63
39
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
64
- aio_context_acquire(s->ctx);
40
{
65
aio_wait_bh_oneshot(s->ctx, virtio_scsi_dataplane_stop_bh, s);
41
StreamBlockJob *s;
66
- aio_context_release(s->ctx);
42
BlockDriverState *iter;
67
43
- int orig_bs_flags;
68
blk_drain_all(); /* ensure there are no in-flight requests */
44
+ bool bs_read_only;
69
45
70
diff --git a/util/aio-wait.c b/util/aio-wait.c
46
/* Make sure that the image is opened in read-write mode */
71
index XXXXXXX..XXXXXXX 100644
47
- orig_bs_flags = bdrv_get_flags(bs);
72
--- a/util/aio-wait.c
48
- if (!(orig_bs_flags & BDRV_O_RDWR)) {
73
+++ b/util/aio-wait.c
49
- if (bdrv_reopen(bs, orig_bs_flags | BDRV_O_RDWR, errp) != 0) {
74
@@ -XXX,XX +XXX,XX @@ void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
50
+ bs_read_only = bdrv_is_read_only(bs);
75
assert(qemu_get_current_aio_context() == qemu_get_aio_context());
51
+ if (bs_read_only) {
76
52
+ if (bdrv_reopen_set_read_only(bs, false, errp) != 0) {
77
aio_bh_schedule_oneshot(ctx, aio_wait_bh, &data);
53
return;
78
- AIO_WAIT_WHILE(ctx, !data.done);
54
}
79
+ AIO_WAIT_WHILE_UNLOCKED(NULL, !data.done);
55
}
56
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
57
58
s->base = base;
59
s->backing_file_str = g_strdup(backing_file_str);
60
- s->bs_flags = orig_bs_flags;
61
+ s->bs_read_only = bs_read_only;
62
63
s->on_error = on_error;
64
trace_stream_start(bs, base, s);
65
@@ -XXX,XX +XXX,XX @@ void stream_start(const char *job_id, BlockDriverState *bs,
66
return;
67
68
fail:
69
- if (orig_bs_flags != bdrv_get_flags(bs)) {
70
- bdrv_reopen(bs, orig_bs_flags, NULL);
71
+ if (bs_read_only) {
72
+ bdrv_reopen_set_read_only(bs, true, NULL);
73
}
74
}
80
}
75
--
81
--
76
2.19.2
82
2.40.1
77
78
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
job_cancel_locked() drops the job list lock temporarily and it may call
2
aio_poll(). We must assume that the list has changed after this call.
3
Also, with unlucky timing, it can end up freeing the job during
4
job_completed_txn_abort_locked(), making the job pointer invalid, too.
2
5
3
This patch replaces the bdrv_reopen() call that set and remove the
6
For both reasons, we can't just continue at block_job_next_locked(job).
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
7
Instead, start at the head of the list again after job_cancel_locked()
8
and skip those jobs that we already cancelled (or that are completing
9
anyway).
5
10
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
11
Cc: qemu-stable@nongnu.org
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Message-Id: <20230503140142.474404-1-kwolf@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
15
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
16
---
10
blockdev.c | 3 +--
17
blockdev.c | 18 ++++++++++++++----
11
1 file changed, 1 insertion(+), 2 deletions(-)
18
1 file changed, 14 insertions(+), 4 deletions(-)
12
19
13
diff --git a/blockdev.c b/blockdev.c
20
diff --git a/blockdev.c b/blockdev.c
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/blockdev.c
22
--- a/blockdev.c
16
+++ b/blockdev.c
23
+++ b/blockdev.c
17
@@ -XXX,XX +XXX,XX @@ static void external_snapshot_commit(BlkActionState *common)
24
@@ -XXX,XX +XXX,XX @@ void blockdev_mark_auto_del(BlockBackend *blk)
18
* bdrv_reopen_multiple() across all the entries at once, because we
25
19
* don't want to abort all of them if one of them fails the reopen */
26
JOB_LOCK_GUARD();
20
if (!atomic_read(&state->old_bs->copy_on_read)) {
27
21
- bdrv_reopen(state->old_bs, state->old_bs->open_flags & ~BDRV_O_RDWR,
28
- for (job = block_job_next_locked(NULL); job;
22
- NULL);
29
- job = block_job_next_locked(job)) {
23
+ bdrv_reopen_set_read_only(state->old_bs, true, NULL);
30
- if (block_job_has_bdrv(job, blk_bs(blk))) {
24
}
31
+ do {
25
32
+ job = block_job_next_locked(NULL);
26
aio_context_release(aio_context);
33
+ while (job && (job->job.cancelled ||
34
+ job->job.deferred_to_main_loop ||
35
+ !block_job_has_bdrv(job, blk_bs(blk))))
36
+ {
37
+ job = block_job_next_locked(job);
38
+ }
39
+ if (job) {
40
+ /*
41
+ * This drops the job lock temporarily and polls, so we need to
42
+ * restart processing the list from the start after this.
43
+ */
44
job_cancel_locked(&job->job, false);
45
}
46
- }
47
+ } while (job);
48
49
dinfo->auto_del = 1;
50
}
27
--
51
--
28
2.19.2
52
2.40.1
29
30
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
Socket paths need to be short to avoid failures. This is why there is a
2
iotests.sock_dir (defaulting to /tmp) separate from the disk image base
3
directory.
2
4
3
Towards the end of bdrv_reopen_queue_child(), before starting to
5
Make use of it to fix failures in too deeply nested test directories.
4
process the children, the update_flags_from_options() function is
5
called in order to have BDRVReopenState.flags in sync with the options
6
from the QDict.
7
6
8
This is necessary because during the reopen process flags must be
7
Fixes: ab7f7e67a7e7b49964109501dfcde4ec29bae60e
9
updated for all nodes in the queue so bdrv_is_writable_after_reopen()
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
and the permission checks work correctly.
9
Message-Id: <20230503165019.8867-1-kwolf@redhat.com>
11
10
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Because of that, calling update_flags_from_options() again in
11
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
13
bdrv_reopen_prepare() doesn't really change the flags (they are
14
already up-to-date). But we need to call it in order to remove those
15
options from QemuOpts and that way indicate that they have been
16
processed.
17
18
Signed-off-by: Alberto Garcia <berto@igalia.com>
19
Reviewed-by: Max Reitz <mreitz@redhat.com>
20
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
21
---
13
---
22
block.c | 6 ++++++
14
tests/qemu-iotests/tests/nbd-reconnect-on-open | 3 ++-
23
1 file changed, 6 insertions(+)
15
tests/qemu-iotests/tests/nbd-reconnect-on-open.out | 4 ++--
16
2 files changed, 4 insertions(+), 3 deletions(-)
24
17
25
diff --git a/block.c b/block.c
18
diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open b/tests/qemu-iotests/tests/nbd-reconnect-on-open
19
index XXXXXXX..XXXXXXX 100755
20
--- a/tests/qemu-iotests/tests/nbd-reconnect-on-open
21
+++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open
22
@@ -XXX,XX +XXX,XX @@ from iotests import qemu_img_create, file_path, qemu_io_popen, qemu_nbd, \
23
24
iotests.script_initialize(supported_fmts=['qcow2'])
25
26
-disk, nbd_sock = file_path('disk', 'nbd-sock')
27
+disk = file_path('disk')
28
+nbd_sock = file_path('nbd-sock', base_dir=iotests.sock_dir)
29
30
31
def create_args(open_timeout):
32
diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open.out b/tests/qemu-iotests/tests/nbd-reconnect-on-open.out
26
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
34
--- a/tests/qemu-iotests/tests/nbd-reconnect-on-open.out
28
+++ b/block.c
35
+++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open.out
29
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
36
@@ -XXX,XX +XXX,XX @@ read 1048576/1048576 bytes at offset 0
30
Error **errp)
37
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
31
{
38
32
int ret = -1;
39
Check fail to connect with 0 seconds of timeout
33
+ int old_flags;
40
-qemu-io: can't open: Failed to connect to 'TEST_DIR/PID-nbd-sock': No such file or directory
34
Error *local_err = NULL;
41
+qemu-io: can't open: Failed to connect to 'SOCK_DIR/PID-nbd-sock': No such file or directory
35
BlockDriver *drv;
42
36
QemuOpts *opts;
43
qemu_io finished in 0..0.2 seconds, OK
37
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
44
Check fail to connect with 1 seconds of timeout
38
goto error;
45
-qemu-io: can't open: Failed to connect to 'TEST_DIR/PID-nbd-sock': No such file or directory
39
}
46
+qemu-io: can't open: Failed to connect to 'SOCK_DIR/PID-nbd-sock': No such file or directory
40
47
41
+ /* This was already called in bdrv_reopen_queue_child() so the flags
48
qemu_io finished in 1..1.2 seconds, OK
42
+ * are up-to-date. This time we simply want to remove the options from
43
+ * QemuOpts in order to indicate that they have been processed. */
44
+ old_flags = reopen_state->flags;
45
update_flags_from_options(&reopen_state->flags, opts);
46
+ assert(old_flags == reopen_state->flags);
47
48
discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
49
if (discard != NULL) {
50
--
49
--
51
2.19.2
50
2.40.1
52
53
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Eric Blake <eblake@redhat.com>
2
2
3
This function takes four options (cache.direct, cache.no-flush,
3
Commit fe904ea824 added a fail_inactivate label, which tries to
4
read-only and auto-read-only) from a QemuOpts object and updates the
4
reactivate disks on the source after a failure while s->state ==
5
flags accordingly.
5
MIGRATION_STATUS_ACTIVE, but didn't actually use the label if
6
qemu_savevm_state_complete_precopy() failed. This failure to
7
reactivate is also present in commit 6039dd5b1c (also covering the new
8
s->state == MIGRATION_STATUS_DEVICE state) and 403d18ae (ensuring
9
s->block_inactive is set more reliably).
6
10
7
If any of those options is not set (because it was missing from the
11
Consolidate the two labels back into one - no matter HOW migration is
8
original QDict or because it had an invalid value) then the function
12
failed, if there is any chance we can reach vm_start() after having
9
aborts with a failed assertion:
13
attempted inactivation, it is essential that we have tried to restart
14
disks before then. This also makes the cleanup more like
15
migrate_fd_cancel().
10
16
11
$ qemu-io -c 'reopen -o read-only=foo' hd.qcow2
17
Suggested-by: Kevin Wolf <kwolf@redhat.com>
12
block.c:1126: update_flags_from_options: Assertion `qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT)' failed.
18
Signed-off-by: Eric Blake <eblake@redhat.com>
13
Aborted
19
Message-Id: <20230502205212.134680-1-eblake@redhat.com>
14
20
Acked-by: Peter Xu <peterx@redhat.com>
15
This assertion is unnecessary, and it forces any caller of
21
Reviewed-by: Juan Quintela <quintela@redhat.com>
16
bdrv_reopen() to pass all the aforementioned four options. This may
22
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
17
have made sense in order to remove ambiguity when bdrv_reopen() was
18
taking both flags and options, but that's not the case anymore.
19
20
It's also unnecessary if we want to validate the option values,
21
because bdrv_reopen_prepare() already takes care of that, as we can
22
see if we remove the assertions:
23
24
$ qemu-io -c 'reopen -o read-only=foo' hd.qcow2
25
Parameter 'read-only' expects 'on' or 'off'
26
27
Signed-off-by: Alberto Garcia <berto@igalia.com>
28
Reviewed-by: Max Reitz <mreitz@redhat.com>
29
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
23
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
30
---
24
---
31
block.c | 4 ----
25
migration/migration.c | 24 ++++++++++++++----------
32
tests/qemu-iotests/133 | 9 +++++++++
26
1 file changed, 14 insertions(+), 10 deletions(-)
33
tests/qemu-iotests/133.out | 7 +++++++
34
3 files changed, 16 insertions(+), 4 deletions(-)
35
27
36
diff --git a/block.c b/block.c
28
diff --git a/migration/migration.c b/migration/migration.c
37
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
38
--- a/block.c
30
--- a/migration/migration.c
39
+++ b/block.c
31
+++ b/migration/migration.c
40
@@ -XXX,XX +XXX,XX @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
32
@@ -XXX,XX +XXX,XX @@ static void migration_completion(MigrationState *s)
41
{
33
MIGRATION_STATUS_DEVICE);
42
*flags &= ~(BDRV_O_CACHE_MASK | BDRV_O_RDWR | BDRV_O_AUTO_RDONLY);
34
}
43
35
if (ret >= 0) {
44
- assert(qemu_opt_find(opts, BDRV_OPT_CACHE_NO_FLUSH));
36
+ /*
45
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_NO_FLUSH, false)) {
37
+ * Inactivate disks except in COLO, and track that we
46
*flags |= BDRV_O_NO_FLUSH;
38
+ * have done so in order to remember to reactivate
39
+ * them if migration fails or is cancelled.
40
+ */
41
s->block_inactive = !migrate_colo();
42
qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX);
43
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
44
@@ -XXX,XX +XXX,XX @@ static void migration_completion(MigrationState *s)
45
rp_error = await_return_path_close_on_source(s);
46
trace_migration_return_path_end_after(rp_error);
47
if (rp_error) {
48
- goto fail_invalidate;
49
+ goto fail;
50
}
47
}
51
}
48
52
49
- assert(qemu_opt_find(opts, BDRV_OPT_CACHE_DIRECT));
53
if (qemu_file_get_error(s->to_dst_file)) {
50
if (qemu_opt_get_bool_del(opts, BDRV_OPT_CACHE_DIRECT, false)) {
54
trace_migration_completion_file_err();
51
*flags |= BDRV_O_NOCACHE;
55
- goto fail_invalidate;
56
+ goto fail;
52
}
57
}
53
58
54
- assert(qemu_opt_find(opts, BDRV_OPT_READ_ONLY));
59
if (migrate_colo() && s->state == MIGRATION_STATUS_ACTIVE) {
55
if (!qemu_opt_get_bool_del(opts, BDRV_OPT_READ_ONLY, false)) {
60
@@ -XXX,XX +XXX,XX @@ static void migration_completion(MigrationState *s)
56
*flags |= BDRV_O_RDWR;
61
62
return;
63
64
-fail_invalidate:
65
- /* If not doing postcopy, vm_start() will be called: let's regain
66
- * control on images.
67
- */
68
- if (s->state == MIGRATION_STATUS_ACTIVE ||
69
- s->state == MIGRATION_STATUS_DEVICE) {
70
+fail:
71
+ if (s->block_inactive && (s->state == MIGRATION_STATUS_ACTIVE ||
72
+ s->state == MIGRATION_STATUS_DEVICE)) {
73
+ /*
74
+ * If not doing postcopy, vm_start() will be called: let's
75
+ * regain control on images.
76
+ */
77
Error *local_err = NULL;
78
79
qemu_mutex_lock_iothread();
80
bdrv_activate_all(&local_err);
81
if (local_err) {
82
error_report_err(local_err);
83
- s->block_inactive = true;
84
} else {
85
s->block_inactive = false;
86
}
87
qemu_mutex_unlock_iothread();
57
}
88
}
58
89
59
- assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
90
-fail:
60
if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
91
migrate_set_state(&s->state, current_active_state,
61
*flags |= BDRV_O_AUTO_RDONLY;
92
MIGRATION_STATUS_FAILED);
62
}
93
}
63
diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133
64
index XXXXXXX..XXXXXXX 100755
65
--- a/tests/qemu-iotests/133
66
+++ b/tests/qemu-iotests/133
67
@@ -XXX,XX +XXX,XX @@ $QEMU_IO -c 'reopen -w -o read-only=on' $TEST_IMG
68
$QEMU_IO -c 'reopen -c none -o cache.direct=on' $TEST_IMG
69
$QEMU_IO -c 'reopen -c writeback -o cache.direct=on' $TEST_IMG
70
$QEMU_IO -c 'reopen -c directsync -o cache.no-flush=on' $TEST_IMG
71
+
72
+echo
73
+echo "=== Check that invalid options are handled correctly ==="
74
+echo
75
+
76
+$QEMU_IO -c 'reopen -o read-only=foo' $TEST_IMG
77
+$QEMU_IO -c 'reopen -o cache.no-flush=bar' $TEST_IMG
78
+$QEMU_IO -c 'reopen -o cache.direct=baz' $TEST_IMG
79
+$QEMU_IO -c 'reopen -o auto-read-only=qux' $TEST_IMG
80
# success, all done
81
echo "*** done"
82
rm -f $seq.full
83
diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out
84
index XXXXXXX..XXXXXXX 100644
85
--- a/tests/qemu-iotests/133.out
86
+++ b/tests/qemu-iotests/133.out
87
@@ -XXX,XX +XXX,XX @@ Cannot set both -r/-w and 'read-only'
88
Cannot set both -c and the cache options
89
Cannot set both -c and the cache options
90
Cannot set both -c and the cache options
91
+
92
+=== Check that invalid options are handled correctly ===
93
+
94
+Parameter 'read-only' expects 'on' or 'off'
95
+Parameter 'cache.no-flush' expects 'on' or 'off'
96
+Parameter 'cache.direct' expects 'on' or 'off'
97
+Parameter 'auto-read-only' expects 'on' or 'off'
98
*** done
99
--
94
--
100
2.19.2
95
2.40.1
101
102
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
There is a bdrv_co_getlength() now, which should be used in coroutine
2
context.
2
3
3
Allocate buffers locally and release qcow2 lock. Than, reads inside
4
This requires adding GRAPH_RDLOCK to some functions so that this still
4
qcow2_co_preadv_compressed may be done in parallel, however all
5
compiles with TSA because bdrv_co_getlength() is GRAPH_RDLOCK.
5
decompression is still done synchronously. Let's improve it in the
6
following commit.
7
6
8
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20230504115750.54437-2-kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
---
12
block/qcow2.h | 4 ---
13
block/qcow2.h | 4 +++-
13
block/qcow2.c | 96 ++++++++++++++++++++++++++-------------------------
14
block/qcow2-refcount.c | 2 +-
14
2 files changed, 49 insertions(+), 51 deletions(-)
15
block/qcow2.c | 19 +++++++++----------
16
3 files changed, 13 insertions(+), 12 deletions(-)
15
17
16
diff --git a/block/qcow2.h b/block/qcow2.h
18
diff --git a/block/qcow2.h b/block/qcow2.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.h
20
--- a/block/qcow2.h
19
+++ b/block/qcow2.h
21
+++ b/block/qcow2.h
20
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVQcow2State {
22
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
21
QEMUTimer *cache_clean_timer;
23
void *cb_opaque, Error **errp);
22
unsigned cache_clean_interval;
24
int coroutine_fn GRAPH_RDLOCK qcow2_shrink_reftable(BlockDriverState *bs);
23
25
int64_t coroutine_fn qcow2_get_last_cluster(BlockDriverState *bs, int64_t size);
24
- uint8_t *cluster_cache;
26
-int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs);
25
- uint8_t *cluster_data;
27
+
26
- uint64_t cluster_cache_offset;
28
+int coroutine_fn GRAPH_RDLOCK
27
QLIST_HEAD(QCowClusterAlloc, QCowL2Meta) cluster_allocs;
29
+qcow2_detect_metadata_preallocation(BlockDriverState *bs);
28
30
29
uint64_t *refcount_table;
31
/* qcow2-cluster.c functions */
30
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
32
int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
31
bool exact_size);
33
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
32
int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t max_size);
34
index XXXXXXX..XXXXXXX 100644
33
int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index);
35
--- a/block/qcow2-refcount.c
34
-int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
36
+++ b/block/qcow2-refcount.c
35
int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
37
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs)
36
uint8_t *buf, int nb_sectors, bool enc, Error **errp);
38
37
39
qemu_co_mutex_assert_locked(&s->lock);
40
41
- file_length = bdrv_getlength(bs->file->bs);
42
+ file_length = bdrv_co_getlength(bs->file->bs);
43
if (file_length < 0) {
44
return file_length;
45
}
38
diff --git a/block/qcow2.c b/block/qcow2.c
46
diff --git a/block/qcow2.c b/block/qcow2.c
39
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
40
--- a/block/qcow2.c
48
--- a/block/qcow2.c
41
+++ b/block/qcow2.c
49
+++ b/block/qcow2.c
42
@@ -XXX,XX +XXX,XX @@ typedef struct {
50
@@ -XXX,XX +XXX,XX @@ static void qcow2_join_options(QDict *options, QDict *old_options)
43
#define QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x0537be77
44
#define QCOW2_EXT_MAGIC_BITMAPS 0x23852875
45
46
+static int coroutine_fn
47
+qcow2_co_preadv_compressed(BlockDriverState *bs,
48
+ uint64_t file_cluster_offset,
49
+ uint64_t offset,
50
+ uint64_t bytes,
51
+ QEMUIOVector *qiov);
52
+
53
static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
54
{
55
const QCowHeader *cow_header = (const void *)buf;
56
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
57
goto fail;
58
}
51
}
59
60
- s->cluster_cache_offset = -1;
61
s->flags = flags;
62
63
ret = qcow2_refcount_init(bs);
64
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_preadv(BlockDriverState *bs, uint64_t offset,
65
break;
66
67
case QCOW2_CLUSTER_COMPRESSED:
68
- /* add AIO support for compressed blocks ? */
69
- ret = qcow2_decompress_cluster(bs, cluster_offset);
70
+ qemu_co_mutex_unlock(&s->lock);
71
+ ret = qcow2_co_preadv_compressed(bs, cluster_offset,
72
+ offset, cur_bytes,
73
+ &hd_qiov);
74
+ qemu_co_mutex_lock(&s->lock);
75
if (ret < 0) {
76
goto fail;
77
}
78
79
- qemu_iovec_from_buf(&hd_qiov, 0,
80
- s->cluster_cache + offset_in_cluster,
81
- cur_bytes);
82
break;
83
84
case QCOW2_CLUSTER_NORMAL:
85
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int qcow2_co_pwritev(BlockDriverState *bs, uint64_t offset,
86
87
qemu_iovec_init(&hd_qiov, qiov->niov);
88
89
- s->cluster_cache_offset = -1; /* disable compressed cache */
90
-
91
qemu_co_mutex_lock(&s->lock);
92
93
while (bytes != 0) {
94
@@ -XXX,XX +XXX,XX @@ static void qcow2_close(BlockDriverState *bs)
95
g_free(s->image_backing_file);
96
g_free(s->image_backing_format);
97
98
- g_free(s->cluster_cache);
99
- qemu_vfree(s->cluster_data);
100
qcow2_refcount_close(bs);
101
qcow2_free_snapshots(bs);
102
}
52
}
103
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_to(BlockDriverState *bs,
53
104
QCowL2Meta *l2meta = NULL;
54
-static int coroutine_fn qcow2_co_block_status(BlockDriverState *bs,
105
55
- bool want_zero,
106
assert(!bs->encrypted);
56
- int64_t offset, int64_t count,
107
- s->cluster_cache_offset = -1; /* disable compressed cache */
57
- int64_t *pnum, int64_t *map,
108
58
- BlockDriverState **file)
109
qemu_co_mutex_lock(&s->lock);
59
+static int coroutine_fn GRAPH_RDLOCK
110
60
+qcow2_co_block_status(BlockDriverState *bs, bool want_zero, int64_t offset,
111
@@ -XXX,XX +XXX,XX @@ fail:
61
+ int64_t count, int64_t *pnum, int64_t *map,
112
return ret;
62
+ BlockDriverState **file)
113
}
114
115
-int coroutine_fn
116
-qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
117
+static int coroutine_fn
118
+qcow2_co_preadv_compressed(BlockDriverState *bs,
119
+ uint64_t file_cluster_offset,
120
+ uint64_t offset,
121
+ uint64_t bytes,
122
+ QEMUIOVector *qiov)
123
{
63
{
124
BDRVQcow2State *s = bs->opaque;
64
BDRVQcow2State *s = bs->opaque;
125
- int ret, csize, nb_csectors;
65
uint64_t host_offset;
126
+ int ret = 0, csize, nb_csectors;
66
@@ -XXX,XX +XXX,XX @@ preallocate_co(BlockDriverState *bs, uint64_t offset, uint64_t new_length,
127
uint64_t coffset;
67
* all of the allocated clusters (otherwise we get failing reads after
128
+ uint8_t *buf, *out_buf;
68
* EOF). Extend the image to the last allocated sector.
129
struct iovec iov;
69
*/
130
QEMUIOVector local_qiov;
70
- file_length = bdrv_getlength(s->data_file->bs);
131
+ int offset_in_cluster = offset_into_cluster(s, offset);
71
+ file_length = bdrv_co_getlength(s->data_file->bs);
132
72
if (file_length < 0) {
133
- coffset = cluster_offset & s->cluster_offset_mask;
73
error_setg_errno(errp, -file_length, "Could not get file size");
134
- if (s->cluster_cache_offset != coffset) {
74
ret = file_length;
135
- nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
75
@@ -XXX,XX +XXX,XX @@ qcow2_co_copy_range_from(BlockDriverState *bs,
136
- csize = nb_csectors * 512 - (coffset & 511);
76
case QCOW2_SUBCLUSTER_UNALLOCATED_PLAIN:
137
+ coffset = file_cluster_offset & s->cluster_offset_mask;
77
case QCOW2_SUBCLUSTER_UNALLOCATED_ALLOC:
138
+ nb_csectors = ((file_cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
78
if (bs->backing && bs->backing->bs) {
139
+ csize = nb_csectors * 512 - (coffset & 511);
79
- int64_t backing_length = bdrv_getlength(bs->backing->bs);
140
80
+ int64_t backing_length = bdrv_co_getlength(bs->backing->bs);
141
- /* Allocate buffers on first decompress operation, most images are
81
if (src_offset >= backing_length) {
142
- * uncompressed and the memory overhead can be avoided. The buffers
82
cur_write_flags |= BDRV_REQ_ZERO_WRITE;
143
- * are freed in .bdrv_close().
83
} else {
144
- */
84
@@ -XXX,XX +XXX,XX @@ qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
145
- if (!s->cluster_data) {
85
goto fail;
146
- /* one more sector for decompressed data alignment */
86
}
147
- s->cluster_data = qemu_try_blockalign(bs->file->bs,
87
148
- QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size + 512);
88
- old_file_size = bdrv_getlength(bs->file->bs);
149
- if (!s->cluster_data) {
89
+ old_file_size = bdrv_co_getlength(bs->file->bs);
150
- return -ENOMEM;
90
if (old_file_size < 0) {
151
- }
91
error_setg_errno(errp, -old_file_size,
152
- }
92
"Failed to inquire current file length");
153
- if (!s->cluster_cache) {
93
@@ -XXX,XX +XXX,XX @@ qcow2_co_truncate(BlockDriverState *bs, int64_t offset, bool exact,
154
- s->cluster_cache = g_malloc(s->cluster_size);
94
break;
155
- }
95
}
156
+ buf = g_try_malloc(csize);
96
157
+ if (!buf) {
97
- old_file_size = bdrv_getlength(bs->file->bs);
158
+ return -ENOMEM;
98
+ old_file_size = bdrv_co_getlength(bs->file->bs);
159
+ }
99
if (old_file_size < 0) {
160
+ iov.iov_base = buf;
100
error_setg_errno(errp, -old_file_size,
161
+ iov.iov_len = csize;
101
"Failed to inquire current file length");
162
+ qemu_iovec_init_external(&local_qiov, &iov, 1);
102
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed_part(BlockDriverState *bs,
163
103
* align end of file to a sector boundary to ease reading with
164
- iov.iov_base = s->cluster_data;
104
* sector based I/Os
165
- iov.iov_len = csize;
105
*/
166
- qemu_iovec_init_external(&local_qiov, &iov, 1);
106
- int64_t len = bdrv_getlength(bs->file->bs);
167
+ out_buf = qemu_blockalign(bs, s->cluster_size);
107
+ int64_t len = bdrv_co_getlength(bs->file->bs);
168
108
if (len < 0) {
169
- BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
109
return len;
170
- ret = bdrv_co_preadv(bs->file, coffset, csize, &local_qiov, 0);
110
}
171
- if (ret < 0) {
172
- return ret;
173
- }
174
- if (qcow2_decompress(s->cluster_cache, s->cluster_size,
175
- s->cluster_data, csize) < 0) {
176
- return -EIO;
177
- }
178
- s->cluster_cache_offset = coffset;
179
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
180
+ ret = bdrv_co_preadv(bs->file, coffset, csize, &local_qiov, 0);
181
+ if (ret < 0) {
182
+ goto fail;
183
}
184
- return 0;
185
+
186
+ if (qcow2_decompress(out_buf, s->cluster_size, buf, csize) < 0) {
187
+ ret = -EIO;
188
+ goto fail;
189
+ }
190
+
191
+ qemu_iovec_from_buf(qiov, 0, out_buf + offset_in_cluster, bytes);
192
+
193
+fail:
194
+ qemu_vfree(out_buf);
195
+ g_free(buf);
196
+
197
+ return ret;
198
}
199
200
static int make_completely_empty(BlockDriverState *bs)
201
--
111
--
202
2.19.2
112
2.40.1
203
204
diff view generated by jsdifflib
1
aio_worker() for reads and writes isn't boring enough yet. It still does
1
Migration code can call bdrv_activate() in coroutine context, whereas
2
some postprocessing for handling short reads and turning the result into
2
other callers call it outside of coroutines. As it calls other code that
3
the right return value.
3
is not supposed to run in coroutines, standardise on running outside of
4
coroutines.
4
5
5
However, there is no reason why handle_aiocb_rw() couldn't do the same,
6
This adds a no_co_wrapper to switch to the main loop before calling
6
and even without duplicating code between the read and write path. So
7
bdrv_activate().
7
move the code there.
8
8
9
Cc: qemu-stable@nongnu.org
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Message-Id: <20230504115750.54437-3-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
15
---
11
block/file-posix.c | 40 ++++++++++++++++++++--------------------
16
include/block/block-global-state.h | 6 +++++-
12
1 file changed, 20 insertions(+), 20 deletions(-)
17
block/block-backend.c | 10 +++++++++-
18
2 files changed, 14 insertions(+), 2 deletions(-)
13
19
14
diff --git a/block/file-posix.c b/block/file-posix.c
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/block/file-posix.c
22
--- a/include/block/block-global-state.h
17
+++ b/block/file-posix.c
23
+++ b/include/block/block-global-state.h
18
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
24
@@ -XXX,XX +XXX,XX @@ int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
19
* we can just use plain pread/pwrite without any problems.
25
BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs,
20
*/
26
const char *node_name, Error **errp);
21
if (aiocb->io.niov == 1) {
27
22
- return handle_aiocb_rw_linear(aiocb, aiocb->io.iov->iov_base);
28
-int bdrv_activate(BlockDriverState *bs, Error **errp);
23
+ nbytes = handle_aiocb_rw_linear(aiocb, aiocb->io.iov->iov_base);
29
+int no_coroutine_fn bdrv_activate(BlockDriverState *bs, Error **errp);
24
+ goto out;
30
+
25
}
31
+int coroutine_fn no_co_wrapper
26
/*
32
+bdrv_co_activate(BlockDriverState *bs, Error **errp);
27
* We have more than one iovec, and all are properly aligned.
33
+
28
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
34
void bdrv_activate_all(Error **errp);
29
nbytes = handle_aiocb_rw_vector(aiocb);
35
int bdrv_inactivate_all(void);
30
if (nbytes == aiocb->aio_nbytes ||
36
31
(nbytes < 0 && nbytes != -ENOSYS)) {
37
diff --git a/block/block-backend.c b/block/block-backend.c
32
- return nbytes;
38
index XXXXXXX..XXXXXXX 100644
33
+ goto out;
39
--- a/block/block-backend.c
34
}
40
+++ b/block/block-backend.c
35
preadv_present = false;
41
@@ -XXX,XX +XXX,XX @@ void blk_activate(BlockBackend *blk, Error **errp)
36
}
42
return;
37
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
38
*/
39
buf = qemu_try_blockalign(aiocb->bs, aiocb->aio_nbytes);
40
if (buf == NULL) {
41
- return -ENOMEM;
42
+ nbytes = -ENOMEM;
43
+ goto out;
44
}
43
}
45
44
46
if (aiocb->aio_type & QEMU_AIO_WRITE) {
45
- bdrv_activate(bs, errp);
47
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
46
+ /*
48
}
47
+ * Migration code can call this function in coroutine context, so leave
49
qemu_vfree(buf);
48
+ * coroutine context if necessary.
50
49
+ */
51
- return nbytes;
50
+ if (qemu_in_coroutine()) {
52
+out:
51
+ bdrv_co_activate(bs, errp);
53
+ if (nbytes == aiocb->aio_nbytes) {
54
+ return 0;
55
+ } else if (nbytes >= 0 && nbytes < aiocb->aio_nbytes) {
56
+ if (aiocb->aio_type & QEMU_AIO_WRITE) {
57
+ return -EINVAL;
58
+ } else {
59
+ iov_memset(aiocb->io.iov, aiocb->io.niov, nbytes,
60
+ 0, aiocb->aio_nbytes - nbytes);
61
+ return 0;
62
+ }
63
+ } else {
52
+ } else {
64
+ assert(nbytes < 0);
53
+ bdrv_activate(bs, errp);
65
+ return nbytes;
66
+ }
54
+ }
67
}
55
}
68
56
69
#ifdef CONFIG_XFS
57
bool coroutine_fn blk_co_is_inserted(BlockBackend *blk)
70
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
71
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
72
case QEMU_AIO_READ:
73
ret = handle_aiocb_rw(aiocb);
74
- if (ret >= 0 && ret < aiocb->aio_nbytes) {
75
- iov_memset(aiocb->io.iov, aiocb->io.niov, ret,
76
- 0, aiocb->aio_nbytes - ret);
77
-
78
- ret = aiocb->aio_nbytes;
79
- }
80
- if (ret == aiocb->aio_nbytes) {
81
- ret = 0;
82
- } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
83
- ret = -EINVAL;
84
- }
85
break;
86
case QEMU_AIO_WRITE:
87
ret = handle_aiocb_rw(aiocb);
88
- if (ret == aiocb->aio_nbytes) {
89
- ret = 0;
90
- } else if (ret >= 0 && ret < aiocb->aio_nbytes) {
91
- ret = -EINVAL;
92
- }
93
break;
94
case QEMU_AIO_IOCTL:
95
ret = handle_aiocb_ioctl(aiocb);
96
--
58
--
97
2.19.2
59
2.40.1
98
99
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
These functions must not be called in coroutine context, because they
2
need write access to the graph.
2
3
3
Use appropriate macro, corresponding to deflateInit2 spec.
4
Cc: qemu-stable@nongnu.org
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
6
Reviewed-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20230504115750.54437-4-kwolf@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
10
---
9
block/qcow2.c | 2 +-
11
include/block/block-global-state.h | 3 ++-
10
1 file changed, 1 insertion(+), 1 deletion(-)
12
include/sysemu/block-backend-global-state.h | 5 ++++-
13
block.c | 2 +-
14
block/crypto.c | 6 +++---
15
block/parallels.c | 6 +++---
16
block/qcow.c | 6 +++---
17
block/qcow2.c | 14 +++++++-------
18
block/qed.c | 6 +++---
19
block/vdi.c | 6 +++---
20
block/vhdx.c | 6 +++---
21
block/vmdk.c | 18 +++++++++---------
22
block/vpc.c | 6 +++---
23
12 files changed, 44 insertions(+), 40 deletions(-)
11
24
25
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/block/block-global-state.h
28
+++ b/include/block/block-global-state.h
29
@@ -XXX,XX +XXX,XX @@ void bdrv_img_create(const char *filename, const char *fmt,
30
bool quiet, Error **errp);
31
32
void bdrv_ref(BlockDriverState *bs);
33
-void bdrv_unref(BlockDriverState *bs);
34
+void no_coroutine_fn bdrv_unref(BlockDriverState *bs);
35
+void coroutine_fn no_co_wrapper bdrv_co_unref(BlockDriverState *bs);
36
void bdrv_unref_child(BlockDriverState *parent, BdrvChild *child);
37
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
38
BlockDriverState *child_bs,
39
diff --git a/include/sysemu/block-backend-global-state.h b/include/sysemu/block-backend-global-state.h
40
index XXXXXXX..XXXXXXX 100644
41
--- a/include/sysemu/block-backend-global-state.h
42
+++ b/include/sysemu/block-backend-global-state.h
43
@@ -XXX,XX +XXX,XX @@ blk_co_new_open(const char *filename, const char *reference, QDict *options,
44
45
int blk_get_refcnt(BlockBackend *blk);
46
void blk_ref(BlockBackend *blk);
47
-void blk_unref(BlockBackend *blk);
48
+
49
+void no_coroutine_fn blk_unref(BlockBackend *blk);
50
+void coroutine_fn no_co_wrapper blk_co_unref(BlockBackend *blk);
51
+
52
void blk_remove_all_bs(void);
53
BlockBackend *blk_by_name(const char *name);
54
BlockBackend *blk_next(BlockBackend *blk);
55
diff --git a/block.c b/block.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/block.c
58
+++ b/block.c
59
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_create_opts_simple(BlockDriver *drv,
60
61
ret = 0;
62
out:
63
- blk_unref(blk);
64
+ blk_co_unref(blk);
65
return ret;
66
}
67
68
diff --git a/block/crypto.c b/block/crypto.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/crypto.c
71
+++ b/block/crypto.c
72
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
73
ret = 0;
74
cleanup:
75
qcrypto_block_free(crypto);
76
- blk_unref(blk);
77
+ blk_co_unref(blk);
78
return ret;
79
}
80
81
@@ -XXX,XX +XXX,XX @@ block_crypto_co_create_luks(BlockdevCreateOptions *create_options, Error **errp)
82
83
ret = 0;
84
fail:
85
- bdrv_unref(bs);
86
+ bdrv_co_unref(bs);
87
return ret;
88
}
89
90
@@ -XXX,XX +XXX,XX @@ fail:
91
bdrv_co_delete_file_noerr(bs);
92
}
93
94
- bdrv_unref(bs);
95
+ bdrv_co_unref(bs);
96
qapi_free_QCryptoBlockCreateOptions(create_opts);
97
qobject_unref(cryptoopts);
98
return ret;
99
diff --git a/block/parallels.c b/block/parallels.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/block/parallels.c
102
+++ b/block/parallels.c
103
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
104
105
ret = 0;
106
out:
107
- blk_unref(blk);
108
- bdrv_unref(bs);
109
+ blk_co_unref(blk);
110
+ bdrv_co_unref(bs);
111
return ret;
112
113
exit:
114
@@ -XXX,XX +XXX,XX @@ parallels_co_create_opts(BlockDriver *drv, const char *filename,
115
116
done:
117
qobject_unref(qdict);
118
- bdrv_unref(bs);
119
+ bdrv_co_unref(bs);
120
qapi_free_BlockdevCreateOptions(create_options);
121
return ret;
122
}
123
diff --git a/block/qcow.c b/block/qcow.c
124
index XXXXXXX..XXXXXXX 100644
125
--- a/block/qcow.c
126
+++ b/block/qcow.c
127
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
128
g_free(tmp);
129
ret = 0;
130
exit:
131
- blk_unref(qcow_blk);
132
- bdrv_unref(bs);
133
+ blk_co_unref(qcow_blk);
134
+ bdrv_co_unref(bs);
135
qcrypto_block_free(crypto);
136
return ret;
137
}
138
@@ -XXX,XX +XXX,XX @@ qcow_co_create_opts(BlockDriver *drv, const char *filename,
139
fail:
140
g_free(backing_fmt);
141
qobject_unref(qdict);
142
- bdrv_unref(bs);
143
+ bdrv_co_unref(bs);
144
qapi_free_BlockdevCreateOptions(create_options);
145
return ret;
146
}
12
diff --git a/block/qcow2.c b/block/qcow2.c
147
diff --git a/block/qcow2.c b/block/qcow2.c
13
index XXXXXXX..XXXXXXX 100644
148
index XXXXXXX..XXXXXXX 100644
14
--- a/block/qcow2.c
149
--- a/block/qcow2.c
15
+++ b/block/qcow2.c
150
+++ b/block/qcow2.c
16
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, const void *src, size_t size)
151
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
17
memset(&strm, 0, sizeof(strm));
152
goto out;
18
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
153
}
19
-12, 9, Z_DEFAULT_STRATEGY);
154
20
- if (ret != 0) {
155
- blk_unref(blk);
21
+ if (ret != Z_OK) {
156
+ blk_co_unref(blk);
22
return -2;
157
blk = NULL;
23
}
158
24
159
/*
160
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
161
}
162
}
163
164
- blk_unref(blk);
165
+ blk_co_unref(blk);
166
blk = NULL;
167
168
/* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning.
169
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
170
171
ret = 0;
172
out:
173
- blk_unref(blk);
174
- bdrv_unref(bs);
175
- bdrv_unref(data_bs);
176
+ blk_co_unref(blk);
177
+ bdrv_co_unref(bs);
178
+ bdrv_co_unref(data_bs);
179
return ret;
180
}
181
182
@@ -XXX,XX +XXX,XX @@ finish:
183
}
184
185
qobject_unref(qdict);
186
- bdrv_unref(bs);
187
- bdrv_unref(data_bs);
188
+ bdrv_co_unref(bs);
189
+ bdrv_co_unref(data_bs);
190
qapi_free_BlockdevCreateOptions(create_options);
191
return ret;
192
}
193
diff --git a/block/qed.c b/block/qed.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/block/qed.c
196
+++ b/block/qed.c
197
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
198
ret = 0; /* success */
199
out:
200
g_free(l1_table);
201
- blk_unref(blk);
202
- bdrv_unref(bs);
203
+ blk_co_unref(blk);
204
+ bdrv_co_unref(bs);
205
return ret;
206
}
207
208
@@ -XXX,XX +XXX,XX @@ bdrv_qed_co_create_opts(BlockDriver *drv, const char *filename,
209
210
fail:
211
qobject_unref(qdict);
212
- bdrv_unref(bs);
213
+ bdrv_co_unref(bs);
214
qapi_free_BlockdevCreateOptions(create_options);
215
return ret;
216
}
217
diff --git a/block/vdi.c b/block/vdi.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/vdi.c
220
+++ b/block/vdi.c
221
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
222
223
ret = 0;
224
exit:
225
- blk_unref(blk);
226
- bdrv_unref(bs_file);
227
+ blk_co_unref(blk);
228
+ bdrv_co_unref(bs_file);
229
g_free(bmap);
230
return ret;
231
}
232
@@ -XXX,XX +XXX,XX @@ vdi_co_create_opts(BlockDriver *drv, const char *filename,
233
done:
234
qobject_unref(qdict);
235
qapi_free_BlockdevCreateOptions(create_options);
236
- bdrv_unref(bs_file);
237
+ bdrv_co_unref(bs_file);
238
return ret;
239
}
240
241
diff --git a/block/vhdx.c b/block/vhdx.c
242
index XXXXXXX..XXXXXXX 100644
243
--- a/block/vhdx.c
244
+++ b/block/vhdx.c
245
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
246
247
ret = 0;
248
delete_and_exit:
249
- blk_unref(blk);
250
- bdrv_unref(bs);
251
+ blk_co_unref(blk);
252
+ bdrv_co_unref(bs);
253
g_free(creator);
254
return ret;
255
}
256
@@ -XXX,XX +XXX,XX @@ vhdx_co_create_opts(BlockDriver *drv, const char *filename,
257
258
fail:
259
qobject_unref(qdict);
260
- bdrv_unref(bs);
261
+ bdrv_co_unref(bs);
262
qapi_free_BlockdevCreateOptions(create_options);
263
return ret;
264
}
265
diff --git a/block/vmdk.c b/block/vmdk.c
266
index XXXXXXX..XXXXXXX 100644
267
--- a/block/vmdk.c
268
+++ b/block/vmdk.c
269
@@ -XXX,XX +XXX,XX @@ exit:
270
if (pbb) {
271
*pbb = blk;
272
} else {
273
- blk_unref(blk);
274
+ blk_co_unref(blk);
275
blk = NULL;
276
}
277
}
278
@@ -XXX,XX +XXX,XX @@ vmdk_co_do_create(int64_t size,
279
if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) {
280
error_setg(errp, "Invalid backing file format: %s. Must be vmdk",
281
blk_bs(backing)->drv->format_name);
282
- blk_unref(backing);
283
+ blk_co_unref(backing);
284
ret = -EINVAL;
285
goto exit;
286
}
287
ret = vmdk_read_cid(blk_bs(backing), 0, &parent_cid);
288
- blk_unref(backing);
289
+ blk_co_unref(backing);
290
if (ret) {
291
error_setg(errp, "Failed to read parent CID");
292
goto exit;
293
@@ -XXX,XX +XXX,XX @@ vmdk_co_do_create(int64_t size,
294
blk_bs(extent_blk)->filename);
295
created_size += cur_size;
296
extent_idx++;
297
- blk_unref(extent_blk);
298
+ blk_co_unref(extent_blk);
299
}
300
301
/* Check whether we got excess extents */
302
extent_blk = extent_fn(-1, extent_idx, flat, split, compress, zeroed_grain,
303
opaque, NULL);
304
if (extent_blk) {
305
- blk_unref(extent_blk);
306
+ blk_co_unref(extent_blk);
307
error_setg(errp, "List of extents contains unused extents");
308
ret = -EINVAL;
309
goto exit;
310
@@ -XXX,XX +XXX,XX @@ vmdk_co_do_create(int64_t size,
311
ret = 0;
312
exit:
313
if (blk) {
314
- blk_unref(blk);
315
+ blk_co_unref(blk);
316
}
317
g_free(desc);
318
g_free(parent_desc_line);
319
@@ -XXX,XX +XXX,XX @@ vmdk_co_create_opts_cb(int64_t size, int idx, bool flat, bool split,
320
errp)) {
321
goto exit;
322
}
323
- bdrv_unref(bs);
324
+ bdrv_co_unref(bs);
325
exit:
326
g_free(ext_filename);
327
return blk;
328
@@ -XXX,XX +XXX,XX @@ static BlockBackend * coroutine_fn vmdk_co_create_cb(int64_t size, int idx,
329
return NULL;
330
}
331
blk_set_allow_write_beyond_eof(blk, true);
332
- bdrv_unref(bs);
333
+ bdrv_co_unref(bs);
334
335
if (size != -1) {
336
ret = vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp);
337
if (ret) {
338
- blk_unref(blk);
339
+ blk_co_unref(blk);
340
blk = NULL;
341
}
342
}
343
diff --git a/block/vpc.c b/block/vpc.c
344
index XXXXXXX..XXXXXXX 100644
345
--- a/block/vpc.c
346
+++ b/block/vpc.c
347
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vpc_co_create(BlockdevCreateOptions *opts,
348
}
349
350
out:
351
- blk_unref(blk);
352
- bdrv_unref(bs);
353
+ blk_co_unref(blk);
354
+ bdrv_co_unref(bs);
355
return ret;
356
}
357
358
@@ -XXX,XX +XXX,XX @@ vpc_co_create_opts(BlockDriver *drv, const char *filename,
359
360
fail:
361
qobject_unref(qdict);
362
- bdrv_unref(bs);
363
+ bdrv_co_unref(bs);
364
qapi_free_BlockdevCreateOptions(create_options);
365
return ret;
366
}
25
--
367
--
26
2.19.2
368
2.40.1
27
28
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This QMP handler runs in a coroutine, so it must use the corresponding
2
no_co_wrappers instead.
2
3
3
This patch replaces the bdrv_reopen() calls that set and remove the
4
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2185688
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
5
Cc: qemu-stable@nongnu.org
5
6
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-Id: <20230504115750.54437-5-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
11
---
10
blockdev.c | 8 ++------
12
blockdev.c | 4 ++--
11
1 file changed, 2 insertions(+), 6 deletions(-)
13
1 file changed, 2 insertions(+), 2 deletions(-)
12
14
13
diff --git a/blockdev.c b/blockdev.c
15
diff --git a/blockdev.c b/blockdev.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/blockdev.c
17
--- a/blockdev.c
16
+++ b/blockdev.c
18
+++ b/blockdev.c
17
@@ -XXX,XX +XXX,XX @@ void qmp_change_backing_file(const char *device,
19
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
18
BlockDriverState *image_bs = NULL;
20
return;
19
Error *local_err = NULL;
20
bool ro;
21
- int open_flags;
22
int ret;
23
24
bs = qmp_get_root_bs(device, errp);
25
@@ -XXX,XX +XXX,XX @@ void qmp_change_backing_file(const char *device,
26
}
21
}
27
22
28
/* if not r/w, reopen to make r/w */
23
- blk = blk_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
29
- open_flags = image_bs->open_flags;
24
+ blk = blk_co_new_with_bs(bs, BLK_PERM_RESIZE, BLK_PERM_ALL, errp);
30
ro = bdrv_is_read_only(image_bs);
25
if (!blk) {
31
26
return;
32
if (ro) {
33
- bdrv_reopen(image_bs, open_flags | BDRV_O_RDWR, &local_err);
34
- if (local_err) {
35
- error_propagate(errp, local_err);
36
+ if (bdrv_reopen_set_read_only(image_bs, false, errp) != 0) {
37
goto out;
38
}
39
}
27
}
40
@@ -XXX,XX +XXX,XX @@ void qmp_change_backing_file(const char *device,
28
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
41
}
29
42
30
bdrv_co_lock(bs);
43
if (ro) {
31
bdrv_drained_end(bs);
44
- bdrv_reopen(image_bs, open_flags, &local_err);
32
- blk_unref(blk);
45
+ bdrv_reopen_set_read_only(image_bs, true, &local_err);
33
+ blk_co_unref(blk);
46
error_propagate(errp, local_err);
34
bdrv_co_unlock(bs);
47
}
35
}
48
36
49
--
37
--
50
2.19.2
38
2.40.1
51
52
diff view generated by jsdifflib
1
From: Julio Faracco <jcfaracco@gmail.com>
1
This tests that trying to resize an image with QMP block_resize doesn't
2
hang or otherwise fail when the image is attached to a device running in
3
an iothread.
2
4
3
QEMU dmg support includes zlib and bzip2, but it does not contains lzfse
5
This is a regression test for the recent fix that changed
4
support. This commit adds the source file to extend compression support
6
qmp_block_resize, which is a coroutine based QMP handler, to avoid
5
for new DMGs.
7
calling no_coroutine_fns directly.
6
8
7
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
Message-Id: <20230509134133.373408-1-kwolf@redhat.com>
11
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
block/dmg-lzfse.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
14
tests/qemu-iotests/tests/iothreads-resize | 71 +++++++++++++++++++
11
1 file changed, 49 insertions(+)
15
tests/qemu-iotests/tests/iothreads-resize.out | 11 +++
12
create mode 100644 block/dmg-lzfse.c
16
2 files changed, 82 insertions(+)
17
create mode 100755 tests/qemu-iotests/tests/iothreads-resize
18
create mode 100644 tests/qemu-iotests/tests/iothreads-resize.out
13
19
14
diff --git a/block/dmg-lzfse.c b/block/dmg-lzfse.c
20
diff --git a/tests/qemu-iotests/tests/iothreads-resize b/tests/qemu-iotests/tests/iothreads-resize
21
new file mode 100755
22
index XXXXXXX..XXXXXXX
23
--- /dev/null
24
+++ b/tests/qemu-iotests/tests/iothreads-resize
25
@@ -XXX,XX +XXX,XX @@
26
+#!/usr/bin/env bash
27
+# group: rw auto quick
28
+#
29
+# Test resizing an image that is attached to a separate iothread
30
+#
31
+# Copyright (C) 2023 Red Hat, Inc.
32
+#
33
+# This program is free software; you can redistribute it and/or modify
34
+# it under the terms of the GNU General Public License as published by
35
+# the Free Software Foundation; either version 2 of the License, or
36
+# (at your option) any later version.
37
+#
38
+# This program is distributed in the hope that it will be useful,
39
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
+# GNU General Public License for more details.
42
+#
43
+# You should have received a copy of the GNU General Public License
44
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
45
+#
46
+
47
+# creator
48
+owner=kwolf@redhat.com
49
+
50
+seq=`basename $0`
51
+echo "QA output created by $seq"
52
+
53
+status=1 # failure is the default!
54
+
55
+_cleanup()
56
+{
57
+ _cleanup_test_img
58
+}
59
+trap "_cleanup; exit \$status" 0 1 2 3 15
60
+
61
+# get standard environment, filters and checks
62
+cd ..
63
+. ./common.rc
64
+. ./common.filter
65
+
66
+# Resizing images is only supported by a few block drivers
67
+_supported_fmt raw qcow2 qed
68
+_supported_proto file
69
+_require_devices virtio-scsi-pci
70
+
71
+size=64M
72
+_make_test_img $size
73
+
74
+qmp() {
75
+cat <<EOF
76
+{"execute":"qmp_capabilities"}
77
+{'execute': 'block_resize',
78
+ 'arguments': {'node-name': 'img', 'size': 134217728}}
79
+{"execute":"quit"}
80
+EOF
81
+}
82
+
83
+qmp | $QEMU -S -display none \
84
+ -drive if=none,format=$IMGFMT,file="$TEST_IMG",node-name=img \
85
+ -object iothread,id=t0 \
86
+ -device virtio-scsi-pci,iothread=t0 \
87
+ -device scsi-hd,drive=none0 \
88
+ -qmp stdio \
89
+ | _filter_qmp
90
+
91
+_img_info | _filter_img_info
92
+
93
+# success, all done
94
+echo "*** done"
95
+rm -f $seq.full
96
+status=0
97
diff --git a/tests/qemu-iotests/tests/iothreads-resize.out b/tests/qemu-iotests/tests/iothreads-resize.out
15
new file mode 100644
98
new file mode 100644
16
index XXXXXXX..XXXXXXX
99
index XXXXXXX..XXXXXXX
17
--- /dev/null
100
--- /dev/null
18
+++ b/block/dmg-lzfse.c
101
+++ b/tests/qemu-iotests/tests/iothreads-resize.out
19
@@ -XXX,XX +XXX,XX @@
102
@@ -XXX,XX +XXX,XX @@
20
+/*
103
+QA output created by iothreads-resize
21
+ * DMG lzfse uncompression
104
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
22
+ *
105
+QMP_VERSION
23
+ * Copyright (c) 2018 Julio Cesar Faracco
106
+{"return": {}}
24
+ *
107
+{"return": {}}
25
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
108
+{"return": {}}
26
+ * of this software and associated documentation files (the "Software"), to deal
109
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false, "reason": "host-qmp-quit"}}
27
+ * in the Software without restriction, including without limitation the rights
110
+image: TEST_DIR/t.IMGFMT
28
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
111
+file format: IMGFMT
29
+ * copies of the Software, and to permit persons to whom the Software is
112
+virtual size: 128 MiB (134217728 bytes)
30
+ * furnished to do so, subject to the following conditions:
113
+*** done
31
+ *
32
+ * The above copyright notice and this permission notice shall be included in
33
+ * all copies or substantial portions of the Software.
34
+ *
35
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
38
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41
+ * THE SOFTWARE.
42
+ */
43
+#include "qemu/osdep.h"
44
+#include "qemu-common.h"
45
+#include "dmg.h"
46
+#include <lzfse.h>
47
+
48
+static int dmg_uncompress_lzfse_do(char *next_in, unsigned int avail_in,
49
+ char *next_out, unsigned int avail_out)
50
+{
51
+ size_t out_size = lzfse_decode_buffer((uint8_t *) next_out, avail_out,
52
+ (uint8_t *) next_in, avail_in,
53
+ NULL);
54
+
55
+ /* We need to decode the single chunk only. */
56
+ /* So, out_size == avail_out is not an error here. */
57
+ if (out_size > 0) {
58
+ return out_size;
59
+ }
60
+ return -1;
61
+}
62
+
63
+__attribute__((constructor))
64
+static void dmg_lzfse_init(void)
65
+{
66
+ assert(!dmg_uncompress_lzfse);
67
+ dmg_uncompress_lzfse = dmg_uncompress_lzfse_do;
68
+}
69
--
114
--
70
2.19.2
115
2.40.1
71
72
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
test-bdrv-drain contains a few test cases that are run both in coroutine
2
and non-coroutine context. Running the entire code including the setup
3
and shutdown in coroutines is incorrect because graph modifications can
4
generally not happen in coroutines.
2
5
3
This function is used to put the hidden and secondary disks in
6
Change the test so that creating and destroying the test nodes and
4
read-write mode before launching the backup job, and back in read-only
7
BlockBackends always happens outside of coroutine context.
5
mode afterwards.
6
8
7
This patch does the following changes:
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
10
Reviewed-by: Eric Blake <eblake@redhat.com>
9
- Use an options QDict with the "read-only" option instead of
11
Message-Id: <20230504115750.54437-6-kwolf@redhat.com>
10
passing the changes as flags only.
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
12
- Simplify the code (it was unnecessarily complicated and verbose).
13
14
- Fix a bug due to which the secondary disk was not being put back
15
in read-only mode when writable=false (because in this case
16
orig_secondary_flags always had the BDRV_O_RDWR flag set).
17
18
- Stop clearing the BDRV_O_INACTIVE flag.
19
20
The flags parameter to bdrv_reopen_queue() becomes redundant and we'll
21
be able to get rid of it in a subsequent patch.
22
23
Signed-off-by: Alberto Garcia <berto@igalia.com>
24
Reviewed-by: Max Reitz <mreitz@redhat.com>
25
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
26
---
14
---
27
block/replication.c | 45 +++++++++++++++++++++------------------------
15
tests/unit/test-bdrv-drain.c | 112 +++++++++++++++++++++++------------
28
1 file changed, 21 insertions(+), 24 deletions(-)
16
1 file changed, 75 insertions(+), 37 deletions(-)
29
17
30
diff --git a/block/replication.c b/block/replication.c
18
diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c
31
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
32
--- a/block/replication.c
20
--- a/tests/unit/test-bdrv-drain.c
33
+++ b/block/replication.c
21
+++ b/tests/unit/test-bdrv-drain.c
34
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static void do_drain_begin_unlocked(enum drain_type drain_type, BlockDriverState
35
#include "block/block_backup.h"
36
#include "sysemu/block-backend.h"
37
#include "qapi/error.h"
38
+#include "qapi/qmp/qdict.h"
39
#include "replication.h"
40
41
typedef enum {
42
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVReplicationState {
43
char *top_id;
44
ReplicationState *rs;
45
Error *blocker;
46
- int orig_hidden_flags;
47
- int orig_secondary_flags;
48
+ bool orig_hidden_read_only;
49
+ bool orig_secondary_read_only;
50
int error;
51
} BDRVReplicationState;
52
53
@@ -XXX,XX +XXX,XX @@ static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
54
}
23
}
55
}
24
}
56
25
57
+/* This function is supposed to be called twice:
26
+static BlockBackend * no_coroutine_fn test_setup(void)
58
+ * first with writable = true, then with writable = false.
27
+{
59
+ * The first call puts s->hidden_disk and s->secondary_disk in
28
+ BlockBackend *blk;
60
+ * r/w mode, and the second puts them back in their original state.
29
+ BlockDriverState *bs, *backing;
61
+ */
30
+
62
static void reopen_backing_file(BlockDriverState *bs, bool writable,
31
+ blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
63
Error **errp)
32
+ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
64
{
33
+ &error_abort);
65
BDRVReplicationState *s = bs->opaque;
34
+ blk_insert_bs(blk, bs, &error_abort);
66
BlockReopenQueue *reopen_queue = NULL;
35
+
67
- int orig_hidden_flags, orig_secondary_flags;
36
+ backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
68
- int new_hidden_flags, new_secondary_flags;
37
+ bdrv_set_backing_hd(bs, backing, &error_abort);
69
Error *local_err = NULL;
38
+
70
39
+ bdrv_unref(backing);
71
if (writable) {
40
+ bdrv_unref(bs);
72
- orig_hidden_flags = s->orig_hidden_flags =
41
+
73
- bdrv_get_flags(s->hidden_disk->bs);
42
+ return blk;
74
- new_hidden_flags = (orig_hidden_flags | BDRV_O_RDWR) &
43
+}
75
- ~BDRV_O_INACTIVE;
44
+
76
- orig_secondary_flags = s->orig_secondary_flags =
45
static void do_drain_end_unlocked(enum drain_type drain_type, BlockDriverState *bs)
77
- bdrv_get_flags(s->secondary_disk->bs);
46
{
78
- new_secondary_flags = (orig_secondary_flags | BDRV_O_RDWR) &
47
if (drain_type != BDRV_DRAIN_ALL) {
79
- ~BDRV_O_INACTIVE;
48
@@ -XXX,XX +XXX,XX @@ static void do_drain_end_unlocked(enum drain_type drain_type, BlockDriverState *
80
- } else {
81
- orig_hidden_flags = (s->orig_hidden_flags | BDRV_O_RDWR) &
82
- ~BDRV_O_INACTIVE;
83
- new_hidden_flags = s->orig_hidden_flags;
84
- orig_secondary_flags = (s->orig_secondary_flags | BDRV_O_RDWR) &
85
- ~BDRV_O_INACTIVE;
86
- new_secondary_flags = s->orig_secondary_flags;
87
+ s->orig_hidden_read_only = bdrv_is_read_only(s->hidden_disk->bs);
88
+ s->orig_secondary_read_only = bdrv_is_read_only(s->secondary_disk->bs);
89
}
49
}
90
50
}
91
bdrv_subtree_drained_begin(s->hidden_disk->bs);
51
92
bdrv_subtree_drained_begin(s->secondary_disk->bs);
52
-static void test_drv_cb_common(enum drain_type drain_type, bool recursive)
93
53
+static void test_drv_cb_common(BlockBackend *blk, enum drain_type drain_type,
94
- if (orig_hidden_flags != new_hidden_flags) {
54
+ bool recursive)
95
- reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
55
{
96
- new_hidden_flags);
56
- BlockBackend *blk;
97
+ if (s->orig_hidden_read_only) {
57
- BlockDriverState *bs, *backing;
98
+ int flags = bdrv_get_flags(s->hidden_disk->bs);
58
+ BlockDriverState *bs = blk_bs(blk);
99
+ QDict *opts = qdict_new();
59
+ BlockDriverState *backing = bs->backing->bs;
100
+ qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
60
BDRVTestState *s, *backing_s;
101
+ reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
61
BlockAIOCB *acb;
102
+ opts, flags);
62
int aio_ret;
103
}
63
104
64
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, NULL, 0);
105
- if (!(orig_secondary_flags & BDRV_O_RDWR)) {
65
106
+ if (s->orig_secondary_read_only) {
66
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
107
+ int flags = bdrv_get_flags(s->secondary_disk->bs);
67
- bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
108
+ QDict *opts = qdict_new();
68
- &error_abort);
109
+ qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
69
s = bs->opaque;
110
reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
70
- blk_insert_bs(blk, bs, &error_abort);
111
- NULL, new_secondary_flags);
71
-
112
+ opts, flags);
72
- backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
113
}
73
backing_s = backing->opaque;
114
74
- bdrv_set_backing_hd(bs, backing, &error_abort);
115
if (reopen_queue) {
75
76
/* Simple bdrv_drain_all_begin/end pair, check that CBs are called */
77
g_assert_cmpint(s->drain_count, ==, 0);
78
@@ -XXX,XX +XXX,XX @@ static void test_drv_cb_common(enum drain_type drain_type, bool recursive)
79
80
g_assert_cmpint(s->drain_count, ==, 0);
81
g_assert_cmpint(backing_s->drain_count, ==, 0);
82
-
83
- bdrv_unref(backing);
84
- bdrv_unref(bs);
85
- blk_unref(blk);
86
}
87
88
static void test_drv_cb_drain_all(void)
89
{
90
- test_drv_cb_common(BDRV_DRAIN_ALL, true);
91
+ BlockBackend *blk = test_setup();
92
+ test_drv_cb_common(blk, BDRV_DRAIN_ALL, true);
93
+ blk_unref(blk);
94
}
95
96
static void test_drv_cb_drain(void)
97
{
98
- test_drv_cb_common(BDRV_DRAIN, false);
99
+ BlockBackend *blk = test_setup();
100
+ test_drv_cb_common(blk, BDRV_DRAIN, false);
101
+ blk_unref(blk);
102
+}
103
+
104
+static void coroutine_fn test_drv_cb_co_drain_all_entry(void)
105
+{
106
+ BlockBackend *blk = blk_all_next(NULL);
107
+ test_drv_cb_common(blk, BDRV_DRAIN_ALL, true);
108
}
109
110
static void test_drv_cb_co_drain_all(void)
111
{
112
- call_in_coroutine(test_drv_cb_drain_all);
113
+ BlockBackend *blk = test_setup();
114
+ call_in_coroutine(test_drv_cb_co_drain_all_entry);
115
+ blk_unref(blk);
116
}
117
118
-static void test_drv_cb_co_drain(void)
119
+static void coroutine_fn test_drv_cb_co_drain_entry(void)
120
{
121
- call_in_coroutine(test_drv_cb_drain);
122
+ BlockBackend *blk = blk_all_next(NULL);
123
+ test_drv_cb_common(blk, BDRV_DRAIN, false);
124
}
125
126
-static void test_quiesce_common(enum drain_type drain_type, bool recursive)
127
+static void test_drv_cb_co_drain(void)
128
{
129
- BlockBackend *blk;
130
- BlockDriverState *bs, *backing;
131
-
132
- blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL);
133
- bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR,
134
- &error_abort);
135
- blk_insert_bs(blk, bs, &error_abort);
136
+ BlockBackend *blk = test_setup();
137
+ call_in_coroutine(test_drv_cb_co_drain_entry);
138
+ blk_unref(blk);
139
+}
140
141
- backing = bdrv_new_open_driver(&bdrv_test, "backing", 0, &error_abort);
142
- bdrv_set_backing_hd(bs, backing, &error_abort);
143
+static void test_quiesce_common(BlockBackend *blk, enum drain_type drain_type,
144
+ bool recursive)
145
+{
146
+ BlockDriverState *bs = blk_bs(blk);
147
+ BlockDriverState *backing = bs->backing->bs;
148
149
g_assert_cmpint(bs->quiesce_counter, ==, 0);
150
g_assert_cmpint(backing->quiesce_counter, ==, 0);
151
@@ -XXX,XX +XXX,XX @@ static void test_quiesce_common(enum drain_type drain_type, bool recursive)
152
153
g_assert_cmpint(bs->quiesce_counter, ==, 0);
154
g_assert_cmpint(backing->quiesce_counter, ==, 0);
155
-
156
- bdrv_unref(backing);
157
- bdrv_unref(bs);
158
- blk_unref(blk);
159
}
160
161
static void test_quiesce_drain_all(void)
162
{
163
- test_quiesce_common(BDRV_DRAIN_ALL, true);
164
+ BlockBackend *blk = test_setup();
165
+ test_quiesce_common(blk, BDRV_DRAIN_ALL, true);
166
+ blk_unref(blk);
167
}
168
169
static void test_quiesce_drain(void)
170
{
171
- test_quiesce_common(BDRV_DRAIN, false);
172
+ BlockBackend *blk = test_setup();
173
+ test_quiesce_common(blk, BDRV_DRAIN, false);
174
+ blk_unref(blk);
175
+}
176
+
177
+static void coroutine_fn test_quiesce_co_drain_all_entry(void)
178
+{
179
+ BlockBackend *blk = blk_all_next(NULL);
180
+ test_quiesce_common(blk, BDRV_DRAIN_ALL, true);
181
}
182
183
static void test_quiesce_co_drain_all(void)
184
{
185
- call_in_coroutine(test_quiesce_drain_all);
186
+ BlockBackend *blk = test_setup();
187
+ call_in_coroutine(test_quiesce_co_drain_all_entry);
188
+ blk_unref(blk);
189
+}
190
+
191
+static void coroutine_fn test_quiesce_co_drain_entry(void)
192
+{
193
+ BlockBackend *blk = blk_all_next(NULL);
194
+ test_quiesce_common(blk, BDRV_DRAIN, false);
195
}
196
197
static void test_quiesce_co_drain(void)
198
{
199
- call_in_coroutine(test_quiesce_drain);
200
+ BlockBackend *blk = test_setup();
201
+ call_in_coroutine(test_quiesce_co_drain_entry);
202
+ blk_unref(blk);
203
}
204
205
static void test_nested(void)
116
--
206
--
117
2.19.2
207
2.40.1
118
119
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
For some functions, it is part of their interface to be called without
2
holding the graph lock. Add a new macro to document this.
2
3
3
When reopen_f() puts a block device in the reopen queue, some of the
4
The macro expands to TSA_EXCLUDES(), which is a relatively weak check
4
new options are passed using a QDict, but others ("read-only" and the
5
because it passes in cases where the compiler just doesn't know if the
5
cache options) are passed as flags.
6
lock is held. Function pointers can't be checked at all. Therefore, its
7
primary purpose is documentation.
6
8
7
This patch puts those flags in the QDict. This way the flags parameter
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
becomes redundant and we'll be able to get rid of it in a subsequent
10
Reviewed-by: Eric Blake <eblake@redhat.com>
9
patch.
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
12
Message-Id: <20230504115750.54437-7-kwolf@redhat.com>
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
14
---
15
qemu-io-cmds.c | 27 ++++++++++++++++++++++++++-
15
include/block/graph-lock.h | 2 ++
16
tests/qemu-iotests/133 | 9 +++++++++
16
1 file changed, 2 insertions(+)
17
tests/qemu-iotests/133.out | 8 ++++++++
18
3 files changed, 43 insertions(+), 1 deletion(-)
19
17
20
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
18
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
21
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
22
--- a/qemu-io-cmds.c
20
--- a/include/block/graph-lock.h
23
+++ b/qemu-io-cmds.c
21
+++ b/include/block/graph-lock.h
24
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ extern BdrvGraphLock graph_lock;
25
23
*/
26
#include "qemu/osdep.h"
24
#define GRAPH_WRLOCK TSA_REQUIRES(graph_lock)
27
#include "qapi/error.h"
25
#define GRAPH_RDLOCK TSA_REQUIRES_SHARED(graph_lock)
28
+#include "qapi/qmp/qdict.h"
26
+#define GRAPH_UNLOCKED TSA_EXCLUDES(graph_lock)
29
#include "qemu-io.h"
27
30
#include "sysemu/block-backend.h"
28
/*
31
#include "block/block.h"
29
* TSA annotations are not part of function types, so checks are defeated when
32
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
30
@@ -XXX,XX +XXX,XX @@ extern BdrvGraphLock graph_lock;
33
int flags = bs->open_flags;
31
*/
34
bool writethrough = !blk_enable_write_cache(blk);
32
#define GRAPH_RDLOCK_PTR TSA_GUARDED_BY(graph_lock)
35
bool has_rw_option = false;
33
#define GRAPH_WRLOCK_PTR TSA_GUARDED_BY(graph_lock)
36
+ bool has_cache_option = false;
34
+#define GRAPH_UNLOCKED_PTR
37
35
38
BlockReopenQueue *brq;
36
/*
39
Error *local_err = NULL;
37
* register_aiocontext:
40
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
41
error_report("Invalid cache option: %s", optarg);
42
return -EINVAL;
43
}
44
+ has_cache_option = true;
45
break;
46
case 'o':
47
if (!qemu_opts_parse_noisily(&reopen_opts, optarg, 0)) {
48
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
49
}
50
51
qopts = qemu_opts_find(&reopen_opts, NULL);
52
- opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : NULL;
53
+ opts = qopts ? qemu_opts_to_qdict(qopts, NULL) : qdict_new();
54
qemu_opts_reset(&reopen_opts);
55
56
+ if (qdict_haskey(opts, BDRV_OPT_READ_ONLY)) {
57
+ if (has_rw_option) {
58
+ error_report("Cannot set both -r/-w and '" BDRV_OPT_READ_ONLY "'");
59
+ qobject_unref(opts);
60
+ return -EINVAL;
61
+ }
62
+ } else {
63
+ qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
64
+ }
65
+
66
+ if (qdict_haskey(opts, BDRV_OPT_CACHE_DIRECT) ||
67
+ qdict_haskey(opts, BDRV_OPT_CACHE_NO_FLUSH)) {
68
+ if (has_cache_option) {
69
+ error_report("Cannot set both -c and the cache options");
70
+ qobject_unref(opts);
71
+ return -EINVAL;
72
+ }
73
+ } else {
74
+ qdict_put_bool(opts, BDRV_OPT_CACHE_DIRECT, flags & BDRV_O_NOCACHE);
75
+ qdict_put_bool(opts, BDRV_OPT_CACHE_NO_FLUSH, flags & BDRV_O_NO_FLUSH);
76
+ }
77
+
78
bdrv_subtree_drained_begin(bs);
79
brq = bdrv_reopen_queue(NULL, bs, opts, flags);
80
bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
81
diff --git a/tests/qemu-iotests/133 b/tests/qemu-iotests/133
82
index XXXXXXX..XXXXXXX 100755
83
--- a/tests/qemu-iotests/133
84
+++ b/tests/qemu-iotests/133
85
@@ -XXX,XX +XXX,XX @@ echo
86
IMGOPTSSYNTAX=false $QEMU_IO -f null-co -c 'reopen' -c 'info' \
87
"json:{'driver': 'null-co', 'size': 65536}"
88
89
+echo
90
+echo "=== Check that mixing -c/-r/-w and their corresponding options is forbidden ==="
91
+echo
92
+
93
+$QEMU_IO -c 'reopen -r -o read-only=on' $TEST_IMG
94
+$QEMU_IO -c 'reopen -w -o read-only=on' $TEST_IMG
95
+$QEMU_IO -c 'reopen -c none -o cache.direct=on' $TEST_IMG
96
+$QEMU_IO -c 'reopen -c writeback -o cache.direct=on' $TEST_IMG
97
+$QEMU_IO -c 'reopen -c directsync -o cache.no-flush=on' $TEST_IMG
98
# success, all done
99
echo "*** done"
100
rm -f $seq.full
101
diff --git a/tests/qemu-iotests/133.out b/tests/qemu-iotests/133.out
102
index XXXXXXX..XXXXXXX 100644
103
--- a/tests/qemu-iotests/133.out
104
+++ b/tests/qemu-iotests/133.out
105
@@ -XXX,XX +XXX,XX @@ Cannot change the option 'driver'
106
107
format name: null-co
108
format name: null-co
109
+
110
+=== Check that mixing -c/-r/-w and their corresponding options is forbidden ===
111
+
112
+Cannot set both -r/-w and 'read-only'
113
+Cannot set both -r/-w and 'read-only'
114
+Cannot set both -c and the cache options
115
+Cannot set both -c and the cache options
116
+Cannot set both -c and the cache options
117
*** done
118
--
38
--
119
2.19.2
39
2.40.1
120
121
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
GRAPH_RDLOCK_GUARD() and GRAPH_RDLOCK_GUARD_MAINLOOP() only take a
2
reader lock for the graph, so the correct annotation for them to use is
3
TSA_ASSERT_SHARED rather than TSA_ASSERT.
2
4
3
Now that all callers are passing the new options using the QDict we no
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
longer need the 'flags' parameter.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
7
Message-Id: <20230504115750.54437-8-kwolf@redhat.com>
6
This patch makes the following changes:
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
8
1) The update_options_from_flags() call is no longer necessary
9
so it can be removed.
10
11
2) The update_flags_from_options() call is now used in all cases,
12
and is moved down a few lines so it happens after the options
13
QDict contains the final set of values.
14
15
3) The flags parameter is removed. Now the flags are initialized
16
using the current value (for the top-level node) or the parent
17
flags (after inherit_options()). In both cases the initial
18
values are updated to reflect the new options in the QDict. This
19
happens in bdrv_reopen_queue_child() (as explained above) and in
20
bdrv_reopen_prepare().
21
22
Signed-off-by: Alberto Garcia <berto@igalia.com>
23
Reviewed-by: Max Reitz <mreitz@redhat.com>
24
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
25
---
10
---
26
block.c | 48 +++++++++++++++++++-----------------------------
11
include/block/graph-lock.h | 16 ++++++++--------
27
1 file changed, 19 insertions(+), 29 deletions(-)
12
1 file changed, 8 insertions(+), 8 deletions(-)
28
13
29
diff --git a/block.c b/block.c
14
diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/block.c
16
--- a/include/block/graph-lock.h
32
+++ b/block.c
17
+++ b/include/block/graph-lock.h
33
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
18
@@ -XXX,XX +XXX,XX @@ typedef struct GraphLockable { } GraphLockable;
34
static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
19
#define GML_OBJ_() (&(GraphLockable) { })
35
BlockDriverState *bs,
20
36
QDict *options,
21
/*
37
- int flags,
22
- * This is not marked as TSA_ACQUIRE() because TSA doesn't understand the
38
const BdrvChildRole *role,
23
+ * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
39
QDict *parent_options,
24
* cleanup attribute and would therefore complain that the graph is never
40
int parent_flags)
25
- * unlocked. TSA_ASSERT() makes sure that the following calls know that we
41
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
26
- * hold the lock while unlocking is left unchecked.
42
27
+ * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
43
BlockReopenQueueEntry *bs_entry;
28
+ * we hold the lock while unlocking is left unchecked.
44
BdrvChild *child;
29
*/
45
- QDict *old_options, *explicit_options;
30
-static inline GraphLockable * TSA_ASSERT(graph_lock) TSA_NO_TSA coroutine_fn
46
+ QDict *old_options, *explicit_options, *options_copy;
31
+static inline GraphLockable * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA coroutine_fn
47
+ int flags;
32
graph_lockable_auto_lock(GraphLockable *x)
48
+ QemuOpts *opts;
49
50
/* Make sure that the caller remembered to use a drained section. This is
51
* important to avoid graph changes between the recursive queuing here and
52
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
53
/*
54
* Precedence of options:
55
* 1. Explicitly passed in options (highest)
56
- * 2. Set in flags (only for top level)
57
- * 3. Retained from explicitly set options of bs
58
- * 4. Inherited from parent node
59
- * 5. Retained from effective options of bs
60
+ * 2. Retained from explicitly set options of bs
61
+ * 3. Inherited from parent node
62
+ * 4. Retained from effective options of bs
63
*/
64
65
- if (!parent_options) {
66
- /*
67
- * Any setting represented by flags is always updated. If the
68
- * corresponding QDict option is set, it takes precedence. Otherwise
69
- * the flag is translated into a QDict option. The old setting of bs is
70
- * not considered.
71
- */
72
- update_options_from_flags(options, flags);
73
- }
74
-
75
/* Old explicitly set values (don't overwrite by inherited value) */
76
if (bs_entry) {
77
old_options = qdict_clone_shallow(bs_entry->state.explicit_options);
78
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
79
80
/* Inherit from parent node */
81
if (parent_options) {
82
- QemuOpts *opts;
83
- QDict *options_copy;
84
- assert(!flags);
85
+ flags = 0;
86
role->inherit_options(&flags, options, parent_flags, parent_options);
87
- options_copy = qdict_clone_shallow(options);
88
- opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
89
- qemu_opts_absorb_qdict(opts, options_copy, NULL);
90
- update_flags_from_options(&flags, opts);
91
- qemu_opts_del(opts);
92
- qobject_unref(options_copy);
93
+ } else {
94
+ flags = bdrv_get_flags(bs);
95
}
96
97
/* Old values are used for options that aren't set yet */
98
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
99
bdrv_join_options(bs, options, old_options);
100
qobject_unref(old_options);
101
102
+ /* We have the final set of options so let's update the flags */
103
+ options_copy = qdict_clone_shallow(options);
104
+ opts = qemu_opts_create(&bdrv_runtime_opts, NULL, 0, &error_abort);
105
+ qemu_opts_absorb_qdict(opts, options_copy, NULL);
106
+ update_flags_from_options(&flags, opts);
107
+ qemu_opts_del(opts);
108
+ qobject_unref(options_copy);
109
+
110
/* bdrv_open_inherit() sets and clears some additional flags internally */
111
flags &= ~BDRV_O_PROTOCOL;
112
if (flags & BDRV_O_RDWR) {
113
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
114
qdict_extract_subqdict(options, &new_child_options, child_key_dot);
115
g_free(child_key_dot);
116
117
- bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, 0,
118
+ bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options,
119
child->role, options, flags);
120
}
121
122
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
123
BlockDriverState *bs,
124
QDict *options)
125
{
33
{
126
- int flags = bdrv_get_flags(bs);
34
bdrv_graph_co_rdlock();
127
- return bdrv_reopen_queue_child(bs_queue, bs, options, flags,
35
@@ -XXX,XX +XXX,XX @@ typedef struct GraphLockableMainloop { } GraphLockableMainloop;
128
- NULL, NULL, 0);
36
#define GMLML_OBJ_() (&(GraphLockableMainloop) { })
129
+ return bdrv_reopen_queue_child(bs_queue, bs, options, NULL, NULL, 0);
130
}
131
37
132
/*
38
/*
39
- * This is not marked as TSA_ACQUIRE() because TSA doesn't understand the
40
+ * This is not marked as TSA_ACQUIRE_SHARED() because TSA doesn't understand the
41
* cleanup attribute and would therefore complain that the graph is never
42
- * unlocked. TSA_ASSERT() makes sure that the following calls know that we
43
- * hold the lock while unlocking is left unchecked.
44
+ * unlocked. TSA_ASSERT_SHARED() makes sure that the following calls know that
45
+ * we hold the lock while unlocking is left unchecked.
46
*/
47
-static inline GraphLockableMainloop * TSA_ASSERT(graph_lock) TSA_NO_TSA
48
+static inline GraphLockableMainloop * TSA_ASSERT_SHARED(graph_lock) TSA_NO_TSA
49
graph_lockable_auto_lock_mainloop(GraphLockableMainloop *x)
50
{
51
bdrv_graph_rdlock_main_loop();
133
--
52
--
134
2.19.2
53
2.40.1
135
136
diff view generated by jsdifflib
1
aio_worker() doesn't add anything interesting, it's only a useless
1
Drivers were a bit confused about whether .bdrv_open can run in a
2
indirection. Call the handler function directly instead.
2
coroutine and whether or not it holds a graph lock.
3
3
4
As we know that this handler function is only called from coroutine
4
It cannot keep a graph lock from the caller across the whole function
5
context and the coroutine stays around until the worker thread finishes,
5
because it both changes the graph (requires a writer lock) and does I/O
6
we can keep RawPosixAIOData on the stack.
6
(requires a reader lock). Therefore, it should take these locks
7
internally as needed.
8
9
The functions used to be called in coroutine context during image
10
creation. This was buggy for other reasons, and as of commit 32192301,
11
all block drivers go through no_co_wrappers. So it is not called in
12
coroutine context any more.
13
14
Fix qcow2 and qed to work with the correct assumptions: The graph lock
15
needs to be taken internally instead of just assuming it's already
16
there, and the coroutine path is dead code that can be removed.
7
17
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
18
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
19
Reviewed-by: Eric Blake <eblake@redhat.com>
20
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
21
Message-Id: <20230504115750.54437-9-kwolf@redhat.com>
22
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
23
---
10
block/file-posix.c | 16 +++++++++++-----
24
include/block/block_int-common.h | 8 ++++----
11
1 file changed, 11 insertions(+), 5 deletions(-)
25
block.c | 6 +++---
26
block/qcow2.c | 15 ++++++---------
27
block/qed.c | 18 ++++++++----------
28
4 files changed, 21 insertions(+), 26 deletions(-)
12
29
13
diff --git a/block/file-posix.c b/block/file-posix.c
30
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
14
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
32
--- a/include/block/block_int-common.h
16
+++ b/block/file-posix.c
33
+++ b/include/block/block_int-common.h
17
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
34
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
18
return 0;
35
void (*bdrv_reopen_abort)(BDRVReopenState *reopen_state);
36
void (*bdrv_join_options)(QDict *options, QDict *old_options);
37
38
- int (*bdrv_open)(BlockDriverState *bs, QDict *options, int flags,
39
- Error **errp);
40
+ int GRAPH_UNLOCKED_PTR (*bdrv_open)(
41
+ BlockDriverState *bs, QDict *options, int flags, Error **errp);
42
43
/* Protocol drivers should implement this instead of bdrv_open */
44
- int (*bdrv_file_open)(BlockDriverState *bs, QDict *options, int flags,
45
- Error **errp);
46
+ int GRAPH_UNLOCKED_PTR (*bdrv_file_open)(
47
+ BlockDriverState *bs, QDict *options, int flags, Error **errp);
48
void (*bdrv_close)(BlockDriverState *bs);
49
50
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_create)(
51
diff --git a/block.c b/block.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block.c
54
+++ b/block.c
55
@@ -XXX,XX +XXX,XX @@ out:
56
* bdrv_refresh_total_sectors() which polls when called from non-coroutine
57
* context.
58
*/
59
-static int bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv,
60
- const char *node_name, QDict *options,
61
- int open_flags, Error **errp)
62
+static int no_coroutine_fn GRAPH_UNLOCKED
63
+bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
64
+ QDict *options, int open_flags, Error **errp)
65
{
66
Error *local_err = NULL;
67
int i, ret;
68
diff --git a/block/qcow2.c b/block/qcow2.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/qcow2.c
71
+++ b/block/qcow2.c
72
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qcow2_open_entry(void *opaque)
73
QCow2OpenCo *qoc = opaque;
74
BDRVQcow2State *s = qoc->bs->opaque;
75
76
- assume_graph_lock(); /* FIXME */
77
+ GRAPH_RDLOCK_GUARD();
78
79
qemu_co_mutex_lock(&s->lock);
80
qoc->ret = qcow2_do_open(qoc->bs, qoc->options, qoc->flags, true,
81
@@ -XXX,XX +XXX,XX @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
82
/* Initialise locks */
83
qemu_co_mutex_init(&s->lock);
84
85
- if (qemu_in_coroutine()) {
86
- /* From bdrv_co_create. */
87
- qcow2_open_entry(&qoc);
88
- } else {
89
- assert(qemu_get_current_aio_context() == qemu_get_aio_context());
90
- qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
91
- BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
92
- }
93
+ assert(!qemu_in_coroutine());
94
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
95
+ qemu_coroutine_enter(qemu_coroutine_create(qcow2_open_entry, &qoc));
96
+ BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
97
+
98
return qoc.ret;
19
}
99
}
20
100
21
-static ssize_t handle_aiocb_flush(RawPosixAIOData *aiocb)
101
diff --git a/block/qed.c b/block/qed.c
22
+static int handle_aiocb_flush(void *opaque)
102
index XXXXXXX..XXXXXXX 100644
103
--- a/block/qed.c
104
+++ b/block/qed.c
105
@@ -XXX,XX +XXX,XX @@ typedef struct QEDOpenCo {
106
int ret;
107
} QEDOpenCo;
108
109
-static void coroutine_fn GRAPH_RDLOCK bdrv_qed_open_entry(void *opaque)
110
+static void coroutine_fn bdrv_qed_open_entry(void *opaque)
23
{
111
{
24
+ RawPosixAIOData *aiocb = opaque;
112
QEDOpenCo *qoc = opaque;
25
BDRVRawState *s = aiocb->bs->opaque;
113
BDRVQEDState *s = qoc->bs->opaque;
114
115
+ GRAPH_RDLOCK_GUARD();
116
+
117
qemu_co_mutex_lock(&s->table_lock);
118
qoc->ret = bdrv_qed_do_open(qoc->bs, qoc->options, qoc->flags, qoc->errp);
119
qemu_co_mutex_unlock(&s->table_lock);
120
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
121
};
26
int ret;
122
int ret;
27
123
28
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
124
- assume_graph_lock(); /* FIXME */
29
ret = -EINVAL;
125
-
30
}
126
ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
31
break;
127
if (ret < 0) {
32
- case QEMU_AIO_FLUSH:
33
- ret = handle_aiocb_flush(aiocb);
34
- break;
35
case QEMU_AIO_IOCTL:
36
ret = handle_aiocb_ioctl(aiocb);
37
break;
38
+ case QEMU_AIO_FLUSH:
39
case QEMU_AIO_DISCARD:
40
case QEMU_AIO_WRITE_ZEROES:
41
case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
42
@@ -XXX,XX +XXX,XX @@ static void raw_aio_unplug(BlockDriverState *bs)
43
static int raw_co_flush_to_disk(BlockDriverState *bs)
44
{
45
BDRVRawState *s = bs->opaque;
46
+ RawPosixAIOData acb;
47
int ret;
48
49
ret = fd_open(bs);
50
@@ -XXX,XX +XXX,XX @@ static int raw_co_flush_to_disk(BlockDriverState *bs)
51
return ret;
128
return ret;
52
}
129
}
53
130
54
- return paio_submit_co(bs, s->fd, 0, NULL, 0, QEMU_AIO_FLUSH);
131
bdrv_qed_init_state(bs);
55
+ acb = (RawPosixAIOData) {
132
- if (qemu_in_coroutine()) {
56
+ .bs = bs,
133
- bdrv_qed_open_entry(&qoc);
57
+ .aio_fildes = s->fd,
134
- } else {
58
+ .aio_type = QEMU_AIO_FLUSH,
135
- assert(qemu_get_current_aio_context() == qemu_get_aio_context());
59
+ };
136
- qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
137
- BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
138
- }
139
+ assert(!qemu_in_coroutine());
140
+ assert(qemu_get_current_aio_context() == qemu_get_aio_context());
141
+ qemu_coroutine_enter(qemu_coroutine_create(bdrv_qed_open_entry, &qoc));
142
+ BDRV_POLL_WHILE(bs, qoc.ret == -EINPROGRESS);
60
+
143
+
61
+ return raw_thread_pool_submit(bs, handle_aiocb_flush, &acb);
144
return qoc.ret;
62
}
145
}
63
146
64
static void raw_aio_attach_aio_context(BlockDriverState *bs,
65
--
147
--
66
2.19.2
148
2.40.1
67
68
diff view generated by jsdifflib
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
1
The only thing nbd_co_flush() does is call nbd_client_co_flush(). Just
2
use that function directly in the BlockDriver definitions and remove the
3
wrapper.
2
4
3
Compression is done in threads in qcow2.c. We want to do decompression
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
in the same way, so, firstly, move it to the same file.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
The only change is braces around if-body in decompress_buffer, to
8
Message-Id: <20230504115750.54437-10-kwolf@redhat.com>
7
satisfy checkpatch.
8
9
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
10
Reviewed-by: Alberto Garcia <berto@igalia.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
10
---
13
block/qcow2-cluster.c | 70 ------------------------------------------
11
block/nbd.c | 11 +++--------
14
block/qcow2.c | 71 +++++++++++++++++++++++++++++++++++++++++++
12
1 file changed, 3 insertions(+), 8 deletions(-)
15
2 files changed, 71 insertions(+), 70 deletions(-)
16
13
17
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
14
diff --git a/block/nbd.c b/block/nbd.c
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2-cluster.c
16
--- a/block/nbd.c
20
+++ b/block/qcow2-cluster.c
17
+++ b/block/nbd.c
21
@@ -XXX,XX +XXX,XX @@ again:
22
return 0;
23
}
24
25
-static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
26
- const uint8_t *buf, int buf_size)
27
-{
28
- z_stream strm1, *strm = &strm1;
29
- int ret, out_len;
30
-
31
- memset(strm, 0, sizeof(*strm));
32
-
33
- strm->next_in = (uint8_t *)buf;
34
- strm->avail_in = buf_size;
35
- strm->next_out = out_buf;
36
- strm->avail_out = out_buf_size;
37
-
38
- ret = inflateInit2(strm, -12);
39
- if (ret != Z_OK)
40
- return -1;
41
- ret = inflate(strm, Z_FINISH);
42
- out_len = strm->next_out - out_buf;
43
- if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
44
- out_len != out_buf_size) {
45
- inflateEnd(strm);
46
- return -1;
47
- }
48
- inflateEnd(strm);
49
- return 0;
50
-}
51
-
52
-int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
53
-{
54
- BDRVQcow2State *s = bs->opaque;
55
- int ret, csize, nb_csectors, sector_offset;
56
- uint64_t coffset;
57
-
58
- coffset = cluster_offset & s->cluster_offset_mask;
59
- if (s->cluster_cache_offset != coffset) {
60
- nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
61
- sector_offset = coffset & 511;
62
- csize = nb_csectors * 512 - sector_offset;
63
-
64
- /* Allocate buffers on first decompress operation, most images are
65
- * uncompressed and the memory overhead can be avoided. The buffers
66
- * are freed in .bdrv_close().
67
- */
68
- if (!s->cluster_data) {
69
- /* one more sector for decompressed data alignment */
70
- s->cluster_data = qemu_try_blockalign(bs->file->bs,
71
- QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size + 512);
72
- if (!s->cluster_data) {
73
- return -ENOMEM;
74
- }
75
- }
76
- if (!s->cluster_cache) {
77
- s->cluster_cache = g_malloc(s->cluster_size);
78
- }
79
-
80
- BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
81
- ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data,
82
- nb_csectors);
83
- if (ret < 0) {
84
- return ret;
85
- }
86
- if (decompress_buffer(s->cluster_cache, s->cluster_size,
87
- s->cluster_data + sector_offset, csize) < 0) {
88
- return -EIO;
89
- }
90
- s->cluster_cache_offset = coffset;
91
- }
92
- return 0;
93
-}
94
-
95
/*
96
* This discards as many clusters of nb_clusters as possible at once (i.e.
97
* all clusters in the same L2 slice) and returns the number of discarded
98
diff --git a/block/qcow2.c b/block/qcow2.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/qcow2.c
101
+++ b/block/qcow2.c
102
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, size_t dest_size,
103
return ret;
104
}
105
106
+static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
107
+ const uint8_t *buf, int buf_size)
108
+{
109
+ z_stream strm1, *strm = &strm1;
110
+ int ret, out_len;
111
+
112
+ memset(strm, 0, sizeof(*strm));
113
+
114
+ strm->next_in = (uint8_t *)buf;
115
+ strm->avail_in = buf_size;
116
+ strm->next_out = out_buf;
117
+ strm->avail_out = out_buf_size;
118
+
119
+ ret = inflateInit2(strm, -12);
120
+ if (ret != Z_OK) {
121
+ return -1;
122
+ }
123
+ ret = inflate(strm, Z_FINISH);
124
+ out_len = strm->next_out - out_buf;
125
+ if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
126
+ out_len != out_buf_size) {
127
+ inflateEnd(strm);
128
+ return -1;
129
+ }
130
+ inflateEnd(strm);
131
+ return 0;
132
+}
133
+
134
#define MAX_COMPRESS_THREADS 4
135
136
typedef struct Qcow2CompressData {
137
@@ -XXX,XX +XXX,XX @@ fail:
18
@@ -XXX,XX +XXX,XX @@ fail:
138
return ret;
19
return ret;
139
}
20
}
140
21
141
+int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
22
-static int coroutine_fn nbd_co_flush(BlockDriverState *bs)
142
+{
23
-{
143
+ BDRVQcow2State *s = bs->opaque;
24
- return nbd_client_co_flush(bs);
144
+ int ret, csize, nb_csectors, sector_offset;
25
-}
145
+ uint64_t coffset;
26
-
146
+
27
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
147
+ coffset = cluster_offset & s->cluster_offset_mask;
148
+ if (s->cluster_cache_offset != coffset) {
149
+ nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
150
+ sector_offset = coffset & 511;
151
+ csize = nb_csectors * 512 - sector_offset;
152
+
153
+ /* Allocate buffers on first decompress operation, most images are
154
+ * uncompressed and the memory overhead can be avoided. The buffers
155
+ * are freed in .bdrv_close().
156
+ */
157
+ if (!s->cluster_data) {
158
+ /* one more sector for decompressed data alignment */
159
+ s->cluster_data = qemu_try_blockalign(bs->file->bs,
160
+ QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size + 512);
161
+ if (!s->cluster_data) {
162
+ return -ENOMEM;
163
+ }
164
+ }
165
+ if (!s->cluster_cache) {
166
+ s->cluster_cache = g_malloc(s->cluster_size);
167
+ }
168
+
169
+ BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
170
+ ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data,
171
+ nb_csectors);
172
+ if (ret < 0) {
173
+ return ret;
174
+ }
175
+ if (decompress_buffer(s->cluster_cache, s->cluster_size,
176
+ s->cluster_data + sector_offset, csize) < 0) {
177
+ return -EIO;
178
+ }
179
+ s->cluster_cache_offset = coffset;
180
+ }
181
+ return 0;
182
+}
183
+
184
static int make_completely_empty(BlockDriverState *bs)
185
{
28
{
186
BDRVQcow2State *s = bs->opaque;
29
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
30
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd = {
31
.bdrv_co_pwritev = nbd_client_co_pwritev,
32
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
33
.bdrv_close = nbd_close,
34
- .bdrv_co_flush_to_os = nbd_co_flush,
35
+ .bdrv_co_flush_to_os = nbd_client_co_flush,
36
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
37
.bdrv_refresh_limits = nbd_refresh_limits,
38
.bdrv_co_truncate = nbd_co_truncate,
39
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_tcp = {
40
.bdrv_co_pwritev = nbd_client_co_pwritev,
41
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
42
.bdrv_close = nbd_close,
43
- .bdrv_co_flush_to_os = nbd_co_flush,
44
+ .bdrv_co_flush_to_os = nbd_client_co_flush,
45
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
46
.bdrv_refresh_limits = nbd_refresh_limits,
47
.bdrv_co_truncate = nbd_co_truncate,
48
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_nbd_unix = {
49
.bdrv_co_pwritev = nbd_client_co_pwritev,
50
.bdrv_co_pwrite_zeroes = nbd_client_co_pwrite_zeroes,
51
.bdrv_close = nbd_close,
52
- .bdrv_co_flush_to_os = nbd_co_flush,
53
+ .bdrv_co_flush_to_os = nbd_client_co_flush,
54
.bdrv_co_pdiscard = nbd_client_co_pdiscard,
55
.bdrv_refresh_limits = nbd_refresh_limits,
56
.bdrv_co_truncate = nbd_co_truncate,
187
--
57
--
188
2.19.2
58
2.40.1
189
190
diff view generated by jsdifflib
1
aio_worker() doesn't add anything interesting, it's only a useless
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
indirection. Call the handler function directly instead.
3
2
4
As we know that this handler function is only called from coroutine
3
This adds GRAPH_RDLOCK annotations to declare that callers of
5
context and the coroutine stays around until the worker thread finishes,
4
nbd_co_do_establish_connection() need to hold a reader lock for the
6
we can keep RawPosixAIOData on the stack.
5
graph.
7
6
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Message-Id: <20230504115750.54437-11-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
13
---
10
block/file-posix.c | 53 +++++++++++++++++++++++++++++-----------------
14
block/coroutines.h | 5 +++--
11
1 file changed, 34 insertions(+), 19 deletions(-)
15
block/nbd.c | 39 +++++++++++++++++++++------------------
16
2 files changed, 24 insertions(+), 20 deletions(-)
12
17
13
diff --git a/block/file-posix.c b/block/file-posix.c
18
diff --git a/block/coroutines.h b/block/coroutines.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
20
--- a/block/coroutines.h
16
+++ b/block/file-posix.c
21
+++ b/block/coroutines.h
17
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_write_zeroes_block(RawPosixAIOData *aiocb)
22
@@ -XXX,XX +XXX,XX @@ bdrv_co_readv_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
18
return ret;
23
int coroutine_fn GRAPH_RDLOCK
24
bdrv_co_writev_vmstate(BlockDriverState *bs, QEMUIOVector *qiov, int64_t pos);
25
26
-int coroutine_fn
27
+int coroutine_fn GRAPH_RDLOCK
28
nbd_co_do_establish_connection(BlockDriverState *bs, bool blocking,
29
Error **errp);
30
31
@@ -XXX,XX +XXX,XX @@ bdrv_common_block_status_above(BlockDriverState *bs,
32
int64_t *map,
33
BlockDriverState **file,
34
int *depth);
35
-int co_wrapper_mixed
36
+
37
+int co_wrapper_mixed_bdrv_rdlock
38
nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
39
40
#endif /* BLOCK_COROUTINES_H */
41
diff --git a/block/nbd.c b/block/nbd.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/block/nbd.c
44
+++ b/block/nbd.c
45
@@ -XXX,XX +XXX,XX @@ int coroutine_fn nbd_co_do_establish_connection(BlockDriverState *bs,
46
int ret;
47
IO_CODE();
48
49
+ assert_bdrv_graph_readable();
50
assert(!s->ioc);
51
52
s->ioc = nbd_co_establish_connection(s->conn, &s->info, blocking, errp);
53
@@ -XXX,XX +XXX,XX @@ static bool nbd_client_connecting(BDRVNBDState *s)
19
}
54
}
20
55
21
-static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData *aiocb)
56
/* Called with s->requests_lock taken. */
22
+static int handle_aiocb_write_zeroes(void *opaque)
57
-static coroutine_fn void nbd_reconnect_attempt(BDRVNBDState *s)
58
+static void coroutine_fn GRAPH_RDLOCK nbd_reconnect_attempt(BDRVNBDState *s)
23
{
59
{
24
+ RawPosixAIOData *aiocb = opaque;
60
int ret;
25
#if defined(CONFIG_FALLOCATE) || defined(CONFIG_XFS)
61
bool blocking = s->state == NBD_CLIENT_CONNECTING_WAIT;
26
BDRVRawState *s = aiocb->bs->opaque;
62
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_receive_replies(BDRVNBDState *s, uint64_t handle)
27
#endif
63
}
28
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData *aiocb)
29
return -ENOTSUP;
30
}
64
}
31
65
32
-static ssize_t handle_aiocb_write_zeroes_unmap(RawPosixAIOData *aiocb)
66
-static int coroutine_fn nbd_co_send_request(BlockDriverState *bs,
33
+static int handle_aiocb_write_zeroes_unmap(void *opaque)
67
- NBDRequest *request,
68
- QEMUIOVector *qiov)
69
+static int coroutine_fn GRAPH_RDLOCK
70
+nbd_co_send_request(BlockDriverState *bs, NBDRequest *request,
71
+ QEMUIOVector *qiov)
34
{
72
{
35
+ RawPosixAIOData *aiocb = opaque;
73
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
36
BDRVRawState *s G_GNUC_UNUSED = aiocb->bs->opaque;
74
int rc, i = -1;
37
int ret;
75
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_receive_blockstatus_reply(BDRVNBDState *s,
38
76
return iter.ret;
39
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
40
ret = handle_aiocb_discard(aiocb);
41
break;
42
case QEMU_AIO_WRITE_ZEROES:
43
- ret = handle_aiocb_write_zeroes(aiocb);
44
- break;
45
case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
46
- ret = handle_aiocb_write_zeroes_unmap(aiocb);
47
- break;
48
case QEMU_AIO_COPY_RANGE:
49
case QEMU_AIO_TRUNCATE:
50
g_assert_not_reached();
51
@@ -XXX,XX +XXX,XX @@ raw_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
52
return paio_submit_co(bs, s->fd, offset, NULL, bytes, QEMU_AIO_DISCARD);
53
}
77
}
54
78
55
-static int coroutine_fn raw_co_pwrite_zeroes(
79
-static int coroutine_fn nbd_co_request(BlockDriverState *bs, NBDRequest *request,
56
- BlockDriverState *bs, int64_t offset,
80
- QEMUIOVector *write_qiov)
57
- int bytes, BdrvRequestFlags flags)
81
+static int coroutine_fn GRAPH_RDLOCK
58
+static int coroutine_fn
82
+nbd_co_request(BlockDriverState *bs, NBDRequest *request,
59
+raw_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int bytes,
83
+ QEMUIOVector *write_qiov)
60
+ BdrvRequestFlags flags, bool blkdev)
61
{
84
{
62
BDRVRawState *s = bs->opaque;
85
int ret, request_ret;
63
- int operation = QEMU_AIO_WRITE_ZEROES;
86
Error *local_err = NULL;
64
+ RawPosixAIOData acb;
87
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_request(BlockDriverState *bs, NBDRequest *request
65
+ ThreadPoolFunc *handler;
88
return ret ? ret : request_ret;
66
+
67
+ acb = (RawPosixAIOData) {
68
+ .bs = bs,
69
+ .aio_fildes = s->fd,
70
+ .aio_type = QEMU_AIO_WRITE_ZEROES,
71
+ .aio_offset = offset,
72
+ .aio_nbytes = bytes,
73
+ };
74
+
75
+ if (blkdev) {
76
+ acb.aio_type |= QEMU_AIO_BLKDEV;
77
+ }
78
79
if (flags & BDRV_REQ_MAY_UNMAP) {
80
- operation |= QEMU_AIO_DISCARD;
81
+ acb.aio_type |= QEMU_AIO_DISCARD;
82
+ handler = handle_aiocb_write_zeroes_unmap;
83
+ } else {
84
+ handler = handle_aiocb_write_zeroes;
85
}
86
87
- return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
88
+ return raw_thread_pool_submit(bs, handler, &acb);
89
+}
90
+
91
+static int coroutine_fn raw_co_pwrite_zeroes(
92
+ BlockDriverState *bs, int64_t offset,
93
+ int bytes, BdrvRequestFlags flags)
94
+{
95
+ return raw_do_pwrite_zeroes(bs, offset, bytes, flags, false);
96
}
89
}
97
90
98
static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
91
-static int coroutine_fn nbd_client_co_preadv(BlockDriverState *bs, int64_t offset,
99
@@ -XXX,XX +XXX,XX @@ hdev_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
92
- int64_t bytes, QEMUIOVector *qiov,
100
static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
93
- BdrvRequestFlags flags)
101
int64_t offset, int bytes, BdrvRequestFlags flags)
94
+static int coroutine_fn GRAPH_RDLOCK
95
+nbd_client_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes,
96
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
102
{
97
{
103
- BDRVRawState *s = bs->opaque;
98
int ret, request_ret;
104
- int operation = QEMU_AIO_WRITE_ZEROES | QEMU_AIO_BLKDEV;
99
Error *local_err = NULL;
105
int rc;
100
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_preadv(BlockDriverState *bs, int64_t offse
106
101
return ret ? ret : request_ret;
107
rc = fd_open(bs);
108
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
109
return rc;
110
}
111
112
- if (flags & BDRV_REQ_MAY_UNMAP) {
113
- operation |= QEMU_AIO_DISCARD;
114
- }
115
-
116
- return paio_submit_co(bs, s->fd, offset, NULL, bytes, operation);
117
+ return raw_do_pwrite_zeroes(bs, offset, bytes, flags, true);
118
}
102
}
119
103
120
static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts,
104
-static int coroutine_fn nbd_client_co_pwritev(BlockDriverState *bs, int64_t offset,
105
- int64_t bytes, QEMUIOVector *qiov,
106
- BdrvRequestFlags flags)
107
+static int coroutine_fn GRAPH_RDLOCK
108
+nbd_client_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
109
+ QEMUIOVector *qiov, BdrvRequestFlags flags)
110
{
111
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
112
NBDRequest request = {
113
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_pwritev(BlockDriverState *bs, int64_t offs
114
return nbd_co_request(bs, &request, qiov);
115
}
116
117
-static int coroutine_fn nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
118
- int64_t bytes, BdrvRequestFlags flags)
119
+static int coroutine_fn GRAPH_RDLOCK
120
+nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
121
+ BdrvRequestFlags flags)
122
{
123
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
124
NBDRequest request = {
125
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_
126
return nbd_co_request(bs, &request, NULL);
127
}
128
129
-static int coroutine_fn nbd_client_co_flush(BlockDriverState *bs)
130
+static int coroutine_fn GRAPH_RDLOCK nbd_client_co_flush(BlockDriverState *bs)
131
{
132
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
133
NBDRequest request = { .type = NBD_CMD_FLUSH };
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_flush(BlockDriverState *bs)
135
return nbd_co_request(bs, &request, NULL);
136
}
137
138
-static int coroutine_fn nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset,
139
- int64_t bytes)
140
+static int coroutine_fn GRAPH_RDLOCK
141
+nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int64_t bytes)
142
{
143
BDRVNBDState *s = (BDRVNBDState *)bs->opaque;
144
NBDRequest request = {
145
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_client_co_pdiscard(BlockDriverState *bs, int64_t off
146
return nbd_co_request(bs, &request, NULL);
147
}
148
149
-static int coroutine_fn nbd_client_co_block_status(
150
+static int coroutine_fn GRAPH_RDLOCK nbd_client_co_block_status(
151
BlockDriverState *bs, bool want_zero, int64_t offset, int64_t bytes,
152
int64_t *pnum, int64_t *map, BlockDriverState **file)
153
{
121
--
154
--
122
2.19.2
155
2.40.1
123
124
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that functions accessing
2
the parent list of a node need to hold a reader lock for the graph. As
3
it happens, they already do.
2
4
3
This patch replaces the bdrv_reopen() calls that set and remove the
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Message-Id: <20230504115750.54437-12-kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block/commit.c | 7 +++----
11
block/vhdx.c | 9 +++++----
11
1 file changed, 3 insertions(+), 4 deletions(-)
12
1 file changed, 5 insertions(+), 4 deletions(-)
12
13
13
diff --git a/block/commit.c b/block/commit.c
14
diff --git a/block/vhdx.c b/block/vhdx.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/block/commit.c
16
--- a/block/vhdx.c
16
+++ b/block/commit.c
17
+++ b/block/vhdx.c
17
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
18
@@ -XXX,XX +XXX,XX @@ exit:
18
BlockDriverState *commit_top_bs = NULL;
19
* There are 2 headers, and the highest sequence number will represent
19
BlockDriver *drv = bs->drv;
20
* the active header
20
int64_t offset, length, backing_length;
21
*/
21
- int ro, open_flags;
22
-static int vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
22
+ int ro;
23
- uint32_t log_size)
23
int64_t n;
24
+static int coroutine_fn GRAPH_RDLOCK
24
int ret = 0;
25
+vhdx_create_new_headers(BlockBackend *blk, uint64_t image_size,
25
uint8_t *buf = NULL;
26
+ uint32_t log_size)
26
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
27
{
27
}
28
BlockDriverState *bs = blk_bs(blk);
28
29
BdrvChild *child;
29
ro = bs->backing->bs->read_only;
30
@@ -XXX,XX +XXX,XX @@ exit:
30
- open_flags = bs->backing->bs->open_flags;
31
* .---- ~ ----------- ~ ------------ ~ ---------------- ~ -----------.
31
32
* 1MB
32
if (ro) {
33
*/
33
- if (bdrv_reopen(bs->backing->bs, open_flags | BDRV_O_RDWR, NULL)) {
34
-static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
34
+ if (bdrv_reopen_set_read_only(bs->backing->bs, false, NULL)) {
35
- Error **errp)
35
return -EACCES;
36
+static int coroutine_fn GRAPH_RDLOCK
36
}
37
+vhdx_co_create(BlockdevCreateOptions *opts, Error **errp)
37
}
38
{
38
@@ -XXX,XX +XXX,XX @@ ro_cleanup:
39
BlockdevCreateOptionsVhdx *vhdx_opts;
39
40
BlockBackend *blk = NULL;
40
if (ro) {
41
/* ignoring error return here */
42
- bdrv_reopen(bs->backing->bs, open_flags & ~BDRV_O_RDWR, NULL);
43
+ bdrv_reopen_set_read_only(bs->backing->bs, true, NULL);
44
}
45
46
return ret;
47
--
41
--
48
2.19.2
42
2.40.1
49
50
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that functions accessing
2
the parent list of a node need to hold a reader lock for the graph. As
3
it happens, they already do.
2
4
3
The 'block-commit' QMP command is implemented internally using two
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
different drivers. If the source image is the active layer then the
6
Message-Id: <20230504115750.54437-13-kwolf@redhat.com>
5
mirror driver is used (commit_active_start()), otherwise the commit
7
Reviewed-by: Eric Blake <eblake@redhat.com>
6
driver is used (commit_start()).
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
8
In both cases the destination image must be put temporarily in
9
read-write mode. This is done correctly in the latter case, but what
10
commit_active_start() does is copy all flags instead.
11
12
This patch replaces the bdrv_reopen() calls in that function with
13
bdrv_reopen_set_read_only() so that only the read-only status is
14
changed.
15
16
A similar change is made in mirror_exit(), which is also used by the
17
'drive-mirror' and 'blockdev-mirror' commands.
18
19
Signed-off-by: Alberto Garcia <berto@igalia.com>
20
Reviewed-by: Max Reitz <mreitz@redhat.com>
21
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
22
---
10
---
23
block/mirror.c | 19 ++++++++++++-------
11
block/mirror.c | 2 +-
24
1 file changed, 12 insertions(+), 7 deletions(-)
12
1 file changed, 1 insertion(+), 1 deletion(-)
25
13
26
diff --git a/block/mirror.c b/block/mirror.c
14
diff --git a/block/mirror.c b/block/mirror.c
27
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
28
--- a/block/mirror.c
16
--- a/block/mirror.c
29
+++ b/block/mirror.c
17
+++ b/block/mirror.c
30
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
18
@@ -XXX,XX +XXX,XX @@ static MirrorOp *coroutine_fn active_write_prepare(MirrorBlockJob *s,
31
19
return op;
32
if (s->should_complete && !abort) {
20
}
33
BlockDriverState *to_replace = s->to_replace ?: src;
21
34
+ bool ro = bdrv_is_read_only(to_replace);
22
-static void coroutine_fn active_write_settle(MirrorOp *op)
35
23
+static void coroutine_fn GRAPH_RDLOCK active_write_settle(MirrorOp *op)
36
- if (bdrv_get_flags(target_bs) != bdrv_get_flags(to_replace)) {
37
- bdrv_reopen(target_bs, bdrv_get_flags(to_replace), NULL);
38
+ if (ro != bdrv_is_read_only(target_bs)) {
39
+ bdrv_reopen_set_read_only(target_bs, ro, NULL);
40
}
41
42
/* The mirror job has no requests in flight any more, but we need to
43
@@ -XXX,XX +XXX,XX @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
44
BlockCompletionFunc *cb, void *opaque,
45
bool auto_complete, Error **errp)
46
{
24
{
47
- int orig_base_flags;
25
uint64_t start_chunk = op->offset / op->s->granularity;
48
+ bool base_read_only;
26
uint64_t end_chunk = DIV_ROUND_UP(op->offset + op->bytes,
49
Error *local_err = NULL;
50
51
- orig_base_flags = bdrv_get_flags(base);
52
+ base_read_only = bdrv_is_read_only(base);
53
54
- if (bdrv_reopen(base, bs->open_flags, errp)) {
55
- return;
56
+ if (base_read_only) {
57
+ if (bdrv_reopen_set_read_only(base, false, errp) < 0) {
58
+ return;
59
+ }
60
}
61
62
mirror_start_job(job_id, bs, creation_flags, base, NULL, speed, 0, 0,
63
@@ -XXX,XX +XXX,XX @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
64
error_restore_flags:
65
/* ignore error and errp for bdrv_reopen, because we want to propagate
66
* the original error */
67
- bdrv_reopen(base, orig_base_flags, NULL);
68
+ if (base_read_only) {
69
+ bdrv_reopen_set_read_only(base, true, NULL);
70
+ }
71
return;
72
}
73
--
27
--
74
2.19.2
28
2.40.1
75
76
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
No one is using this function anymore, so we can safely remove it.
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
bdrv_co_get_allocated_file_size() need to hold a reader lock for the
5
graph.
4
6
5
Signed-off-by: Alberto Garcia <berto@igalia.com>
7
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
6
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Reviewed-by: Eric Blake <eblake@redhat.com>
10
Message-Id: <20230504115750.54437-14-kwolf@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
13
---
9
include/block/block.h | 1 -
14
include/block/block-io.h | 7 +++++--
10
block.c | 21 ---------------------
15
include/block/block_int-common.h | 2 +-
11
2 files changed, 22 deletions(-)
16
block.c | 4 +++-
17
block/vmdk.c | 2 +-
18
4 files changed, 10 insertions(+), 5 deletions(-)
12
19
13
diff --git a/include/block/block.h b/include/block/block.h
20
diff --git a/include/block/block-io.h b/include/block/block-io.h
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/include/block/block.h
22
--- a/include/block/block-io.h
16
+++ b/include/block/block.h
23
+++ b/include/block/block-io.h
17
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
24
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_mixed_fn bdrv_nb_sectors(BlockDriverState *bs);
18
BlockDriverState *bs,
25
int64_t coroutine_fn GRAPH_RDLOCK bdrv_co_getlength(BlockDriverState *bs);
19
QDict *options, int flags);
26
int64_t co_wrapper_mixed_bdrv_rdlock bdrv_getlength(BlockDriverState *bs);
20
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
27
21
-int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
28
-int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs);
22
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
29
-int64_t co_wrapper bdrv_get_allocated_file_size(BlockDriverState *bs);
23
Error **errp);
30
+int64_t coroutine_fn GRAPH_RDLOCK
24
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
31
+bdrv_co_get_allocated_file_size(BlockDriverState *bs);
32
+
33
+int64_t co_wrapper_bdrv_rdlock
34
+bdrv_get_allocated_file_size(BlockDriverState *bs);
35
36
BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
37
BlockDriverState *in_bs, Error **errp);
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
int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_getlength)(
44
BlockDriverState *bs);
45
46
- int64_t coroutine_fn (*bdrv_co_get_allocated_file_size)(
47
+ int64_t coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_get_allocated_file_size)(
48
BlockDriverState *bs);
49
50
BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in_bs,
25
diff --git a/block.c b/block.c
51
diff --git a/block.c b/block.c
26
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
27
--- a/block.c
53
--- a/block.c
28
+++ b/block.c
54
+++ b/block.c
29
@@ -XXX,XX +XXX,XX @@ cleanup:
55
@@ -XXX,XX +XXX,XX @@ exit:
30
return ret;
56
* sums the size of all data-bearing children. (This excludes backing
57
* children.)
58
*/
59
-static int64_t coroutine_fn bdrv_sum_allocated_file_size(BlockDriverState *bs)
60
+static int64_t coroutine_fn GRAPH_RDLOCK
61
+bdrv_sum_allocated_file_size(BlockDriverState *bs)
62
{
63
BdrvChild *child;
64
int64_t child_size, sum = 0;
65
@@ -XXX,XX +XXX,XX @@ int64_t coroutine_fn bdrv_co_get_allocated_file_size(BlockDriverState *bs)
66
{
67
BlockDriver *drv = bs->drv;
68
IO_CODE();
69
+ assert_bdrv_graph_readable();
70
71
if (!drv) {
72
return -ENOMEDIUM;
73
diff --git a/block/vmdk.c b/block/vmdk.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/block/vmdk.c
76
+++ b/block/vmdk.c
77
@@ -XXX,XX +XXX,XX @@ static void vmdk_close(BlockDriverState *bs)
78
error_free(s->migration_blocker);
31
}
79
}
32
80
33
-
81
-static int64_t coroutine_fn
34
-/* Reopen a single BlockDriverState with the specified flags. */
82
+static int64_t coroutine_fn GRAPH_RDLOCK
35
-int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
83
vmdk_co_get_allocated_file_size(BlockDriverState *bs)
36
-{
37
- int ret = -1;
38
- Error *local_err = NULL;
39
- BlockReopenQueue *queue;
40
-
41
- bdrv_subtree_drained_begin(bs);
42
-
43
- queue = bdrv_reopen_queue(NULL, bs, NULL, bdrv_flags);
44
- ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, &local_err);
45
- if (local_err != NULL) {
46
- error_propagate(errp, local_err);
47
- }
48
-
49
- bdrv_subtree_drained_end(bs);
50
-
51
- return ret;
52
-}
53
-
54
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
55
Error **errp)
56
{
84
{
85
int i;
57
--
86
--
58
2.19.2
87
2.40.1
59
60
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Most callers of bdrv_reopen() only use it to switch a BlockDriverState
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
between read-only and read-write, so this patch adds a new function
4
bdrv_co_get_info() need to hold a reader lock for the graph.
5
that does just that.
6
5
7
We also want to get rid of the flags parameter in the bdrv_reopen()
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
8
API, so this function sets the "read-only" option and passes the
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
original flags (which will then be updated in bdrv_reopen_prepare()).
8
Reviewed-by: Eric Blake <eblake@redhat.com>
10
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
11
Signed-off-by: Alberto Garcia <berto@igalia.com>
10
Message-Id: <20230504115750.54437-15-kwolf@redhat.com>
12
Reviewed-by: Max Reitz <mreitz@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
---
12
---
15
include/block/block.h | 2 ++
13
include/block/block-io.h | 7 +++++--
16
block.c | 17 +++++++++++++++++
14
include/block/block_int-common.h | 4 ++--
17
2 files changed, 19 insertions(+)
15
block.c | 2 ++
16
block/crypto.c | 2 +-
17
block/io.c | 11 +++++------
18
block/mirror.c | 8 ++++++--
19
block/raw-format.c | 2 +-
20
7 files changed, 22 insertions(+), 14 deletions(-)
18
21
19
diff --git a/include/block/block.h b/include/block/block.h
22
diff --git a/include/block/block-io.h b/include/block/block-io.h
20
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
21
--- a/include/block/block.h
24
--- a/include/block/block-io.h
22
+++ b/include/block/block.h
25
+++ b/include/block/block-io.h
23
@@ -XXX,XX +XXX,XX @@ BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
26
@@ -XXX,XX +XXX,XX @@ const char *bdrv_get_node_name(const BlockDriverState *bs);
24
QDict *options, int flags);
27
const char *bdrv_get_device_name(const BlockDriverState *bs);
25
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
28
const char *bdrv_get_device_or_node_name(const BlockDriverState *bs);
26
int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp);
29
27
+int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
30
-int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
28
+ Error **errp);
31
-int co_wrapper_mixed bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
29
int bdrv_reopen_prepare(BDRVReopenState *reopen_state,
32
+int coroutine_fn GRAPH_RDLOCK
30
BlockReopenQueue *queue, Error **errp);
33
+bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
31
void bdrv_reopen_commit(BDRVReopenState *reopen_state);
34
+
35
+int co_wrapper_mixed_bdrv_rdlock
36
+bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi);
37
38
ImageInfoSpecific *bdrv_get_specific_info(BlockDriverState *bs,
39
Error **errp);
40
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int-common.h
43
+++ b/include/block/block_int-common.h
44
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
45
BlockDriverState *bs, int64_t offset, int64_t bytes,
46
QEMUIOVector *qiov, size_t qiov_offset);
47
48
- int coroutine_fn (*bdrv_co_get_info)(BlockDriverState *bs,
49
- BlockDriverInfo *bdi);
50
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_get_info)(
51
+ BlockDriverState *bs, BlockDriverInfo *bdi);
52
53
ImageInfoSpecific *(*bdrv_get_specific_info)(BlockDriverState *bs,
54
Error **errp);
32
diff --git a/block.c b/block.c
55
diff --git a/block.c b/block.c
33
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
34
--- a/block.c
57
--- a/block.c
35
+++ b/block.c
58
+++ b/block.c
36
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen(BlockDriverState *bs, int bdrv_flags, Error **errp)
59
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
60
int ret;
61
BlockDriver *drv = bs->drv;
62
IO_CODE();
63
+ assert_bdrv_graph_readable();
64
+
65
/* if bs->drv == NULL, bs is closed, so there's nothing to do here */
66
if (!drv) {
67
return -ENOMEDIUM;
68
diff --git a/block/crypto.c b/block/crypto.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/crypto.c
71
+++ b/block/crypto.c
72
@@ -XXX,XX +XXX,XX @@ fail:
37
return ret;
73
return ret;
38
}
74
}
39
75
40
+int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
76
-static int coroutine_fn
41
+ Error **errp)
77
+static int coroutine_fn GRAPH_RDLOCK
42
+{
78
block_crypto_co_get_info_luks(BlockDriverState *bs, BlockDriverInfo *bdi)
43
+ int ret;
44
+ BlockReopenQueue *queue;
45
+ QDict *opts = qdict_new();
46
+
47
+ qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
48
+
49
+ bdrv_subtree_drained_begin(bs);
50
+ queue = bdrv_reopen_queue(NULL, bs, opts, bdrv_get_flags(bs));
51
+ ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
52
+ bdrv_subtree_drained_end(bs);
53
+
54
+ return ret;
55
+}
56
+
57
static BlockReopenQueueEntry *find_parent_in_reopen_queue(BlockReopenQueue *q,
58
BdrvChild *c)
59
{
79
{
80
BlockDriverInfo subbdi;
81
diff --git a/block/io.c b/block/io.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/block/io.c
84
+++ b/block/io.c
85
@@ -XXX,XX +XXX,XX @@ BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs)
86
/**
87
* Round a region to cluster boundaries
88
*/
89
-void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
90
- int64_t offset, int64_t bytes,
91
- int64_t *cluster_offset,
92
- int64_t *cluster_bytes)
93
+void coroutine_fn GRAPH_RDLOCK
94
+bdrv_round_to_clusters(BlockDriverState *bs, int64_t offset, int64_t bytes,
95
+ int64_t *cluster_offset, int64_t *cluster_bytes)
96
{
97
BlockDriverInfo bdi;
98
IO_CODE();
99
@@ -XXX,XX +XXX,XX @@ void coroutine_fn bdrv_round_to_clusters(BlockDriverState *bs,
100
}
101
}
102
103
-static coroutine_fn int bdrv_get_cluster_size(BlockDriverState *bs)
104
+static int coroutine_fn GRAPH_RDLOCK bdrv_get_cluster_size(BlockDriverState *bs)
105
{
106
BlockDriverInfo bdi;
107
int ret;
108
@@ -XXX,XX +XXX,XX @@ fail:
109
return ret;
110
}
111
112
-static inline int coroutine_fn
113
+static inline int coroutine_fn GRAPH_RDLOCK
114
bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
115
BdrvTrackedRequest *req, int flags)
116
{
117
diff --git a/block/mirror.c b/block/mirror.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/block/mirror.c
120
+++ b/block/mirror.c
121
@@ -XXX,XX +XXX,XX @@ static uint64_t coroutine_fn mirror_iteration(MirrorBlockJob *s)
122
} else if (ret >= 0 && !(ret & BDRV_BLOCK_DATA)) {
123
int64_t target_offset;
124
int64_t target_bytes;
125
- bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
126
- &target_offset, &target_bytes);
127
+ WITH_GRAPH_RDLOCK_GUARD() {
128
+ bdrv_round_to_clusters(blk_bs(s->target), offset, io_bytes,
129
+ &target_offset, &target_bytes);
130
+ }
131
if (target_offset == offset &&
132
target_bytes == io_bytes) {
133
mirror_method = ret & BDRV_BLOCK_ZERO ?
134
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn mirror_run(Job *job, Error **errp)
135
*/
136
bdrv_get_backing_filename(target_bs, backing_filename,
137
sizeof(backing_filename));
138
+ bdrv_graph_co_rdlock();
139
if (!bdrv_co_get_info(target_bs, &bdi) && bdi.cluster_size) {
140
s->target_cluster_size = bdi.cluster_size;
141
} else {
142
s->target_cluster_size = BDRV_SECTOR_SIZE;
143
}
144
+ bdrv_graph_co_rdunlock();
145
if (backing_filename[0] && !bdrv_backing_chain_next(target_bs) &&
146
s->granularity < s->target_cluster_size) {
147
s->buf_size = MAX(s->buf_size, s->target_cluster_size);
148
diff --git a/block/raw-format.c b/block/raw-format.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/block/raw-format.c
151
+++ b/block/raw-format.c
152
@@ -XXX,XX +XXX,XX @@ static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_bs,
153
return info;
154
}
155
156
-static int coroutine_fn
157
+static int coroutine_fn GRAPH_RDLOCK
158
raw_co_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
159
{
160
return bdrv_co_get_info(bs->file->bs, bdi);
60
--
161
--
61
2.19.2
162
2.40.1
62
63
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
2
3
Now that all callers are passing all flag changes as QDict options,
3
This adds GRAPH_RDLOCK annotations to declare that callers of
4
the flags parameter is no longer necessary, so we can get rid of it.
4
bdrv_co_debug_event() need to hold a reader lock for the graph.
5
5
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
6
Unfortunately we cannot use a co_wrapper_bdrv_rdlock (i.e. make the
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
7
coroutine wrapper a no_coroutine_fn), because the function is called
8
(using the BLKDBG_EVENT macro) by mixed functions that run both in
9
coroutine and non-coroutine context (for example many of the functions
10
in qcow2-cluster.c and qcow2-refcount.c).
11
12
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
13
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
16
Message-Id: <20230504115750.54437-16-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
17
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
18
---
10
include/block/block.h | 3 +--
19
include/block/block-io.h | 9 +++++----
11
block.c | 5 +++--
20
include/block/block_int-common.h | 4 ++--
12
block/replication.c | 6 ++----
21
block.c | 2 ++
13
qemu-io-cmds.c | 2 +-
22
3 files changed, 9 insertions(+), 6 deletions(-)
14
4 files changed, 7 insertions(+), 9 deletions(-)
15
23
16
diff --git a/include/block/block.h b/include/block/block.h
24
diff --git a/include/block/block-io.h b/include/block/block-io.h
17
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
18
--- a/include/block/block.h
26
--- a/include/block/block-io.h
19
+++ b/include/block/block.h
27
+++ b/include/block/block-io.h
20
@@ -XXX,XX +XXX,XX @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
28
@@ -XXX,XX +XXX,XX @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size);
21
BlockDriverState *bdrv_new_open_driver(BlockDriver *drv, const char *node_name,
29
void bdrv_enable_copy_on_read(BlockDriverState *bs);
22
int flags, Error **errp);
30
void bdrv_disable_copy_on_read(BlockDriverState *bs);
23
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
31
24
- BlockDriverState *bs,
32
-void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs,
25
- QDict *options, int flags);
33
- BlkdebugEvent event);
26
+ BlockDriverState *bs, QDict *options);
34
-void co_wrapper_mixed bdrv_debug_event(BlockDriverState *bs,
27
int bdrv_reopen_multiple(AioContext *ctx, BlockReopenQueue *bs_queue, Error **errp);
35
- BlkdebugEvent event);
28
int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
36
+void coroutine_fn GRAPH_RDLOCK
29
Error **errp);
37
+bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event);
38
+
39
+void co_wrapper_mixed_bdrv_rdlock
40
+bdrv_debug_event(BlockDriverState *bs, BlkdebugEvent event);
41
42
#define BLKDBG_EVENT(child, evt) \
43
do { \
44
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
45
index XXXXXXX..XXXXXXX 100644
46
--- a/include/block/block_int-common.h
47
+++ b/include/block/block_int-common.h
48
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
49
int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_check)(
50
BlockDriverState *bs, BdrvCheckResult *result, BdrvCheckMode fix);
51
52
- void coroutine_fn (*bdrv_co_debug_event)(BlockDriverState *bs,
53
- BlkdebugEvent event);
54
+ void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_debug_event)(
55
+ BlockDriverState *bs, BlkdebugEvent event);
56
57
/* io queue for linux-aio */
58
void coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_io_plug)(BlockDriverState *bs);
30
diff --git a/block.c b/block.c
59
diff --git a/block.c b/block.c
31
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
32
--- a/block.c
61
--- a/block.c
33
+++ b/block.c
62
+++ b/block.c
34
@@ -XXX,XX +XXX,XX @@ static BlockReopenQueue *bdrv_reopen_queue_child(BlockReopenQueue *bs_queue,
63
@@ -XXX,XX +XXX,XX @@ BlockStatsSpecific *bdrv_get_specific_stats(BlockDriverState *bs)
35
64
void coroutine_fn bdrv_co_debug_event(BlockDriverState *bs, BlkdebugEvent event)
36
BlockReopenQueue *bdrv_reopen_queue(BlockReopenQueue *bs_queue,
37
BlockDriverState *bs,
38
- QDict *options, int flags)
39
+ QDict *options)
40
{
65
{
41
+ int flags = bdrv_get_flags(bs);
66
IO_CODE();
42
return bdrv_reopen_queue_child(bs_queue, bs, options, flags,
67
+ assert_bdrv_graph_readable();
43
NULL, NULL, 0);
68
+
44
}
69
if (!bs || !bs->drv || !bs->drv->bdrv_co_debug_event) {
45
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
70
return;
46
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, read_only);
47
48
bdrv_subtree_drained_begin(bs);
49
- queue = bdrv_reopen_queue(NULL, bs, opts, bdrv_get_flags(bs));
50
+ queue = bdrv_reopen_queue(NULL, bs, opts);
51
ret = bdrv_reopen_multiple(bdrv_get_aio_context(bs), queue, errp);
52
bdrv_subtree_drained_end(bs);
53
54
diff --git a/block/replication.c b/block/replication.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/replication.c
57
+++ b/block/replication.c
58
@@ -XXX,XX +XXX,XX @@ static void reopen_backing_file(BlockDriverState *bs, bool writable,
59
bdrv_subtree_drained_begin(s->secondary_disk->bs);
60
61
if (s->orig_hidden_read_only) {
62
- int flags = bdrv_get_flags(s->hidden_disk->bs);
63
QDict *opts = qdict_new();
64
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
65
reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs,
66
- opts, flags);
67
+ opts);
68
}
71
}
69
70
if (s->orig_secondary_read_only) {
71
- int flags = bdrv_get_flags(s->secondary_disk->bs);
72
QDict *opts = qdict_new();
73
qdict_put_bool(opts, BDRV_OPT_READ_ONLY, !writable);
74
reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
75
- opts, flags);
76
+ opts);
77
}
78
79
if (reopen_queue) {
80
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/qemu-io-cmds.c
83
+++ b/qemu-io-cmds.c
84
@@ -XXX,XX +XXX,XX @@ static int reopen_f(BlockBackend *blk, int argc, char **argv)
85
}
86
87
bdrv_subtree_drained_begin(bs);
88
- brq = bdrv_reopen_queue(NULL, bs, opts, flags);
89
+ brq = bdrv_reopen_queue(NULL, bs, opts);
90
bdrv_reopen_multiple(bdrv_get_aio_context(bs), brq, &local_err);
91
bdrv_subtree_drained_end(bs);
92
93
--
72
--
94
2.19.2
73
2.40.1
95
96
diff view generated by jsdifflib
1
aio_worker() doesn't add anything interesting, it's only a useless
1
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
2
indirection. Call the handler function directly instead.
3
2
4
As we know that this handler function is only called from coroutine
3
This adds GRAPH_RDLOCK annotations to declare that callers of amend
5
context and the coroutine stays around until the worker thread finishes,
4
callbacks in BlockDriver need to hold a reader lock for the graph.
6
we can keep RawPosixAIOData on the stack.
7
5
6
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20230504115750.54437-17-kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
12
---
10
block/file-posix.c | 12 ++++++------
13
include/block/block_int-common.h | 12 ++++++------
11
1 file changed, 6 insertions(+), 6 deletions(-)
14
block/amend.c | 8 +++++++-
15
2 files changed, 13 insertions(+), 7 deletions(-)
12
16
13
diff --git a/block/file-posix.c b/block/file-posix.c
17
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
19
--- a/include/block/block_int-common.h
16
+++ b/block/file-posix.c
20
+++ b/include/block/block_int-common.h
17
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
21
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
22
* to allow driver-specific initialization code that requires
23
* the BQL, like setting up specific permission flags.
24
*/
25
- int (*bdrv_amend_pre_run)(BlockDriverState *bs, Error **errp);
26
+ int GRAPH_RDLOCK_PTR (*bdrv_amend_pre_run)(
27
+ BlockDriverState *bs, Error **errp);
28
/*
29
* This function is invoked under BQL after .bdrv_co_amend()
30
* to allow cleaning up what was done in .bdrv_amend_pre_run().
31
*/
32
- void (*bdrv_amend_clean)(BlockDriverState *bs);
33
+ void GRAPH_RDLOCK_PTR (*bdrv_amend_clean)(BlockDriverState *bs);
34
35
/*
36
* Return true if @to_replace can be replaced by a BDS with the
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
39
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
40
41
- int coroutine_fn (*bdrv_co_amend)(BlockDriverState *bs,
42
- BlockdevAmendOptions *opts,
43
- bool force,
44
- Error **errp);
45
+ int coroutine_fn GRAPH_RDLOCK_PTR (*bdrv_co_amend)(
46
+ BlockDriverState *bs, BlockdevAmendOptions *opts, bool force,
47
+ Error **errp);
48
49
/* aio */
50
BlockAIOCB * GRAPH_RDLOCK_PTR (*bdrv_aio_preadv)(BlockDriverState *bs,
51
diff --git a/block/amend.c b/block/amend.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/amend.c
54
+++ b/block/amend.c
55
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
56
{
57
BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
58
int ret;
59
+ GRAPH_RDLOCK_GUARD();
60
61
job_progress_set_remaining(&s->common, 1);
62
ret = s->bs->drv->bdrv_co_amend(s->bs, s->opts, s->force, errp);
63
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn blockdev_amend_run(Job *job, Error **errp)
18
return ret;
64
return ret;
19
}
65
}
20
66
21
-static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
67
-static int blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
22
+static int handle_aiocb_truncate(void *opaque)
68
+static int GRAPH_RDLOCK
69
+blockdev_amend_pre_run(BlockdevAmendJob *s, Error **errp)
23
{
70
{
24
+ RawPosixAIOData *aiocb = opaque;
71
if (s->bs->drv->bdrv_amend_pre_run) {
25
int result = 0;
72
return s->bs->drv->bdrv_amend_pre_run(s->bs, errp);
26
int64_t current_length = 0;
73
@@ -XXX,XX +XXX,XX @@ static void blockdev_amend_free(Job *job)
27
char *buf = NULL;
28
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
29
ret = handle_aiocb_copy_range(aiocb);
30
break;
31
case QEMU_AIO_TRUNCATE:
32
- ret = handle_aiocb_truncate(aiocb);
33
- break;
34
+ g_assert_not_reached();
35
default:
36
error_report("invalid aio request (0x%x)", aiocb->aio_type);
37
ret = -EINVAL;
38
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
39
raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
40
PreallocMode prealloc, Error **errp)
41
{
74
{
42
- RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
75
BlockdevAmendJob *s = container_of(job, BlockdevAmendJob, common);
43
+ RawPosixAIOData acb;
76
44
77
+ bdrv_graph_rdlock_main_loop();
45
- *acb = (RawPosixAIOData) {
78
if (s->bs->drv->bdrv_amend_clean) {
46
+ acb = (RawPosixAIOData) {
79
s->bs->drv->bdrv_amend_clean(s->bs);
47
.bs = bs,
80
}
48
.aio_fildes = fd,
81
+ bdrv_graph_rdunlock_main_loop();
49
.aio_type = QEMU_AIO_TRUNCATE,
82
50
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
83
bdrv_unref(s->bs);
51
},
52
};
53
54
- return raw_thread_pool_submit(bs, aio_worker, acb);
55
+ return raw_thread_pool_submit(bs, handle_aiocb_truncate, &acb);
56
}
84
}
57
85
@@ -XXX,XX +XXX,XX @@ void qmp_x_blockdev_amend(const char *job_id,
58
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
86
BlockDriver *drv = bdrv_find_format(fmt);
87
BlockDriverState *bs;
88
89
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
90
+
91
bs = bdrv_lookup_bs(NULL, node_name, errp);
92
if (!bs) {
93
return;
59
--
94
--
60
2.19.2
95
2.40.1
61
62
diff view generated by jsdifflib
1
No real reason to keep using the callback based mechanism here when the
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
rest of the file-posix driver is coroutine based. Changing it brings
2
bdrv_query_bds_stats() need to hold a reader lock for the graph because
3
ioctls more in line with how other request types work.
3
it accesses the children list of a node.
4
4
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20230504115750.54437-18-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
10
---
7
include/scsi/pr-manager.h | 8 +++-----
11
block/qapi.c | 6 ++++--
8
block/file-posix.c | 21 +++++++++++----------
12
1 file changed, 4 insertions(+), 2 deletions(-)
9
scsi/pr-manager.c | 21 +++++++++------------
10
scsi/trace-events | 2 +-
11
4 files changed, 24 insertions(+), 28 deletions(-)
12
13
13
diff --git a/include/scsi/pr-manager.h b/include/scsi/pr-manager.h
14
diff --git a/block/qapi.c b/block/qapi.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/include/scsi/pr-manager.h
16
--- a/block/qapi.c
16
+++ b/include/scsi/pr-manager.h
17
+++ b/block/qapi.c
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
18
#include "qapi/visitor.h"
19
= bdrv_latency_histogram_stats(&hgram[BLOCK_ACCT_FLUSH]);
19
#include "qom/object_interfaces.h"
20
#include "block/aio.h"
21
+#include "qemu/coroutine.h"
22
23
#define TYPE_PR_MANAGER "pr-manager"
24
25
@@ -XXX,XX +XXX,XX @@ typedef struct PRManagerClass {
26
} PRManagerClass;
27
28
bool pr_manager_is_connected(PRManager *pr_mgr);
29
-BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
30
- AioContext *ctx, int fd,
31
- struct sg_io_hdr *hdr,
32
- BlockCompletionFunc *complete,
33
- void *opaque);
34
+int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
35
+ struct sg_io_hdr *hdr);
36
37
PRManager *pr_manager_lookup(const char *id, Error **errp);
38
39
diff --git a/block/file-posix.c b/block/file-posix.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/file-posix.c
42
+++ b/block/file-posix.c
43
@@ -XXX,XX +XXX,XX @@ hdev_open_Mac_error:
44
}
20
}
45
21
46
#if defined(__linux__)
22
-static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
47
-
23
- bool blk_level)
48
-static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
24
+static BlockStats * GRAPH_RDLOCK
49
- unsigned long int req, void *buf,
25
+bdrv_query_bds_stats(BlockDriverState *bs, bool blk_level)
50
- BlockCompletionFunc *cb, void *opaque)
51
+static int coroutine_fn
52
+hdev_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
53
{
26
{
54
BDRVRawState *s = bs->opaque;
27
BdrvChild *parent_child;
55
RawPosixAIOData *acb;
28
BlockDriverState *filter_or_cow_bs;
56
ThreadPool *pool;
29
@@ -XXX,XX +XXX,XX @@ BlockStatsList *qmp_query_blockstats(bool has_query_nodes,
57
+ int ret;
30
BlockBackend *blk;
58
31
BlockDriverState *bs;
59
- if (fd_open(bs) < 0)
32
60
- return NULL;
33
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
61
+ ret = fd_open(bs);
34
+
62
+ if (ret < 0) {
35
/* Just to be safe if query_nodes is not always initialized */
63
+ return ret;
36
if (has_query_nodes && query_nodes) {
64
+ }
37
for (bs = bdrv_next_node(NULL); bs; bs = bdrv_next_node(bs)) {
65
66
if (req == SG_IO && s->pr_mgr) {
67
struct sg_io_hdr *io_hdr = buf;
68
if (io_hdr->cmdp[0] == PERSISTENT_RESERVE_OUT ||
69
io_hdr->cmdp[0] == PERSISTENT_RESERVE_IN) {
70
return pr_manager_execute(s->pr_mgr, bdrv_get_aio_context(bs),
71
- s->fd, io_hdr, cb, opaque);
72
+ s->fd, io_hdr);
73
}
74
}
75
76
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
77
acb->ioctl.buf = buf;
78
acb->ioctl.cmd = req;
79
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
80
- return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
81
+ return thread_pool_submit_co(pool, aio_worker, acb);
82
}
83
#endif /* linux */
84
85
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_device = {
86
87
/* generic scsi device */
88
#ifdef __linux__
89
- .bdrv_aio_ioctl = hdev_aio_ioctl,
90
+ .bdrv_co_ioctl = hdev_co_ioctl,
91
#endif
92
};
93
94
@@ -XXX,XX +XXX,XX @@ static BlockDriver bdrv_host_cdrom = {
95
.bdrv_lock_medium = cdrom_lock_medium,
96
97
/* generic scsi device */
98
- .bdrv_aio_ioctl = hdev_aio_ioctl,
99
+ .bdrv_co_ioctl = hdev_co_ioctl,
100
};
101
#endif /* __linux__ */
102
103
diff --git a/scsi/pr-manager.c b/scsi/pr-manager.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/scsi/pr-manager.c
106
+++ b/scsi/pr-manager.c
107
@@ -XXX,XX +XXX,XX @@ static int pr_manager_worker(void *opaque)
108
}
109
110
111
-BlockAIOCB *pr_manager_execute(PRManager *pr_mgr,
112
- AioContext *ctx, int fd,
113
- struct sg_io_hdr *hdr,
114
- BlockCompletionFunc *complete,
115
- void *opaque)
116
+int coroutine_fn pr_manager_execute(PRManager *pr_mgr, AioContext *ctx, int fd,
117
+ struct sg_io_hdr *hdr)
118
{
119
- PRManagerData *data = g_new(PRManagerData, 1);
120
ThreadPool *pool = aio_get_thread_pool(ctx);
121
+ PRManagerData data = {
122
+ .pr_mgr = pr_mgr,
123
+ .fd = fd,
124
+ .hdr = hdr,
125
+ };
126
127
- trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1], opaque);
128
- data->pr_mgr = pr_mgr;
129
- data->fd = fd;
130
- data->hdr = hdr;
131
+ trace_pr_manager_execute(fd, hdr->cmdp[0], hdr->cmdp[1]);
132
133
/* The matching object_unref is in pr_manager_worker. */
134
object_ref(OBJECT(pr_mgr));
135
- return thread_pool_submit_aio(pool, pr_manager_worker,
136
- data, complete, opaque);
137
+ return thread_pool_submit_co(pool, pr_manager_worker, &data);
138
}
139
140
bool pr_manager_is_connected(PRManager *pr_mgr)
141
diff --git a/scsi/trace-events b/scsi/trace-events
142
index XXXXXXX..XXXXXXX 100644
143
--- a/scsi/trace-events
144
+++ b/scsi/trace-events
145
@@ -XXX,XX +XXX,XX @@
146
# scsi/pr-manager.c
147
-pr_manager_execute(int fd, int cmd, int sa, void *opaque) "fd=%d cmd=0x%02x service action=0x%02x opaque=%p"
148
+pr_manager_execute(int fd, int cmd, int sa) "fd=%d cmd=0x%02x service action=0x%02x"
149
pr_manager_run(int fd, int cmd, int sa) "fd=%d cmd=0x%02x service action=0x%02x"
150
--
38
--
151
2.19.2
39
2.40.1
152
153
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_query_block_graph_info() need to hold a reader lock for the graph
3
because it accesses the children list of a node.
2
4
3
This patch replaces the bdrv_reopen() calls that set and remove the
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Message-Id: <20230504115750.54437-19-kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block/commit.c | 16 ++++++----------
11
include/block/qapi.h | 7 ++++---
11
1 file changed, 6 insertions(+), 10 deletions(-)
12
qemu-img.c | 2 ++
13
2 files changed, 6 insertions(+), 3 deletions(-)
12
14
13
diff --git a/block/commit.c b/block/commit.c
15
diff --git a/include/block/qapi.h b/include/block/qapi.h
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/block/commit.c
17
--- a/include/block/qapi.h
16
+++ b/block/commit.c
18
+++ b/include/block/qapi.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct CommitBlockJob {
19
@@ -XXX,XX +XXX,XX @@
18
BlockBackend *base;
20
#ifndef BLOCK_QAPI_H
19
BlockDriverState *base_bs;
21
#define BLOCK_QAPI_H
20
BlockdevOnError on_error;
22
21
- int base_flags;
23
+#include "block/graph-lock.h"
22
+ bool base_read_only;
24
#include "block/snapshot.h"
23
char *backing_file_str;
25
#include "qapi/qapi-types-block-core.h"
24
} CommitBlockJob;
26
25
27
@@ -XXX,XX +XXX,XX @@ void bdrv_query_image_info(BlockDriverState *bs,
26
@@ -XXX,XX +XXX,XX @@ static void commit_clean(Job *job)
28
bool flat,
27
/* restore base open flags here if appropriate (e.g., change the base back
29
bool skip_implicit_filters,
28
* to r/o). These reopens do not need to be atomic, since we won't abort
30
Error **errp);
29
* even on failure here */
31
-void bdrv_query_block_graph_info(BlockDriverState *bs,
30
- if (s->base_flags != bdrv_get_flags(s->base_bs)) {
32
- BlockGraphInfo **p_info,
31
- bdrv_reopen(s->base_bs, s->base_flags, NULL);
33
- Error **errp);
32
+ if (s->base_read_only) {
34
+void GRAPH_RDLOCK
33
+ bdrv_reopen_set_read_only(s->base_bs, true, NULL);
35
+bdrv_query_block_graph_info(BlockDriverState *bs, BlockGraphInfo **p_info,
34
}
36
+ Error **errp);
35
37
36
g_free(s->backing_file_str);
38
void bdrv_snapshot_dump(QEMUSnapshotInfo *sn);
37
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
39
void bdrv_image_info_specific_dump(ImageInfoSpecific *info_spec,
38
const char *filter_node_name, Error **errp)
40
diff --git a/qemu-img.c b/qemu-img.c
39
{
41
index XXXXXXX..XXXXXXX 100644
40
CommitBlockJob *s;
42
--- a/qemu-img.c
41
- int orig_base_flags;
43
+++ b/qemu-img.c
42
BlockDriverState *iter;
44
@@ -XXX,XX +XXX,XX @@ static BlockGraphInfoList *collect_image_info_list(bool image_opts,
43
BlockDriverState *commit_top_bs = NULL;
44
Error *local_err = NULL;
45
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
46
}
47
48
/* convert base to r/w, if necessary */
49
- orig_base_flags = bdrv_get_flags(base);
50
- if (!(orig_base_flags & BDRV_O_RDWR)) {
51
- bdrv_reopen(base, orig_base_flags | BDRV_O_RDWR, &local_err);
52
- if (local_err != NULL) {
53
- error_propagate(errp, local_err);
54
+ s->base_read_only = bdrv_is_read_only(base);
55
+ if (s->base_read_only) {
56
+ if (bdrv_reopen_set_read_only(base, false, errp) != 0) {
57
goto fail;
58
}
45
}
59
}
46
bs = blk_bs(blk);
60
@@ -XXX,XX +XXX,XX @@ void commit_start(const char *job_id, BlockDriverState *bs,
47
61
goto fail;
48
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
62
}
49
+
63
50
/*
64
- s->base_flags = orig_base_flags;
51
* Note that the returned BlockGraphInfo object will not have
65
s->backing_file_str = g_strdup(backing_file_str);
52
* information about this image's backing node, because we have opened
66
s->on_error = on_error;
67
68
--
53
--
69
2.19.2
54
2.40.1
70
71
diff view generated by jsdifflib
1
aio_worker() doesn't add anything interesting, it's only a useless
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
indirection. Call the handler function directly instead.
2
bdrv_recurse_can_replace() need to hold a reader lock for the graph
3
3
because it accesses the children list of a node.
4
As we know that this handler function is only called from coroutine
5
context and the coroutine stays around until the worker thread finishes,
6
we can keep RawPosixAIOData on the stack.
7
8
This was the last user of aio_worker(), so the function goes away now.
9
4
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
Reviewed-by: Eric Blake <eblake@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20230504115750.54437-20-kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
10
---
12
block/file-posix.c | 55 +++++++++++++---------------------------------
11
include/block/block-global-state.h | 5 +++--
13
1 file changed, 15 insertions(+), 40 deletions(-)
12
include/block/block_int-common.h | 4 ++--
13
include/block/block_int-global-state.h | 4 ++--
14
block/blkverify.c | 5 +++--
15
block/mirror.c | 4 ++++
16
block/quorum.c | 4 ++--
17
blockdev.c | 3 +++
18
7 files changed, 19 insertions(+), 10 deletions(-)
14
19
15
diff --git a/block/file-posix.c b/block/file-posix.c
20
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
22
--- a/include/block/block-global-state.h
18
+++ b/block/file-posix.c
23
+++ b/include/block/block-global-state.h
19
@@ -XXX,XX +XXX,XX @@ static int hdev_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
24
@@ -XXX,XX +XXX,XX @@ int bdrv_amend_options(BlockDriverState *bs_new, QemuOpts *opts,
25
Error **errp);
26
27
/* check if a named node can be replaced when doing drive-mirror */
28
-BlockDriverState *check_to_replace_node(BlockDriverState *parent_bs,
29
- const char *node_name, Error **errp);
30
+BlockDriverState * GRAPH_RDLOCK
31
+check_to_replace_node(BlockDriverState *parent_bs, const char *node_name,
32
+ Error **errp);
33
34
int no_coroutine_fn bdrv_activate(BlockDriverState *bs, Error **errp);
35
36
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/block/block_int-common.h
39
+++ b/include/block/block_int-common.h
40
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
41
* same data as @bs without it affecting @bs's behavior (that is,
42
* without it being visible to @bs's parents).
43
*/
44
- bool (*bdrv_recurse_can_replace)(BlockDriverState *bs,
45
- BlockDriverState *to_replace);
46
+ bool GRAPH_RDLOCK_PTR (*bdrv_recurse_can_replace)(
47
+ BlockDriverState *bs, BlockDriverState *to_replace);
48
49
int (*bdrv_probe_device)(const char *filename);
50
51
diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/include/block/block_int-global-state.h
54
+++ b/include/block/block_int-global-state.h
55
@@ -XXX,XX +XXX,XX @@ int bdrv_child_try_set_perm(BdrvChild *c, uint64_t perm, uint64_t shared,
56
*/
57
int bdrv_child_refresh_perms(BlockDriverState *bs, BdrvChild *c, Error **errp);
58
59
-bool bdrv_recurse_can_replace(BlockDriverState *bs,
60
- BlockDriverState *to_replace);
61
+bool GRAPH_RDLOCK bdrv_recurse_can_replace(BlockDriverState *bs,
62
+ BlockDriverState *to_replace);
63
64
/*
65
* Default implementation for BlockDriver.bdrv_child_perm() that can
66
diff --git a/block/blkverify.c b/block/blkverify.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/blkverify.c
69
+++ b/block/blkverify.c
70
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn GRAPH_RDLOCK blkverify_co_flush(BlockDriverState *bs)
71
return bdrv_co_flush(s->test_file->bs);
20
}
72
}
21
#endif
73
22
74
-static bool blkverify_recurse_can_replace(BlockDriverState *bs,
23
-static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
75
- BlockDriverState *to_replace)
24
+static int handle_aiocb_ioctl(void *opaque)
76
+static bool GRAPH_RDLOCK
77
+blkverify_recurse_can_replace(BlockDriverState *bs,
78
+ BlockDriverState *to_replace)
25
{
79
{
26
+ RawPosixAIOData *aiocb = opaque;
80
BDRVBlkverifyState *s = bs->opaque;
27
int ret;
81
28
82
diff --git a/block/mirror.c b/block/mirror.c
29
ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf);
83
index XXXXXXX..XXXXXXX 100644
30
@@ -XXX,XX +XXX,XX @@ out:
84
--- a/block/mirror.c
85
+++ b/block/mirror.c
86
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
87
* Cannot use check_to_replace_node() here, because that would
88
* check for an op blocker on @to_replace, and we have our own
89
* there.
90
+ *
91
+ * TODO Pull out the writer lock from bdrv_replace_node() to here
92
*/
93
+ bdrv_graph_rdlock_main_loop();
94
if (bdrv_recurse_can_replace(src, to_replace)) {
95
bdrv_replace_node(to_replace, target_bs, &local_err);
96
} else {
97
@@ -XXX,XX +XXX,XX @@ static int mirror_exit_common(Job *job)
98
"would not lead to an abrupt change of visible data",
99
to_replace->node_name, target_bs->node_name);
100
}
101
+ bdrv_graph_rdunlock_main_loop();
102
bdrv_drained_end(target_bs);
103
if (local_err) {
104
error_report_err(local_err);
105
diff --git a/block/quorum.c b/block/quorum.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/block/quorum.c
108
+++ b/block/quorum.c
109
@@ -XXX,XX +XXX,XX @@ static coroutine_fn GRAPH_RDLOCK int quorum_co_flush(BlockDriverState *bs)
31
return result;
110
return result;
32
}
111
}
33
112
34
-static int aio_worker(void *arg)
113
-static bool quorum_recurse_can_replace(BlockDriverState *bs,
35
-{
114
- BlockDriverState *to_replace)
36
- RawPosixAIOData *aiocb = arg;
115
+static bool GRAPH_RDLOCK
37
- ssize_t ret = 0;
116
+quorum_recurse_can_replace(BlockDriverState *bs, BlockDriverState *to_replace)
38
-
39
- switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
40
- case QEMU_AIO_IOCTL:
41
- ret = handle_aiocb_ioctl(aiocb);
42
- break;
43
- case QEMU_AIO_READ:
44
- case QEMU_AIO_WRITE:
45
- case QEMU_AIO_FLUSH:
46
- case QEMU_AIO_DISCARD:
47
- case QEMU_AIO_WRITE_ZEROES:
48
- case QEMU_AIO_WRITE_ZEROES | QEMU_AIO_DISCARD:
49
- case QEMU_AIO_COPY_RANGE:
50
- case QEMU_AIO_TRUNCATE:
51
- g_assert_not_reached();
52
- default:
53
- error_report("invalid aio request (0x%x)", aiocb->aio_type);
54
- ret = -EINVAL;
55
- break;
56
- }
57
-
58
- g_free(aiocb);
59
- return ret;
60
-}
61
-
62
static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
63
ThreadPoolFunc func, void *arg)
64
{
117
{
65
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn
118
BDRVQuorumState *s = bs->opaque;
66
hdev_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
119
int i;
67
{
120
diff --git a/blockdev.c b/blockdev.c
68
BDRVRawState *s = bs->opaque;
121
index XXXXXXX..XXXXXXX 100644
69
- RawPosixAIOData *acb;
122
--- a/blockdev.c
70
- ThreadPool *pool;
123
+++ b/blockdev.c
71
+ RawPosixAIOData acb;
124
@@ -XXX,XX +XXX,XX @@ static void blockdev_mirror_common(const char *job_id, BlockDriverState *bs,
72
int ret;
125
BlockDriverState *unfiltered_bs;
73
126
int job_flags = JOB_DEFAULT;
74
ret = fd_open(bs);
127
75
@@ -XXX,XX +XXX,XX @@ hdev_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
128
+ GLOBAL_STATE_CODE();
76
}
129
+ GRAPH_RDLOCK_GUARD_MAINLOOP();
130
+
131
if (!has_speed) {
132
speed = 0;
77
}
133
}
78
79
- acb = g_new(RawPosixAIOData, 1);
80
- acb->bs = bs;
81
- acb->aio_type = QEMU_AIO_IOCTL;
82
- acb->aio_fildes = s->fd;
83
- acb->aio_offset = 0;
84
- acb->ioctl.buf = buf;
85
- acb->ioctl.cmd = req;
86
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
87
- return thread_pool_submit_co(pool, aio_worker, acb);
88
+ acb = (RawPosixAIOData) {
89
+ .bs = bs,
90
+ .aio_type = QEMU_AIO_IOCTL,
91
+ .aio_fildes = s->fd,
92
+ .aio_offset = 0,
93
+ .ioctl = {
94
+ .buf = buf,
95
+ .cmd = req,
96
+ },
97
+ };
98
+
99
+ return raw_thread_pool_submit(bs, handle_aiocb_ioctl, &acb);
100
}
101
#endif /* linux */
102
103
--
134
--
104
2.19.2
135
2.40.1
105
106
diff view generated by jsdifflib
1
From: Alberto Garcia <berto@igalia.com>
1
This adds GRAPH_RDLOCK annotations to declare that callers of
2
bdrv_refresh_limits() need to hold a reader lock for the graph because
3
it accesses the children list of a node.
2
4
3
This patch replaces the bdrv_reopen() calls that set and remove the
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
BDRV_O_RDWR flag with the new bdrv_reopen_set_read_only() function.
6
Reviewed-by: Eric Blake <eblake@redhat.com>
5
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Alberto Garcia <berto@igalia.com>
8
Message-Id: <20230504115750.54437-21-kwolf@redhat.com>
7
Reviewed-by: Max Reitz <mreitz@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
---
10
block.c | 10 +++++-----
11
include/block/block-global-state.h | 5 ++++-
11
1 file changed, 5 insertions(+), 5 deletions(-)
12
include/block/block_int-common.h | 3 ++-
13
block.c | 9 +++++++++
14
block/io.c | 1 -
15
4 files changed, 15 insertions(+), 3 deletions(-)
12
16
17
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block-global-state.h
20
+++ b/include/block/block-global-state.h
21
@@ -XXX,XX +XXX,XX @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
22
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
23
const char *backing_file);
24
void bdrv_refresh_filename(BlockDriverState *bs);
25
-void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
26
+
27
+void GRAPH_RDLOCK
28
+bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp);
29
+
30
int bdrv_commit(BlockDriverState *bs);
31
int bdrv_make_empty(BdrvChild *c, Error **errp);
32
int bdrv_change_backing_file(BlockDriverState *bs, const char *backing_file,
33
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/block/block_int-common.h
36
+++ b/include/block/block_int-common.h
37
@@ -XXX,XX +XXX,XX @@ struct BlockDriver {
38
int (*bdrv_debug_resume)(BlockDriverState *bs, const char *tag);
39
bool (*bdrv_debug_is_suspended)(BlockDriverState *bs, const char *tag);
40
41
- void (*bdrv_refresh_limits)(BlockDriverState *bs, Error **errp);
42
+ void GRAPH_RDLOCK_PTR (*bdrv_refresh_limits)(
43
+ BlockDriverState *bs, Error **errp);
44
45
/*
46
* Returns 1 if newly created images are guaranteed to contain only
13
diff --git a/block.c b/block.c
47
diff --git a/block.c b/block.c
14
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
15
--- a/block.c
49
--- a/block.c
16
+++ b/block.c
50
+++ b/block.c
17
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
51
@@ -XXX,XX +XXX,XX @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
18
const char *filename, Error **errp)
52
return ret;
19
{
20
BlockDriverState *parent = c->opaque;
21
- int orig_flags = bdrv_get_flags(parent);
22
+ bool read_only = bdrv_is_read_only(parent);
23
int ret;
24
25
- if (!(orig_flags & BDRV_O_RDWR)) {
26
- ret = bdrv_reopen(parent, orig_flags | BDRV_O_RDWR, errp);
27
+ if (read_only) {
28
+ ret = bdrv_reopen_set_read_only(parent, false, errp);
29
if (ret < 0) {
30
return ret;
31
}
32
@@ -XXX,XX +XXX,XX @@ static int bdrv_backing_update_filename(BdrvChild *c, BlockDriverState *base,
33
error_setg_errno(errp, -ret, "Could not update backing file link");
34
}
53
}
35
54
36
- if (!(orig_flags & BDRV_O_RDWR)) {
55
+ bdrv_graph_rdlock_main_loop();
37
- bdrv_reopen(parent, orig_flags, NULL);
56
bdrv_refresh_limits(bs, NULL, &local_err);
38
+ if (read_only) {
57
+ bdrv_graph_rdunlock_main_loop();
39
+ bdrv_reopen_set_read_only(parent, true, NULL);
58
+
59
if (local_err) {
60
error_propagate(errp, local_err);
61
return -EINVAL;
62
@@ -XXX,XX +XXX,XX @@ static int bdrv_set_file_or_backing_noperm(BlockDriverState *parent_bs,
40
}
63
}
41
64
42
return ret;
65
out:
66
+ bdrv_graph_rdlock_main_loop();
67
bdrv_refresh_limits(parent_bs, tran, NULL);
68
+ bdrv_graph_rdunlock_main_loop();
69
70
return 0;
71
}
72
@@ -XXX,XX +XXX,XX @@ static void bdrv_reopen_commit(BDRVReopenState *reopen_state)
73
qdict_del(bs->explicit_options, "backing");
74
qdict_del(bs->options, "backing");
75
76
+ bdrv_graph_rdlock_main_loop();
77
bdrv_refresh_limits(bs, NULL, NULL);
78
+ bdrv_graph_rdunlock_main_loop();
79
bdrv_refresh_total_sectors(bs, bs->total_sectors);
80
}
81
82
@@ -XXX,XX +XXX,XX @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
83
out:
84
tran_finalize(tran, ret);
85
86
+ bdrv_graph_rdlock_main_loop();
87
bdrv_refresh_limits(bs_top, NULL, NULL);
88
+ bdrv_graph_rdunlock_main_loop();
89
90
if (new_context && old_context != new_context) {
91
aio_context_release(new_context);
92
diff --git a/block/io.c b/block/io.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/block/io.c
95
+++ b/block/io.c
96
@@ -XXX,XX +XXX,XX @@ void bdrv_refresh_limits(BlockDriverState *bs, Transaction *tran, Error **errp)
97
bool have_limits;
98
99
GLOBAL_STATE_CODE();
100
- assume_graph_lock(); /* FIXME */
101
102
if (tran) {
103
BdrvRefreshLimitsState *s = g_new(BdrvRefreshLimitsState, 1);
43
--
104
--
44
2.19.2
105
2.40.1
45
46
diff view generated by jsdifflib
1
From: Julio Faracco <jcfaracco@gmail.com>
1
From: Stefan Hajnoczi <stefanha@redhat.com>
2
2
3
This commit includes the support to lzfse opensource library. With this
3
reader_count() is a performance bottleneck because the global
4
library dmg block driver can decompress images with this type of
4
aio_context_list_lock mutex causes thread contention. Put this debugging
5
compression inside.
5
assertion behind a new ./configure --enable-debug-graph-lock option and
6
disable it by default.
6
7
7
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
8
The --enable-debug-graph-lock option is also enabled by the more general
9
--enable-debug option.
10
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
Message-Id: <20230501173443.153062-1-stefanha@redhat.com>
13
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
14
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
15
---
10
configure | 31 +++++++++++++++++++++++++++++++
16
meson_options.txt | 2 ++
11
block/Makefile.objs | 2 ++
17
configure | 1 +
12
2 files changed, 33 insertions(+)
18
block/graph-lock.c | 3 +++
19
meson.build | 2 ++
20
scripts/meson-buildoptions.sh | 4 ++++
21
5 files changed, 12 insertions(+)
13
22
23
diff --git a/meson_options.txt b/meson_options.txt
24
index XXXXXXX..XXXXXXX 100644
25
--- a/meson_options.txt
26
+++ b/meson_options.txt
27
@@ -XXX,XX +XXX,XX @@ option('rng_none', type: 'boolean', value: false,
28
description: 'dummy RNG, avoid using /dev/(u)random and getrandom()')
29
option('coroutine_pool', type: 'boolean', value: true,
30
description: 'coroutine freelist (better performance)')
31
+option('debug_graph_lock', type: 'boolean', value: false,
32
+ description: 'graph lock debugging support')
33
option('debug_mutex', type: 'boolean', value: false,
34
description: 'mutex debugging support')
35
option('debug_stack_usage', type: 'boolean', value: false,
14
diff --git a/configure b/configure
36
diff --git a/configure b/configure
15
index XXXXXXX..XXXXXXX 100755
37
index XXXXXXX..XXXXXXX 100755
16
--- a/configure
38
--- a/configure
17
+++ b/configure
39
+++ b/configure
18
@@ -XXX,XX +XXX,XX @@ capstone=""
19
lzo=""
20
snappy=""
21
bzip2=""
22
+lzfse=""
23
guest_agent=""
24
guest_agent_with_vss="no"
25
guest_agent_ntddscsi="no"
26
@@ -XXX,XX +XXX,XX @@ for opt do
40
@@ -XXX,XX +XXX,XX @@ for opt do
27
;;
41
--enable-debug)
28
--enable-bzip2) bzip2="yes"
42
# Enable debugging options that aren't excessively noisy
29
;;
43
debug_tcg="yes"
30
+ --enable-lzfse) lzfse="yes"
44
+ meson_option_parse --enable-debug-graph-lock ""
31
+ ;;
45
meson_option_parse --enable-debug-mutex ""
32
+ --disable-lzfse) lzfse="no"
46
meson_option_add -Doptimization=0
33
+ ;;
47
fortify_source="no"
34
--enable-guest-agent) guest_agent="yes"
48
diff --git a/block/graph-lock.c b/block/graph-lock.c
35
;;
36
--disable-guest-agent) guest_agent="no"
37
@@ -XXX,XX +XXX,XX @@ disabled with --disable-FEATURE, default is enabled if available:
38
snappy support of snappy compression library
39
bzip2 support of bzip2 compression library
40
(for reading bzip2-compressed dmg images)
41
+ lzfse support of lzfse compression library
42
+ (for reading lzfse-compressed dmg images)
43
seccomp seccomp support
44
coroutine-pool coroutine freelist (better performance)
45
glusterfs GlusterFS backend
46
@@ -XXX,XX +XXX,XX @@ EOF
47
fi
48
fi
49
50
+##########################################
51
+# lzfse check
52
+
53
+if test "$lzfse" != "no" ; then
54
+ cat > $TMPC << EOF
55
+#include <lzfse.h>
56
+int main(void) { lzfse_decode_scratch_size(); return 0; }
57
+EOF
58
+ if compile_prog "" "-llzfse" ; then
59
+ lzfse="yes"
60
+ else
61
+ if test "$lzfse" = "yes"; then
62
+ feature_not_found "lzfse" "Install lzfse devel"
63
+ fi
64
+ lzfse="no"
65
+ fi
66
+fi
67
+
68
##########################################
69
# libseccomp check
70
71
@@ -XXX,XX +XXX,XX @@ echo "Live block migration $live_block_migration"
72
echo "lzo support $lzo"
73
echo "snappy support $snappy"
74
echo "bzip2 support $bzip2"
75
+echo "lzfse support $lzfse"
76
echo "NUMA host support $numa"
77
echo "libxml2 $libxml2"
78
echo "tcmalloc support $tcmalloc"
79
@@ -XXX,XX +XXX,XX @@ if test "$bzip2" = "yes" ; then
80
echo "BZIP2_LIBS=-lbz2" >> $config_host_mak
81
fi
82
83
+if test "$lzfse" = "yes" ; then
84
+ echo "CONFIG_LZFSE=y" >> $config_host_mak
85
+ echo "LZFSE_LIBS=-llzfse" >> $config_host_mak
86
+fi
87
+
88
if test "$libiscsi" = "yes" ; then
89
echo "CONFIG_LIBISCSI=m" >> $config_host_mak
90
echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
91
diff --git a/block/Makefile.objs b/block/Makefile.objs
92
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
93
--- a/block/Makefile.objs
50
--- a/block/graph-lock.c
94
+++ b/block/Makefile.objs
51
+++ b/block/graph-lock.c
95
@@ -XXX,XX +XXX,XX @@ ssh.o-libs := $(LIBSSH2_LIBS)
52
@@ -XXX,XX +XXX,XX @@ void bdrv_graph_rdunlock_main_loop(void)
96
block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
53
97
block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
54
void assert_bdrv_graph_readable(void)
98
dmg-bz2.o-libs := $(BZIP2_LIBS)
55
{
99
+block-obj-$(if $(CONFIG_LZFSE),m,n) += dmg-lzfse.o
56
+ /* reader_count() is slow due to aio_context_list_lock lock contention */
100
+dmg-lzfse.o-libs := $(LZFSE_LIBS)
57
+#ifdef CONFIG_DEBUG_GRAPH_LOCK
101
qcow.o-libs := -lz
58
assert(qemu_in_main_thread() || reader_count());
102
linux-aio.o-libs := -laio
59
+#endif
103
parallels.o-cflags := $(LIBXML2_CFLAGS)
60
}
61
62
void assert_bdrv_graph_writable(void)
63
diff --git a/meson.build b/meson.build
64
index XXXXXXX..XXXXXXX 100644
65
--- a/meson.build
66
+++ b/meson.build
67
@@ -XXX,XX +XXX,XX @@ if get_option('debug_stack_usage') and have_coroutine_pool
68
have_coroutine_pool = false
69
endif
70
config_host_data.set10('CONFIG_COROUTINE_POOL', have_coroutine_pool)
71
+config_host_data.set('CONFIG_DEBUG_GRAPH_LOCK', get_option('debug_graph_lock'))
72
config_host_data.set('CONFIG_DEBUG_MUTEX', get_option('debug_mutex'))
73
config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage'))
74
config_host_data.set('CONFIG_GPROF', get_option('gprof'))
75
@@ -XXX,XX +XXX,XX @@ summary_info += {'PIE': get_option('b_pie')}
76
summary_info += {'static build': config_host.has_key('CONFIG_STATIC')}
77
summary_info += {'malloc trim support': has_malloc_trim}
78
summary_info += {'membarrier': have_membarrier}
79
+summary_info += {'debug graph lock': get_option('debug_graph_lock')}
80
summary_info += {'debug stack usage': get_option('debug_stack_usage')}
81
summary_info += {'mutex debugging': get_option('debug_mutex')}
82
summary_info += {'memory allocator': get_option('malloc')}
83
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
84
index XXXXXXX..XXXXXXX 100644
85
--- a/scripts/meson-buildoptions.sh
86
+++ b/scripts/meson-buildoptions.sh
87
@@ -XXX,XX +XXX,XX @@ meson_options_help() {
88
printf "%s\n" ' QEMU'
89
printf "%s\n" ' --enable-cfi Control-Flow Integrity (CFI)'
90
printf "%s\n" ' --enable-cfi-debug Verbose errors in case of CFI violation'
91
+ printf "%s\n" ' --enable-debug-graph-lock'
92
+ printf "%s\n" ' graph lock debugging support'
93
printf "%s\n" ' --enable-debug-mutex mutex debugging support'
94
printf "%s\n" ' --enable-debug-stack-usage'
95
printf "%s\n" ' measure coroutine stack usage'
96
@@ -XXX,XX +XXX,XX @@ _meson_option_parse() {
97
--datadir=*) quote_sh "-Ddatadir=$2" ;;
98
--enable-dbus-display) printf "%s" -Ddbus_display=enabled ;;
99
--disable-dbus-display) printf "%s" -Ddbus_display=disabled ;;
100
+ --enable-debug-graph-lock) printf "%s" -Ddebug_graph_lock=true ;;
101
+ --disable-debug-graph-lock) printf "%s" -Ddebug_graph_lock=false ;;
102
--enable-debug-mutex) printf "%s" -Ddebug_mutex=true ;;
103
--disable-debug-mutex) printf "%s" -Ddebug_mutex=false ;;
104
--enable-debug-stack-usage) printf "%s" -Ddebug_stack_usage=true ;;
104
--
105
--
105
2.19.2
106
2.40.1
106
107
diff view generated by jsdifflib
Deleted patch
1
From: Julio Faracco <jcfaracco@gmail.com>
2
1
3
This commit includes the support to new module dmg-lzfse into dmg block
4
driver. It includes the support for block type ULFO (0x80000007).
5
6
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/dmg.h | 3 +++
10
block/dmg.c | 28 ++++++++++++++++++++++++++++
11
2 files changed, 31 insertions(+)
12
13
diff --git a/block/dmg.h b/block/dmg.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/dmg.h
16
+++ b/block/dmg.h
17
@@ -XXX,XX +XXX,XX @@ typedef struct BDRVDMGState {
18
extern int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
19
char *next_out, unsigned int avail_out);
20
21
+extern int (*dmg_uncompress_lzfse)(char *next_in, unsigned int avail_in,
22
+ char *next_out, unsigned int avail_out);
23
+
24
#endif
25
diff --git a/block/dmg.c b/block/dmg.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/block/dmg.c
28
+++ b/block/dmg.c
29
@@ -XXX,XX +XXX,XX @@
30
int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
31
char *next_out, unsigned int avail_out);
32
33
+int (*dmg_uncompress_lzfse)(char *next_in, unsigned int avail_in,
34
+ char *next_out, unsigned int avail_out);
35
+
36
enum {
37
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
38
* or truncating when converting to 32-bit types
39
@@ -XXX,XX +XXX,XX @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
40
switch (s->types[chunk]) {
41
case 0x80000005: /* zlib compressed */
42
case 0x80000006: /* bzip2 compressed */
43
+ case 0x80000007: /* lzfse compressed */
44
compressed_size = s->lengths[chunk];
45
uncompressed_sectors = s->sectorcounts[chunk];
46
break;
47
@@ -XXX,XX +XXX,XX @@ static bool dmg_is_known_block_type(uint32_t entry_type)
48
return true;
49
case 0x80000006: /* bzip2 */
50
return !!dmg_uncompress_bz2;
51
+ case 0x80000007: /* lzfse */
52
+ return !!dmg_uncompress_lzfse;
53
default:
54
return false;
55
}
56
@@ -XXX,XX +XXX,XX @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
57
}
58
59
block_module_load_one("dmg-bz2");
60
+ block_module_load_one("dmg-lzfse");
61
62
s->n_chunks = 0;
63
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
64
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
65
return ret;
66
}
67
break;
68
+ case 0x80000007:
69
+ if (!dmg_uncompress_lzfse) {
70
+ break;
71
+ }
72
+ /* we need to buffer, because only the chunk as whole can be
73
+ * inflated. */
74
+ ret = bdrv_pread(bs->file, s->offsets[chunk],
75
+ s->compressed_chunk, s->lengths[chunk]);
76
+ if (ret != s->lengths[chunk]) {
77
+ return -1;
78
+ }
79
+
80
+ ret = dmg_uncompress_lzfse((char *)s->compressed_chunk,
81
+ (unsigned int) s->lengths[chunk],
82
+ (char *)s->uncompressed_chunk,
83
+ (unsigned int)
84
+ (512 * s->sectorcounts[chunk]));
85
+ if (ret < 0) {
86
+ return ret;
87
+ }
88
+ break;
89
case 1: /* copy */
90
ret = bdrv_pread(bs->file, s->offsets[chunk],
91
s->uncompressed_chunk, s->lengths[chunk]);
92
--
93
2.19.2
94
95
diff view generated by jsdifflib
Deleted patch
1
From: Julio Faracco <jcfaracco@gmail.com>
2
1
3
This change is better to understand what kind of block type is being
4
handled by the code. Using a syntax similar to the DMG documentation is
5
easier than tracking all hex values assigned to a block type.
6
7
Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/dmg.c | 43 ++++++++++++++++++++++++++++---------------
11
1 file changed, 28 insertions(+), 15 deletions(-)
12
13
diff --git a/block/dmg.c b/block/dmg.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/dmg.c
16
+++ b/block/dmg.c
17
@@ -XXX,XX +XXX,XX @@ enum {
18
DMG_SECTORCOUNTS_MAX = DMG_LENGTHS_MAX / 512,
19
};
20
21
+enum {
22
+ /* DMG Block Type */
23
+ UDZE = 0, /* Zeroes */
24
+ UDRW, /* RAW type */
25
+ UDIG, /* Ignore */
26
+ UDCO = 0x80000004,
27
+ UDZO,
28
+ UDBZ,
29
+ ULFO,
30
+ UDCM = 0x7ffffffe, /* Comments */
31
+ UDLE /* Last Entry */
32
+};
33
+
34
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
35
{
36
int len;
37
@@ -XXX,XX +XXX,XX @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
38
uint32_t uncompressed_sectors = 0;
39
40
switch (s->types[chunk]) {
41
- case 0x80000005: /* zlib compressed */
42
- case 0x80000006: /* bzip2 compressed */
43
- case 0x80000007: /* lzfse compressed */
44
+ case UDZO: /* zlib compressed */
45
+ case UDBZ: /* bzip2 compressed */
46
+ case ULFO: /* lzfse compressed */
47
compressed_size = s->lengths[chunk];
48
uncompressed_sectors = s->sectorcounts[chunk];
49
break;
50
- case 1: /* copy */
51
+ case UDRW: /* copy */
52
uncompressed_sectors = DIV_ROUND_UP(s->lengths[chunk], 512);
53
break;
54
- case 2: /* zero */
55
+ case UDIG: /* zero */
56
/* as the all-zeroes block may be large, it is treated specially: the
57
* sector is not copied from a large buffer, a simple memset is used
58
* instead. Therefore uncompressed_sectors does not need to be set. */
59
@@ -XXX,XX +XXX,XX @@ typedef struct DmgHeaderState {
60
static bool dmg_is_known_block_type(uint32_t entry_type)
61
{
62
switch (entry_type) {
63
- case 0x00000001: /* uncompressed */
64
- case 0x00000002: /* zeroes */
65
- case 0x80000005: /* zlib */
66
+ case UDRW: /* uncompressed */
67
+ case UDIG: /* zeroes */
68
+ case UDZO: /* zlib */
69
return true;
70
- case 0x80000006: /* bzip2 */
71
+ case UDBZ: /* bzip2 */
72
return !!dmg_uncompress_bz2;
73
- case 0x80000007: /* lzfse */
74
+ case ULFO: /* lzfse */
75
return !!dmg_uncompress_lzfse;
76
default:
77
return false;
78
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
79
80
s->current_chunk = s->n_chunks;
81
switch (s->types[chunk]) { /* block entry type */
82
- case 0x80000005: { /* zlib compressed */
83
+ case UDZO: { /* zlib compressed */
84
/* we need to buffer, because only the chunk as whole can be
85
* inflated. */
86
ret = bdrv_pread(bs->file, s->offsets[chunk],
87
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
88
return -1;
89
}
90
break; }
91
- case 0x80000006: /* bzip2 compressed */
92
+ case UDBZ: /* bzip2 compressed */
93
if (!dmg_uncompress_bz2) {
94
break;
95
}
96
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
97
return ret;
98
}
99
break;
100
- case 0x80000007:
101
+ case ULFO:
102
if (!dmg_uncompress_lzfse) {
103
break;
104
}
105
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
106
return ret;
107
}
108
break;
109
- case 1: /* copy */
110
+ case UDRW: /* copy */
111
ret = bdrv_pread(bs->file, s->offsets[chunk],
112
s->uncompressed_chunk, s->lengths[chunk]);
113
if (ret != s->lengths[chunk]) {
114
return -1;
115
}
116
break;
117
- case 2: /* zero */
118
+ case UDIG: /* zero */
119
/* see dmg_read, it is treated specially. No buffer needs to be
120
* pre-filled, the zeroes can be set directly. */
121
break;
122
--
123
2.19.2
124
125
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
After commit f8d59dfb40
4
"block/backup: fix fleecing scheme: use serialized writes" fleecing
5
(specifically reading from backup target, when backup source is in
6
backing chain of backup target) is safe, because all backup-job writes
7
to target are serialized. Therefore we don't need additional
8
synchronization for these reads.
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
12
---
13
block/replication.c | 24 +-----------------------
14
1 file changed, 1 insertion(+), 23 deletions(-)
15
16
diff --git a/block/replication.c b/block/replication.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/replication.c
19
+++ b/block/replication.c
20
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
21
QEMUIOVector *qiov)
22
{
23
BDRVReplicationState *s = bs->opaque;
24
- BdrvChild *child = s->secondary_disk;
25
- BlockJob *job = NULL;
26
- CowRequest req;
27
int ret;
28
29
if (s->mode == REPLICATION_MODE_PRIMARY) {
30
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int replication_co_readv(BlockDriverState *bs,
31
return ret;
32
}
33
34
- if (child && child->bs) {
35
- job = child->bs->job;
36
- }
37
-
38
- if (job) {
39
- uint64_t remaining_bytes = remaining_sectors * BDRV_SECTOR_SIZE;
40
-
41
- backup_wait_for_overlapping_requests(child->bs->job,
42
- sector_num * BDRV_SECTOR_SIZE,
43
- remaining_bytes);
44
- backup_cow_request_begin(&req, child->bs->job,
45
- sector_num * BDRV_SECTOR_SIZE,
46
- remaining_bytes);
47
- ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
48
- remaining_bytes, qiov, 0);
49
- backup_cow_request_end(&req);
50
- goto out;
51
- }
52
-
53
ret = bdrv_co_preadv(bs->file, sector_num * BDRV_SECTOR_SIZE,
54
remaining_sectors * BDRV_SECTOR_SIZE, qiov, 0);
55
-out:
56
+
57
return replication_return_value(s, ret);
58
}
59
60
--
61
2.19.2
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
4
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
5
---
6
include/block/block_backup.h | 13 ------------
7
block/backup.c | 38 +++++++-----------------------------
8
2 files changed, 7 insertions(+), 44 deletions(-)
9
10
diff --git a/include/block/block_backup.h b/include/block/block_backup.h
11
index XXXXXXX..XXXXXXX 100644
12
--- a/include/block/block_backup.h
13
+++ b/include/block/block_backup.h
14
@@ -XXX,XX +XXX,XX @@
15
16
#include "block/block_int.h"
17
18
-typedef struct CowRequest {
19
- int64_t start_byte;
20
- int64_t end_byte;
21
- QLIST_ENTRY(CowRequest) list;
22
- CoQueue wait_queue; /* coroutines blocked on this request */
23
-} CowRequest;
24
-
25
-void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
26
- uint64_t bytes);
27
-void backup_cow_request_begin(CowRequest *req, BlockJob *job,
28
- int64_t offset, uint64_t bytes);
29
-void backup_cow_request_end(CowRequest *req);
30
-
31
void backup_do_checkpoint(BlockJob *job, Error **errp);
32
33
#endif
34
diff --git a/block/backup.c b/block/backup.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/backup.c
37
+++ b/block/backup.c
38
@@ -XXX,XX +XXX,XX @@
39
40
#define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
41
42
+typedef struct CowRequest {
43
+ int64_t start_byte;
44
+ int64_t end_byte;
45
+ QLIST_ENTRY(CowRequest) list;
46
+ CoQueue wait_queue; /* coroutines blocked on this request */
47
+} CowRequest;
48
+
49
typedef struct BackupBlockJob {
50
BlockJob common;
51
BlockBackend *target;
52
@@ -XXX,XX +XXX,XX @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
53
hbitmap_set(backup_job->copy_bitmap, 0, len);
54
}
55
56
-void backup_wait_for_overlapping_requests(BlockJob *job, int64_t offset,
57
- uint64_t bytes)
58
-{
59
- BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
60
- int64_t start, end;
61
-
62
- assert(block_job_driver(job) == &backup_job_driver);
63
-
64
- start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
65
- end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
66
- wait_for_overlapping_requests(backup_job, start, end);
67
-}
68
-
69
-void backup_cow_request_begin(CowRequest *req, BlockJob *job,
70
- int64_t offset, uint64_t bytes)
71
-{
72
- BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
73
- int64_t start, end;
74
-
75
- assert(block_job_driver(job) == &backup_job_driver);
76
-
77
- start = QEMU_ALIGN_DOWN(offset, backup_job->cluster_size);
78
- end = QEMU_ALIGN_UP(offset + bytes, backup_job->cluster_size);
79
- cow_request_begin(req, backup_job, start, end);
80
-}
81
-
82
-void backup_cow_request_end(CowRequest *req)
83
-{
84
- cow_request_end(req);
85
-}
86
-
87
static void backup_drain(BlockJob *job)
88
{
89
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
90
--
91
2.19.2
92
93
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Give explicit size both for source and destination buffers, to make it
4
similar with decompression path and than cleanly reuse parameter
5
structure for decompression threads.
6
7
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
8
Reviewed-by: Alberto Garcia <berto@igalia.com>
9
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
10
---
11
block/qcow2.c | 30 ++++++++++++++++++------------
12
1 file changed, 18 insertions(+), 12 deletions(-)
13
14
diff --git a/block/qcow2.c b/block/qcow2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/block/qcow2.c
17
+++ b/block/qcow2.c
18
@@ -XXX,XX +XXX,XX @@ fail:
19
/*
20
* qcow2_compress()
21
*
22
- * @dest - destination buffer, at least of @size-1 bytes
23
- * @src - source buffer, @size bytes
24
+ * @dest - destination buffer, @dest_size bytes
25
+ * @src - source buffer, @src_size bytes
26
*
27
* Returns: compressed size on success
28
- * -1 if compression is inefficient
29
+ * -1 destination buffer is not enough to store compressed data
30
* -2 on any other error
31
*/
32
-static ssize_t qcow2_compress(void *dest, const void *src, size_t size)
33
+static ssize_t qcow2_compress(void *dest, size_t dest_size,
34
+ const void *src, size_t src_size)
35
{
36
ssize_t ret;
37
z_stream strm;
38
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, const void *src, size_t size)
39
40
/* strm.next_in is not const in old zlib versions, such as those used on
41
* OpenBSD/NetBSD, so cast the const away */
42
- strm.avail_in = size;
43
+ strm.avail_in = src_size;
44
strm.next_in = (void *) src;
45
- strm.avail_out = size - 1;
46
+ strm.avail_out = dest_size;
47
strm.next_out = dest;
48
49
ret = deflate(&strm, Z_FINISH);
50
if (ret == Z_STREAM_END) {
51
- ret = size - 1 - strm.avail_out;
52
+ ret = dest_size - strm.avail_out;
53
} else {
54
ret = (ret == Z_OK ? -1 : -2);
55
}
56
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, const void *src, size_t size)
57
58
typedef struct Qcow2CompressData {
59
void *dest;
60
+ size_t dest_size;
61
const void *src;
62
- size_t size;
63
+ size_t src_size;
64
ssize_t ret;
65
} Qcow2CompressData;
66
67
@@ -XXX,XX +XXX,XX @@ static int qcow2_compress_pool_func(void *opaque)
68
{
69
Qcow2CompressData *data = opaque;
70
71
- data->ret = qcow2_compress(data->dest, data->src, data->size);
72
+ data->ret = qcow2_compress(data->dest, data->dest_size,
73
+ data->src, data->src_size);
74
75
return 0;
76
}
77
@@ -XXX,XX +XXX,XX @@ static void qcow2_compress_complete(void *opaque, int ret)
78
79
/* See qcow2_compress definition for parameters description */
80
static ssize_t qcow2_co_compress(BlockDriverState *bs,
81
- void *dest, const void *src, size_t size)
82
+ void *dest, size_t dest_size,
83
+ const void *src, size_t src_size)
84
{
85
BDRVQcow2State *s = bs->opaque;
86
BlockAIOCB *acb;
87
ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
88
Qcow2CompressData arg = {
89
.dest = dest,
90
+ .dest_size = dest_size,
91
.src = src,
92
- .size = size,
93
+ .src_size = src_size,
94
};
95
96
while (s->nb_compress_threads >= MAX_COMPRESS_THREADS) {
97
@@ -XXX,XX +XXX,XX @@ qcow2_co_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
98
99
out_buf = g_malloc(s->cluster_size);
100
101
- out_len = qcow2_co_compress(bs, out_buf, buf, s->cluster_size);
102
+ out_len = qcow2_co_compress(bs, out_buf, s->cluster_size - 1,
103
+ buf, s->cluster_size);
104
if (out_len == -2) {
105
ret = -EINVAL;
106
goto fail;
107
--
108
2.19.2
109
110
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
- make it look more like a pair of qcow2_compress - rename the function
4
and its parameters
5
- drop extra out_len variable, check filling of output buffer by strm
6
structure itself
7
- fix code style
8
- add some documentation
9
10
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
11
Reviewed-by: Alberto Garcia <berto@igalia.com>
12
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
13
---
14
block/qcow2.c | 56 ++++++++++++++++++++++++++++++++-------------------
15
1 file changed, 35 insertions(+), 21 deletions(-)
16
17
diff --git a/block/qcow2.c b/block/qcow2.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/qcow2.c
20
+++ b/block/qcow2.c
21
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_compress(void *dest, size_t dest_size,
22
return ret;
23
}
24
25
-static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
26
- const uint8_t *buf, int buf_size)
27
+/*
28
+ * qcow2_decompress()
29
+ *
30
+ * Decompress some data (not more than @src_size bytes) to produce exactly
31
+ * @dest_size bytes.
32
+ *
33
+ * @dest - destination buffer, @dest_size bytes
34
+ * @src - source buffer, @src_size bytes
35
+ *
36
+ * Returns: 0 on success
37
+ * -1 on fail
38
+ */
39
+static ssize_t qcow2_decompress(void *dest, size_t dest_size,
40
+ const void *src, size_t src_size)
41
{
42
- z_stream strm1, *strm = &strm1;
43
- int ret, out_len;
44
-
45
- memset(strm, 0, sizeof(*strm));
46
+ int ret = 0;
47
+ z_stream strm;
48
49
- strm->next_in = (uint8_t *)buf;
50
- strm->avail_in = buf_size;
51
- strm->next_out = out_buf;
52
- strm->avail_out = out_buf_size;
53
+ memset(&strm, 0, sizeof(strm));
54
+ strm.avail_in = src_size;
55
+ strm.next_in = (void *) src;
56
+ strm.avail_out = dest_size;
57
+ strm.next_out = dest;
58
59
- ret = inflateInit2(strm, -12);
60
+ ret = inflateInit2(&strm, -12);
61
if (ret != Z_OK) {
62
return -1;
63
}
64
- ret = inflate(strm, Z_FINISH);
65
- out_len = strm->next_out - out_buf;
66
- if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
67
- out_len != out_buf_size) {
68
- inflateEnd(strm);
69
- return -1;
70
+
71
+ ret = inflate(&strm, Z_FINISH);
72
+ if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || strm.avail_out != 0) {
73
+ /* We approve Z_BUF_ERROR because we need @dest buffer to be filled, but
74
+ * @src buffer may be processed partly (because in qcow2 we know size of
75
+ * compressed data with precision of one sector) */
76
+ ret = -1;
77
}
78
- inflateEnd(strm);
79
- return 0;
80
+
81
+ inflateEnd(&strm);
82
+
83
+ return ret;
84
}
85
86
#define MAX_COMPRESS_THREADS 4
87
@@ -XXX,XX +XXX,XX @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
88
if (ret < 0) {
89
return ret;
90
}
91
- if (decompress_buffer(s->cluster_cache, s->cluster_size,
92
- s->cluster_data + sector_offset, csize) < 0) {
93
+ if (qcow2_decompress(s->cluster_cache, s->cluster_size,
94
+ s->cluster_data + sector_offset, csize) < 0) {
95
return -EIO;
96
}
97
s->cluster_cache_offset = coffset;
98
--
99
2.19.2
100
101
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
We are gradually moving away from sector-based interfaces, towards
4
byte-based. Get rid of it here too.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
8
---
9
block/qcow2.c | 19 ++++++++++++-------
10
1 file changed, 12 insertions(+), 7 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 @@ fail:
17
return ret;
18
}
19
20
-int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
21
+int coroutine_fn
22
+qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
23
{
24
BDRVQcow2State *s = bs->opaque;
25
- int ret, csize, nb_csectors, sector_offset;
26
+ int ret, csize, nb_csectors;
27
uint64_t coffset;
28
+ struct iovec iov;
29
+ QEMUIOVector local_qiov;
30
31
coffset = cluster_offset & s->cluster_offset_mask;
32
if (s->cluster_cache_offset != coffset) {
33
nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
34
- sector_offset = coffset & 511;
35
- csize = nb_csectors * 512 - sector_offset;
36
+ csize = nb_csectors * 512 - (coffset & 511);
37
38
/* Allocate buffers on first decompress operation, most images are
39
* uncompressed and the memory overhead can be avoided. The buffers
40
@@ -XXX,XX +XXX,XX @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
41
s->cluster_cache = g_malloc(s->cluster_size);
42
}
43
44
+ iov.iov_base = s->cluster_data;
45
+ iov.iov_len = csize;
46
+ qemu_iovec_init_external(&local_qiov, &iov, 1);
47
+
48
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
49
- ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data,
50
- nb_csectors);
51
+ ret = bdrv_co_preadv(bs->file, coffset, csize, &local_qiov, 0);
52
if (ret < 0) {
53
return ret;
54
}
55
if (qcow2_decompress(s->cluster_cache, s->cluster_size,
56
- s->cluster_data + sector_offset, csize) < 0) {
57
+ s->cluster_data, csize) < 0) {
58
return -EIO;
59
}
60
s->cluster_cache_offset = coffset;
61
--
62
2.19.2
63
64
diff view generated by jsdifflib
Deleted patch
1
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
2
1
3
Do decompression in threads, like it is already done for compression.
4
This improves asynchronous compressed reads performance.
5
6
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
7
Reviewed-by: Alberto Garcia <berto@igalia.com>
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/qcow2.c | 34 +++++++++++++++++++++++++++-------
11
1 file changed, 27 insertions(+), 7 deletions(-)
12
13
diff --git a/block/qcow2.c b/block/qcow2.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/qcow2.c
16
+++ b/block/qcow2.c
17
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_decompress(void *dest, size_t dest_size,
18
19
#define MAX_COMPRESS_THREADS 4
20
21
+typedef ssize_t (*Qcow2CompressFunc)(void *dest, size_t dest_size,
22
+ const void *src, size_t src_size);
23
typedef struct Qcow2CompressData {
24
void *dest;
25
size_t dest_size;
26
const void *src;
27
size_t src_size;
28
ssize_t ret;
29
+
30
+ Qcow2CompressFunc func;
31
} Qcow2CompressData;
32
33
static int qcow2_compress_pool_func(void *opaque)
34
{
35
Qcow2CompressData *data = opaque;
36
37
- data->ret = qcow2_compress(data->dest, data->dest_size,
38
- data->src, data->src_size);
39
+ data->ret = data->func(data->dest, data->dest_size,
40
+ data->src, data->src_size);
41
42
return 0;
43
}
44
@@ -XXX,XX +XXX,XX @@ static void qcow2_compress_complete(void *opaque, int ret)
45
qemu_coroutine_enter(opaque);
46
}
47
48
-/* See qcow2_compress definition for parameters description */
49
-static ssize_t qcow2_co_compress(BlockDriverState *bs,
50
- void *dest, size_t dest_size,
51
- const void *src, size_t src_size)
52
+static ssize_t coroutine_fn
53
+qcow2_co_do_compress(BlockDriverState *bs, void *dest, size_t dest_size,
54
+ const void *src, size_t src_size, Qcow2CompressFunc func)
55
{
56
BDRVQcow2State *s = bs->opaque;
57
BlockAIOCB *acb;
58
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_co_compress(BlockDriverState *bs,
59
.dest_size = dest_size,
60
.src = src,
61
.src_size = src_size,
62
+ .func = func,
63
};
64
65
while (s->nb_compress_threads >= MAX_COMPRESS_THREADS) {
66
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_co_compress(BlockDriverState *bs,
67
return arg.ret;
68
}
69
70
+static ssize_t coroutine_fn
71
+qcow2_co_compress(BlockDriverState *bs, void *dest, size_t dest_size,
72
+ const void *src, size_t src_size)
73
+{
74
+ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
75
+ qcow2_compress);
76
+}
77
+
78
+static ssize_t coroutine_fn
79
+qcow2_co_decompress(BlockDriverState *bs, void *dest, size_t dest_size,
80
+ const void *src, size_t src_size)
81
+{
82
+ return qcow2_co_do_compress(bs, dest, dest_size, src, src_size,
83
+ qcow2_decompress);
84
+}
85
+
86
/* XXX: put compressed sectors first, then all the cluster aligned
87
tables to avoid losing bytes in alignment */
88
static coroutine_fn int
89
@@ -XXX,XX +XXX,XX @@ qcow2_co_preadv_compressed(BlockDriverState *bs,
90
goto fail;
91
}
92
93
- if (qcow2_decompress(out_buf, s->cluster_size, buf, csize) < 0) {
94
+ if (qcow2_co_decompress(bs, out_buf, s->cluster_size, buf, csize) < 0) {
95
ret = -EIO;
96
goto fail;
97
}
98
--
99
2.19.2
100
101
diff view generated by jsdifflib
Deleted patch
1
RawPosixAIOData contains a lot of fields for several separate operations
2
that are to be processed in a worker thread and that need different
3
parameters. The struct is currently rather unorganised, with unions that
4
cover some, but not all operations, and even one #define for field names
5
instead of a union.
6
1
7
Clean this up to have some common fields and a single union. As a side
8
effect, on x86_64 the struct shrinks from 72 to 48 bytes.
9
10
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
11
---
12
block/file-posix.c | 89 +++++++++++++++++++++++++---------------------
13
1 file changed, 49 insertions(+), 40 deletions(-)
14
15
diff --git a/block/file-posix.c b/block/file-posix.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/block/file-posix.c
18
+++ b/block/file-posix.c
19
@@ -XXX,XX +XXX,XX @@ static int64_t raw_getlength(BlockDriverState *bs);
20
21
typedef struct RawPosixAIOData {
22
BlockDriverState *bs;
23
+ int aio_type;
24
int aio_fildes;
25
- union {
26
- struct iovec *aio_iov;
27
- void *aio_ioctl_buf;
28
- };
29
- int aio_niov;
30
- uint64_t aio_nbytes;
31
-#define aio_ioctl_cmd aio_nbytes /* for QEMU_AIO_IOCTL */
32
+
33
off_t aio_offset;
34
- int aio_type;
35
+ uint64_t aio_nbytes;
36
+
37
union {
38
+ struct {
39
+ struct iovec *iov;
40
+ int niov;
41
+ } io;
42
+ struct {
43
+ uint64_t cmd;
44
+ void *buf;
45
+ } ioctl;
46
struct {
47
int aio_fd2;
48
off_t aio_offset2;
49
- };
50
+ } copy_range;
51
struct {
52
PreallocMode prealloc;
53
Error **errp;
54
- };
55
+ } truncate;
56
};
57
} RawPosixAIOData;
58
59
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_ioctl(RawPosixAIOData *aiocb)
60
{
61
int ret;
62
63
- ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
64
+ ret = ioctl(aiocb->aio_fildes, aiocb->ioctl.cmd, aiocb->ioctl.buf);
65
if (ret == -1) {
66
return -errno;
67
}
68
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw_vector(RawPosixAIOData *aiocb)
69
do {
70
if (aiocb->aio_type & QEMU_AIO_WRITE)
71
len = qemu_pwritev(aiocb->aio_fildes,
72
- aiocb->aio_iov,
73
- aiocb->aio_niov,
74
+ aiocb->io.iov,
75
+ aiocb->io.niov,
76
aiocb->aio_offset);
77
else
78
len = qemu_preadv(aiocb->aio_fildes,
79
- aiocb->aio_iov,
80
- aiocb->aio_niov,
81
+ aiocb->io.iov,
82
+ aiocb->io.niov,
83
aiocb->aio_offset);
84
} while (len == -1 && errno == EINTR);
85
86
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
87
* If there is just a single buffer, and it is properly aligned
88
* we can just use plain pread/pwrite without any problems.
89
*/
90
- if (aiocb->aio_niov == 1) {
91
- return handle_aiocb_rw_linear(aiocb, aiocb->aio_iov->iov_base);
92
+ if (aiocb->io.niov == 1) {
93
+ return handle_aiocb_rw_linear(aiocb, aiocb->io.iov->iov_base);
94
}
95
/*
96
* We have more than one iovec, and all are properly aligned.
97
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
98
char *p = buf;
99
int i;
100
101
- for (i = 0; i < aiocb->aio_niov; ++i) {
102
- memcpy(p, aiocb->aio_iov[i].iov_base, aiocb->aio_iov[i].iov_len);
103
- p += aiocb->aio_iov[i].iov_len;
104
+ for (i = 0; i < aiocb->io.niov; ++i) {
105
+ memcpy(p, aiocb->io.iov[i].iov_base, aiocb->io.iov[i].iov_len);
106
+ p += aiocb->io.iov[i].iov_len;
107
}
108
assert(p - buf == aiocb->aio_nbytes);
109
}
110
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
111
size_t count = aiocb->aio_nbytes, copy;
112
int i;
113
114
- for (i = 0; i < aiocb->aio_niov && count; ++i) {
115
+ for (i = 0; i < aiocb->io.niov && count; ++i) {
116
copy = count;
117
- if (copy > aiocb->aio_iov[i].iov_len) {
118
- copy = aiocb->aio_iov[i].iov_len;
119
+ if (copy > aiocb->io.iov[i].iov_len) {
120
+ copy = aiocb->io.iov[i].iov_len;
121
}
122
- memcpy(aiocb->aio_iov[i].iov_base, p, copy);
123
+ memcpy(aiocb->io.iov[i].iov_base, p, copy);
124
assert(count >= copy);
125
p += copy;
126
count -= copy;
127
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
128
{
129
uint64_t bytes = aiocb->aio_nbytes;
130
off_t in_off = aiocb->aio_offset;
131
- off_t out_off = aiocb->aio_offset2;
132
+ off_t out_off = aiocb->copy_range.aio_offset2;
133
134
while (bytes) {
135
ssize_t ret = copy_file_range(aiocb->aio_fildes, &in_off,
136
- aiocb->aio_fd2, &out_off,
137
+ aiocb->copy_range.aio_fd2, &out_off,
138
bytes, 0);
139
trace_file_copy_file_range(aiocb->bs, aiocb->aio_fildes, in_off,
140
- aiocb->aio_fd2, out_off, bytes, 0, ret);
141
+ aiocb->copy_range.aio_fd2, out_off, bytes,
142
+ 0, ret);
143
if (ret == 0) {
144
/* No progress (e.g. when beyond EOF), let the caller fall back to
145
* buffer I/O. */
146
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
147
struct stat st;
148
int fd = aiocb->aio_fildes;
149
int64_t offset = aiocb->aio_offset;
150
- Error **errp = aiocb->errp;
151
+ PreallocMode prealloc = aiocb->truncate.prealloc;
152
+ Error **errp = aiocb->truncate.errp;
153
154
if (fstat(fd, &st) < 0) {
155
result = -errno;
156
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
157
}
158
159
current_length = st.st_size;
160
- if (current_length > offset && aiocb->prealloc != PREALLOC_MODE_OFF) {
161
+ if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
162
error_setg(errp, "Cannot use preallocation for shrinking files");
163
return -ENOTSUP;
164
}
165
166
- switch (aiocb->prealloc) {
167
+ switch (prealloc) {
168
#ifdef CONFIG_POSIX_FALLOCATE
169
case PREALLOC_MODE_FALLOC:
170
/*
171
@@ -XXX,XX +XXX,XX @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb)
172
default:
173
result = -ENOTSUP;
174
error_setg(errp, "Unsupported preallocation mode: %s",
175
- PreallocMode_str(aiocb->prealloc));
176
+ PreallocMode_str(prealloc));
177
return result;
178
}
179
180
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
181
case QEMU_AIO_READ:
182
ret = handle_aiocb_rw(aiocb);
183
if (ret >= 0 && ret < aiocb->aio_nbytes) {
184
- iov_memset(aiocb->aio_iov, aiocb->aio_niov, ret,
185
+ iov_memset(aiocb->io.iov, aiocb->io.niov, ret,
186
0, aiocb->aio_nbytes - ret);
187
188
ret = aiocb->aio_nbytes;
189
@@ -XXX,XX +XXX,XX @@ static int paio_submit_co_full(BlockDriverState *bs, int fd,
190
acb->bs = bs;
191
acb->aio_type = type;
192
acb->aio_fildes = fd;
193
- acb->aio_fd2 = fd2;
194
- acb->aio_offset2 = offset2;
195
196
acb->aio_nbytes = bytes;
197
acb->aio_offset = offset;
198
199
if (qiov) {
200
- acb->aio_iov = qiov->iov;
201
- acb->aio_niov = qiov->niov;
202
+ acb->io.iov = qiov->iov;
203
+ acb->io.niov = qiov->niov;
204
assert(qiov->size == bytes);
205
+ } else {
206
+ acb->copy_range.aio_fd2 = fd2;
207
+ acb->copy_range.aio_offset2 = offset2;
208
}
209
210
trace_file_paio_submit_co(offset, bytes, type);
211
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
212
.aio_fildes = fd,
213
.aio_type = QEMU_AIO_TRUNCATE,
214
.aio_offset = offset,
215
- .prealloc = prealloc,
216
- .errp = errp,
217
+ .truncate = {
218
+ .prealloc = prealloc,
219
+ .errp = errp,
220
+ },
221
};
222
223
/* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
224
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
225
acb->aio_type = QEMU_AIO_IOCTL;
226
acb->aio_fildes = s->fd;
227
acb->aio_offset = 0;
228
- acb->aio_ioctl_buf = buf;
229
- acb->aio_ioctl_cmd = req;
230
+ acb->ioctl.buf = buf;
231
+ acb->ioctl.cmd = req;
232
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
233
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
234
}
235
--
236
2.19.2
237
238
diff view generated by jsdifflib
Deleted patch
1
Getting the thread pool of the AioContext of a block node and scheduling
2
some work in it is an operation that is already done twice, and we'll
3
get more instances. Factor it out into a separate function.
4
1
5
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
6
---
7
block/file-posix.c | 17 ++++++++++-------
8
1 file changed, 10 insertions(+), 7 deletions(-)
9
10
diff --git a/block/file-posix.c b/block/file-posix.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/block/file-posix.c
13
+++ b/block/file-posix.c
14
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
15
return ret;
16
}
17
18
+static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
19
+ ThreadPoolFunc func, void *arg)
20
+{
21
+ /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
22
+ ThreadPool *pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
23
+ return thread_pool_submit_co(pool, func, arg);
24
+}
25
+
26
static int paio_submit_co_full(BlockDriverState *bs, int fd,
27
int64_t offset, int fd2, int64_t offset2,
28
QEMUIOVector *qiov,
29
int bytes, int type)
30
{
31
RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
32
- ThreadPool *pool;
33
34
acb->bs = bs;
35
acb->aio_type = type;
36
@@ -XXX,XX +XXX,XX @@ static int paio_submit_co_full(BlockDriverState *bs, int fd,
37
}
38
39
trace_file_paio_submit_co(offset, bytes, type);
40
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
41
- return thread_pool_submit_co(pool, aio_worker, acb);
42
+ return raw_thread_pool_submit(bs, aio_worker, acb);
43
}
44
45
static inline int paio_submit_co(BlockDriverState *bs, int fd,
46
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
47
PreallocMode prealloc, Error **errp)
48
{
49
RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
50
- ThreadPool *pool;
51
52
*acb = (RawPosixAIOData) {
53
.bs = bs,
54
@@ -XXX,XX +XXX,XX @@ raw_regular_truncate(BlockDriverState *bs, int fd, int64_t offset,
55
},
56
};
57
58
- /* @bs can be NULL, bdrv_get_aio_context() returns the main context then */
59
- pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
60
- return thread_pool_submit_co(pool, aio_worker, acb);
61
+ return raw_thread_pool_submit(bs, aio_worker, acb);
62
}
63
64
static int coroutine_fn raw_co_truncate(BlockDriverState *bs, int64_t offset,
65
--
66
2.19.2
67
68
diff view generated by jsdifflib
Deleted patch
1
aio_worker() doesn't add anything interesting, it's only a useless
2
indirection. Call the handler function directly instead.
3
1
4
As we know that this handler function is only called from coroutine
5
context and the coroutine stays around until the worker thread finishes,
6
we can keep RawPosixAIOData on the stack.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/file-posix.c | 22 +++++++++++++++++-----
11
1 file changed, 17 insertions(+), 5 deletions(-)
12
13
diff --git a/block/file-posix.c b/block/file-posix.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
16
+++ b/block/file-posix.c
17
@@ -XXX,XX +XXX,XX @@ static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
18
}
19
#endif
20
21
-static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
22
+static int handle_aiocb_copy_range(void *opaque)
23
{
24
+ RawPosixAIOData *aiocb = opaque;
25
uint64_t bytes = aiocb->aio_nbytes;
26
off_t in_off = aiocb->aio_offset;
27
off_t out_off = aiocb->copy_range.aio_offset2;
28
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
29
ret = handle_aiocb_write_zeroes_unmap(aiocb);
30
break;
31
case QEMU_AIO_COPY_RANGE:
32
- ret = handle_aiocb_copy_range(aiocb);
33
- break;
34
case QEMU_AIO_TRUNCATE:
35
g_assert_not_reached();
36
default:
37
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
38
BdrvRequestFlags read_flags,
39
BdrvRequestFlags write_flags)
40
{
41
+ RawPosixAIOData acb;
42
BDRVRawState *s = bs->opaque;
43
BDRVRawState *src_s;
44
45
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
46
if (fd_open(src->bs) < 0 || fd_open(dst->bs) < 0) {
47
return -EIO;
48
}
49
- return paio_submit_co_full(bs, src_s->fd, src_offset, s->fd, dst_offset,
50
- NULL, bytes, QEMU_AIO_COPY_RANGE);
51
+
52
+ acb = (RawPosixAIOData) {
53
+ .bs = bs,
54
+ .aio_type = QEMU_AIO_COPY_RANGE,
55
+ .aio_fildes = src_s->fd,
56
+ .aio_offset = src_offset,
57
+ .aio_nbytes = bytes,
58
+ .copy_range = {
59
+ .aio_fd2 = s->fd,
60
+ .aio_offset2 = dst_offset,
61
+ },
62
+ };
63
+
64
+ return raw_thread_pool_submit(bs, handle_aiocb_copy_range, &acb);
65
}
66
67
BlockDriver bdrv_file = {
68
--
69
2.19.2
70
71
diff view generated by jsdifflib
Deleted patch
1
aio_worker() doesn't add anything interesting, it's only a useless
2
indirection. Call the handler function directly instead.
3
1
4
As we know that this handler function is only called from coroutine
5
context and the coroutine stays around until the worker thread finishes,
6
we can keep RawPosixAIOData on the stack.
7
8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9
---
10
block/file-posix.c | 27 +++++++++++++++++++--------
11
1 file changed, 19 insertions(+), 8 deletions(-)
12
13
diff --git a/block/file-posix.c b/block/file-posix.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/block/file-posix.c
16
+++ b/block/file-posix.c
17
@@ -XXX,XX +XXX,XX @@ static ssize_t handle_aiocb_rw_linear(RawPosixAIOData *aiocb, char *buf)
18
return offset;
19
}
20
21
-static ssize_t handle_aiocb_rw(RawPosixAIOData *aiocb)
22
+static int handle_aiocb_rw(void *opaque)
23
{
24
+ RawPosixAIOData *aiocb = opaque;
25
ssize_t nbytes;
26
char *buf;
27
28
@@ -XXX,XX +XXX,XX @@ static int aio_worker(void *arg)
29
ssize_t ret = 0;
30
31
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
32
- case QEMU_AIO_READ:
33
- ret = handle_aiocb_rw(aiocb);
34
- break;
35
- case QEMU_AIO_WRITE:
36
- ret = handle_aiocb_rw(aiocb);
37
- break;
38
case QEMU_AIO_IOCTL:
39
ret = handle_aiocb_ioctl(aiocb);
40
break;
41
+ case QEMU_AIO_READ:
42
+ case QEMU_AIO_WRITE:
43
case QEMU_AIO_FLUSH:
44
case QEMU_AIO_DISCARD:
45
case QEMU_AIO_WRITE_ZEROES:
46
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
47
uint64_t bytes, QEMUIOVector *qiov, int type)
48
{
49
BDRVRawState *s = bs->opaque;
50
+ RawPosixAIOData acb;
51
52
if (fd_open(bs) < 0)
53
return -EIO;
54
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
55
}
56
}
57
58
- return paio_submit_co(bs, s->fd, offset, qiov, bytes, type);
59
+ acb = (RawPosixAIOData) {
60
+ .bs = bs,
61
+ .aio_fildes = s->fd,
62
+ .aio_type = type,
63
+ .aio_offset = offset,
64
+ .aio_nbytes = bytes,
65
+ .io = {
66
+ .iov = qiov->iov,
67
+ .niov = qiov->niov,
68
+ },
69
+ };
70
+
71
+ assert(qiov->size == bytes);
72
+ return raw_thread_pool_submit(bs, handle_aiocb_rw, &acb);
73
}
74
75
static int coroutine_fn raw_co_preadv(BlockDriverState *bs, uint64_t offset,
76
--
77
2.19.2
78
79
diff view generated by jsdifflib
Deleted patch
1
The function is not used any more, remove it.
2
1
3
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
4
---
5
block/file-posix.c | 34 ----------------------------------
6
1 file changed, 34 deletions(-)
7
8
diff --git a/block/file-posix.c b/block/file-posix.c
9
index XXXXXXX..XXXXXXX 100644
10
--- a/block/file-posix.c
11
+++ b/block/file-posix.c
12
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
13
return thread_pool_submit_co(pool, func, arg);
14
}
15
16
-static int paio_submit_co_full(BlockDriverState *bs, int fd,
17
- int64_t offset, int fd2, int64_t offset2,
18
- QEMUIOVector *qiov,
19
- int bytes, int type)
20
-{
21
- RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
22
-
23
- acb->bs = bs;
24
- acb->aio_type = type;
25
- acb->aio_fildes = fd;
26
-
27
- acb->aio_nbytes = bytes;
28
- acb->aio_offset = offset;
29
-
30
- if (qiov) {
31
- acb->io.iov = qiov->iov;
32
- acb->io.niov = qiov->niov;
33
- assert(qiov->size == bytes);
34
- } else {
35
- acb->copy_range.aio_fd2 = fd2;
36
- acb->copy_range.aio_offset2 = offset2;
37
- }
38
-
39
- trace_file_paio_submit_co(offset, bytes, type);
40
- return raw_thread_pool_submit(bs, aio_worker, acb);
41
-}
42
-
43
-static inline int paio_submit_co(BlockDriverState *bs, int fd,
44
- int64_t offset, QEMUIOVector *qiov,
45
- int bytes, int type)
46
-{
47
- return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
48
-}
49
-
50
static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset,
51
uint64_t bytes, QEMUIOVector *qiov, int type)
52
{
53
--
54
2.19.2
55
56
diff view generated by jsdifflib