1
The following changes since commit 9548cbeffffd4253e38570d29b8cff0bf77c998f:
1
The following changes since commit 56f9e46b841c7be478ca038d8d4085d776ab4b0d:
2
2
3
iotests/copy-before-write: specify required_fmts (2022-07-12 13:21:02 +0530)
3
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2017-02-20' into staging (2017-02-20 17:42:47 +0000)
4
4
5
are available in the Git repository at:
5
are available in the git repository at:
6
6
7
https://gitlab.com/hreitz/qemu.git tags/pull-block-2022-07-12
7
git://github.com/stefanha/qemu.git tags/block-pull-request
8
8
9
for you to fetch changes up to 85c4bf8aa6c93c24876e8870ae7cf8ab2e5a96cf:
9
for you to fetch changes up to a7b91d35bab97a2d3e779d0c64c9b837b52a6cf7:
10
10
11
vl: Unlink absolute PID file path (2022-07-12 14:31:15 +0200)
11
coroutine-lock: make CoRwlock thread-safe and fair (2017-02-21 11:39:40 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Block patches:
14
Pull request
15
- Refactoring for non-coroutine variants of bdrv/blk_co_* functions:
15
16
Auto-generate more of them with the block coroutine wrapper generator
16
v2:
17
script
17
* Rebased to resolve scsi conflicts
18
- iotest fixes
19
- Both for the storage daemon and the system emulator: Fix PID file
20
handling when daemonizing (store the absolute path and delete that on
21
exit, which is necessary because daemonizing will change the working
22
directory to /)
23
18
24
----------------------------------------------------------------
19
----------------------------------------------------------------
25
Alberto Faria (28):
26
block: Add a 'flags' param to bdrv_{pread,pwrite,pwrite_sync}()
27
block: Change bdrv_{pread,pwrite,pwrite_sync}() param order
28
block: Make bdrv_{pread,pwrite}() return 0 on success
29
crypto: Make block callbacks return 0 on success
30
block: Make bdrv_co_pwrite() take a const buffer
31
block: Make 'bytes' param of bdrv_co_{pread,pwrite,preadv,pwritev}()
32
an int64_t
33
block: Implement bdrv_{pread,pwrite,pwrite_zeroes}() using
34
generated_co_wrapper
35
block: Add bdrv_co_pwrite_sync()
36
block: Use bdrv_co_pwrite_sync() when caller is coroutine_fn
37
block/qcow2: Use bdrv_pwrite_sync() in qcow2_mark_dirty()
38
block: Make blk_{pread,pwrite}() return 0 on success
39
block: Add a 'flags' param to blk_pread()
40
block: Change blk_{pread,pwrite}() param order
41
block: Make 'bytes' param of blk_{pread,pwrite}() an int64_t
42
block: Make blk_co_pwrite() take a const buffer
43
block: Implement blk_{pread,pwrite}() using generated_co_wrapper
44
block: Add blk_{preadv,pwritev}()
45
block: Add blk_[co_]preadv_part()
46
block: Export blk_pwritev_part() in block-backend-io.h
47
block: Change blk_pwrite_compressed() param order
48
block: Add blk_co_pwrite_compressed()
49
block: Implement blk_pwrite_zeroes() using generated_co_wrapper
50
block: Implement blk_pdiscard() using generated_co_wrapper
51
block: Implement blk_flush() using generated_co_wrapper
52
block: Add blk_co_ioctl()
53
block: Add blk_co_truncate()
54
block: Reorganize some declarations in block-backend-io.h
55
block: Remove remaining unused symbols in coroutines.h
56
20
57
Hanna Reitz (5):
21
Paolo Bonzini (24):
58
qsd: Do not use error_report() before monitor_init
22
block: move AioContext, QEMUTimer, main-loop to libqemuutil
59
iotests/297: Have mypy ignore unused ignores
23
aio: introduce aio_co_schedule and aio_co_wake
60
qsd: Unlink absolute PID file path
24
block-backend: allow blk_prw from coroutine context
61
vl: Conditionally register PID file unlink notifier
25
test-thread-pool: use generic AioContext infrastructure
62
vl: Unlink absolute PID file path
26
io: add methods to set I/O handlers on AioContext
27
io: make qio_channel_yield aware of AioContexts
28
nbd: convert to use qio_channel_yield
29
coroutine-lock: reschedule coroutine on the AioContext it was running
30
on
31
blkdebug: reschedule coroutine on the AioContext it is running on
32
qed: introduce qed_aio_start_io and qed_aio_next_io_cb
33
aio: push aio_context_acquire/release down to dispatching
34
block: explicitly acquire aiocontext in timers that need it
35
block: explicitly acquire aiocontext in callbacks that need it
36
block: explicitly acquire aiocontext in bottom halves that need it
37
block: explicitly acquire aiocontext in aio callbacks that need it
38
aio-posix: partially inline aio_dispatch into aio_poll
39
async: remove unnecessary inc/dec pairs
40
block: document fields protected by AioContext lock
41
coroutine-lock: make CoMutex thread-safe
42
coroutine-lock: add limited spinning to CoMutex
43
test-aio-multithread: add performance comparison with thread-based
44
mutexes
45
coroutine-lock: place CoMutex before CoQueue in header
46
coroutine-lock: add mutex argument to CoQueue APIs
47
coroutine-lock: make CoRwlock thread-safe and fair
63
48
64
John Snow (2):
49
Makefile.objs | 4 -
65
tests/qemu-iotests: hotfix for 307, 223 output
50
stubs/Makefile.objs | 1 +
66
tests/qemu-iotests: skip 108 when FUSE is not loaded
51
tests/Makefile.include | 19 +-
67
52
util/Makefile.objs | 6 +-
68
block/coroutines.h | 44 --------
53
block/nbd-client.h | 2 +-
69
include/block/block-io.h | 22 ++--
54
block/qed.h | 3 +
70
include/block/block_int-io.h | 4 +-
55
include/block/aio.h | 38 ++-
71
include/crypto/block.h | 32 +++---
56
include/block/block_int.h | 64 +++--
72
include/sysemu/block-backend-io.h | 97 ++++++++++-------
57
include/io/channel.h | 72 +++++-
73
block.c | 10 +-
58
include/qemu/coroutine.h | 84 ++++---
74
block/blklogwrites.c | 6 +-
59
include/qemu/coroutine_int.h | 11 +-
75
block/block-backend.c | 150 +++++++++++---------------
60
include/sysemu/block-backend.h | 14 +-
76
block/bochs.c | 10 +-
61
tests/iothread.h | 25 ++
77
block/cloop.c | 12 +--
62
block/backup.c | 2 +-
78
block/commit.c | 4 +-
63
block/blkdebug.c | 9 +-
79
block/crypto.c | 58 +++++-----
64
block/blkreplay.c | 2 +-
80
block/dmg.c | 36 +++----
65
block/block-backend.c | 13 +-
81
block/export/fuse.c | 4 +-
66
block/curl.c | 44 +++-
82
block/io.c | 55 +---------
67
block/gluster.c | 9 +-
83
block/parallels-ext.c | 6 +-
68
block/io.c | 42 +---
84
block/parallels.c | 14 +--
69
block/iscsi.c | 15 +-
85
block/qcow.c | 55 +++++-----
70
block/linux-aio.c | 10 +-
86
block/qcow2-bitmap.c | 14 +--
71
block/mirror.c | 12 +-
87
block/qcow2-cache.c | 9 +-
72
block/nbd-client.c | 119 +++++----
88
block/qcow2-cluster.c | 19 ++--
73
block/nfs.c | 9 +-
89
block/qcow2-refcount.c | 58 +++++-----
74
block/qcow2-cluster.c | 4 +-
90
block/qcow2-snapshot.c | 53 +++++-----
75
block/qed-cluster.c | 2 +
91
block/qcow2.c | 84 +++++++--------
76
block/qed-table.c | 12 +-
92
block/qed.c | 21 ++--
77
block/qed.c | 58 +++--
93
block/vdi.c | 20 ++--
78
block/sheepdog.c | 31 +--
94
block/vhdx-log.c | 23 ++--
79
block/ssh.c | 29 +--
95
block/vhdx.c | 56 +++++-----
80
block/throttle-groups.c | 4 +-
96
block/vmdk.c | 80 +++++++-------
81
block/win32-aio.c | 9 +-
97
block/vpc.c | 35 +++---
82
dma-helpers.c | 2 +
98
block/vvfat.c | 11 +-
83
hw/9pfs/9p.c | 2 +-
99
crypto/block-luks.c | 8 +-
84
hw/block/virtio-blk.c | 19 +-
100
crypto/block.c | 6 +-
85
hw/scsi/scsi-bus.c | 2 +
101
hw/arm/allwinner-h3.c | 2 +-
86
hw/scsi/scsi-disk.c | 15 ++
102
hw/arm/aspeed.c | 2 +-
87
hw/scsi/scsi-generic.c | 20 +-
103
hw/block/block.c | 2 +-
88
hw/scsi/virtio-scsi.c | 7 +
104
hw/block/fdc.c | 20 ++--
89
io/channel-command.c | 13 +
105
hw/block/hd-geometry.c | 2 +-
90
io/channel-file.c | 11 +
106
hw/block/m25p80.c | 2 +-
91
io/channel-socket.c | 16 +-
107
hw/block/nand.c | 47 ++++----
92
io/channel-tls.c | 12 +
108
hw/block/onenand.c | 32 +++---
93
io/channel-watch.c | 6 +
109
hw/block/pflash_cfi01.c | 4 +-
94
io/channel.c | 97 ++++++--
110
hw/block/pflash_cfi02.c | 4 +-
95
nbd/client.c | 2 +-
111
hw/ide/atapi.c | 4 +-
96
nbd/common.c | 9 +-
112
hw/misc/mac_via.c | 6 +-
97
nbd/server.c | 94 +++-----
113
hw/misc/sifive_u_otp.c | 14 +--
98
stubs/linux-aio.c | 32 +++
114
hw/nvram/eeprom_at24c.c | 8 +-
99
stubs/set-fd-handler.c | 11 -
115
hw/nvram/spapr_nvram.c | 16 +--
100
tests/iothread.c | 91 +++++++
116
hw/nvram/xlnx-bbram.c | 4 +-
101
tests/test-aio-multithread.c | 463 ++++++++++++++++++++++++++++++++++++
117
hw/nvram/xlnx-efuse.c | 4 +-
102
tests/test-thread-pool.c | 12 +-
118
hw/ppc/pnv_pnor.c | 6 +-
103
aio-posix.c => util/aio-posix.c | 62 ++---
119
hw/sd/sd.c | 4 +-
104
aio-win32.c => util/aio-win32.c | 30 +--
120
migration/block.c | 8 +-
105
util/aiocb.c | 55 +++++
121
nbd/server.c | 8 +-
106
async.c => util/async.c | 84 ++++++-
122
qemu-img.c | 41 +++----
107
iohandler.c => util/iohandler.c | 0
123
qemu-io-cmds.c | 20 ++--
108
main-loop.c => util/main-loop.c | 0
124
softmmu/vl.c | 42 ++++++--
109
util/qemu-coroutine-lock.c | 254 ++++++++++++++++++--
125
storage-daemon/qemu-storage-daemon.c | 17 ++-
110
util/qemu-coroutine-sleep.c | 2 +-
126
tests/unit/test-block-iothread.c | 153 ++++++++++++++++++++++++---
111
util/qemu-coroutine.c | 8 +
127
tests/unit/test-crypto-block.c | 38 +++----
112
qemu-timer.c => util/qemu-timer.c | 0
128
block/meson.build | 1 +
113
thread-pool.c => util/thread-pool.c | 8 +-
129
tests/qemu-iotests/108 | 5 +
114
trace-events | 11 -
130
tests/qemu-iotests/223.out | 4 +-
115
util/trace-events | 17 +-
131
tests/qemu-iotests/307.out | 4 +-
116
67 files changed, 1712 insertions(+), 533 deletions(-)
132
tests/qemu-iotests/mypy.ini | 2 +-
117
create mode 100644 tests/iothread.h
133
65 files changed, 856 insertions(+), 786 deletions(-)
118
create mode 100644 stubs/linux-aio.c
119
create mode 100644 tests/iothread.c
120
create mode 100644 tests/test-aio-multithread.c
121
rename aio-posix.c => util/aio-posix.c (94%)
122
rename aio-win32.c => util/aio-win32.c (95%)
123
create mode 100644 util/aiocb.c
124
rename async.c => util/async.c (82%)
125
rename iohandler.c => util/iohandler.c (100%)
126
rename main-loop.c => util/main-loop.c (100%)
127
rename qemu-timer.c => util/qemu-timer.c (100%)
128
rename thread-pool.c => util/thread-pool.c (97%)
134
129
135
--
130
--
136
2.35.3
131
2.9.3
132
133
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
bdrv_{pread,pwrite}() now return -EIO instead of -EINVAL when 'bytes' is
3
AioContext is fairly self contained, the only dependency is QEMUTimer but
4
negative, making them consistent with bdrv_{preadv,pwritev}() and
4
that in turn doesn't need anything else. So move them out of block-obj-y
5
bdrv_co_{pread,pwrite,preadv,pwritev}().
5
to avoid introducing a dependency from io/ to block-obj-y.
6
6
7
bdrv_pwrite_zeroes() now also calls trace_bdrv_co_pwrite_zeroes() and
7
main-loop and its dependency iohandler also need to be moved, because
8
clears the BDRV_REQ_MAY_UNMAP flag when appropriate, which it didn't
8
later in this series io/ will call iohandler_get_aio_context.
9
previously.
9
10
10
[Changed copyright "the QEMU team" to "other QEMU contributors" as
11
Signed-off-by: Alberto Faria <afaria@redhat.com>
11
suggested by Daniel Berrange and agreed by Paolo.
12
Message-Id: <20220609152744.3891847-8-afaria@redhat.com>
12
--Stefan]
13
Reviewed-by: Eric Blake <eblake@redhat.com>
13
14
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
14
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
15
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
Reviewed-by: Fam Zheng <famz@redhat.com>
16
Message-id: 20170213135235.12274-2-pbonzini@redhat.com
17
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
16
---
18
---
17
include/block/block-io.h | 15 +++++++++------
19
Makefile.objs | 4 ---
18
block/io.c | 41 ----------------------------------------
20
stubs/Makefile.objs | 1 +
19
2 files changed, 9 insertions(+), 47 deletions(-)
21
tests/Makefile.include | 11 ++++----
20
22
util/Makefile.objs | 6 +++-
21
diff --git a/include/block/block-io.h b/include/block/block-io.h
23
block/io.c | 29 -------------------
22
index XXXXXXX..XXXXXXX 100644
24
stubs/linux-aio.c | 32 +++++++++++++++++++++
23
--- a/include/block/block-io.h
25
stubs/set-fd-handler.c | 11 --------
24
+++ b/include/block/block-io.h
26
aio-posix.c => util/aio-posix.c | 2 +-
25
@@ -XXX,XX +XXX,XX @@
27
aio-win32.c => util/aio-win32.c | 0
26
* to catch when they are accidentally called by the wrong API.
28
util/aiocb.c | 55 +++++++++++++++++++++++++++++++++++++
27
*/
29
async.c => util/async.c | 3 +-
28
30
iohandler.c => util/iohandler.c | 0
29
-int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
31
main-loop.c => util/main-loop.c | 0
30
- int64_t bytes, BdrvRequestFlags flags);
32
qemu-timer.c => util/qemu-timer.c | 0
31
+int generated_co_wrapper bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
33
thread-pool.c => util/thread-pool.c | 2 +-
32
+ int64_t bytes,
34
trace-events | 11 --------
33
+ BdrvRequestFlags flags);
35
util/trace-events | 11 ++++++++
34
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
36
17 files changed, 114 insertions(+), 64 deletions(-)
35
-int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
37
create mode 100644 stubs/linux-aio.c
36
- BdrvRequestFlags flags);
38
rename aio-posix.c => util/aio-posix.c (99%)
37
-int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
39
rename aio-win32.c => util/aio-win32.c (100%)
38
- const void *buf, BdrvRequestFlags flags);
40
create mode 100644 util/aiocb.c
39
+int generated_co_wrapper bdrv_pread(BdrvChild *child, int64_t offset,
41
rename async.c => util/async.c (99%)
40
+ int64_t bytes, void *buf,
42
rename iohandler.c => util/iohandler.c (100%)
41
+ BdrvRequestFlags flags);
43
rename main-loop.c => util/main-loop.c (100%)
42
+int generated_co_wrapper bdrv_pwrite(BdrvChild *child, int64_t offset,
44
rename qemu-timer.c => util/qemu-timer.c (100%)
43
+ int64_t bytes, const void *buf,
45
rename thread-pool.c => util/thread-pool.c (99%)
44
+ BdrvRequestFlags flags);
46
45
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
47
diff --git a/Makefile.objs b/Makefile.objs
46
const void *buf, BdrvRequestFlags flags);
48
index XXXXXXX..XXXXXXX 100644
47
/*
49
--- a/Makefile.objs
50
+++ b/Makefile.objs
51
@@ -XXX,XX +XXX,XX @@ chardev-obj-y = chardev/
52
#######################################################################
53
# block-obj-y is code used by both qemu system emulation and qemu-img
54
55
-block-obj-y = async.o thread-pool.o
56
block-obj-y += nbd/
57
block-obj-y += block.o blockjob.o
58
-block-obj-y += main-loop.o iohandler.o qemu-timer.o
59
-block-obj-$(CONFIG_POSIX) += aio-posix.o
60
-block-obj-$(CONFIG_WIN32) += aio-win32.o
61
block-obj-y += block/
62
block-obj-y += qemu-io-cmds.o
63
block-obj-$(CONFIG_REPLICATION) += replication.o
64
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
65
index XXXXXXX..XXXXXXX 100644
66
--- a/stubs/Makefile.objs
67
+++ b/stubs/Makefile.objs
68
@@ -XXX,XX +XXX,XX @@ stub-obj-y += get-vm-name.o
69
stub-obj-y += iothread.o
70
stub-obj-y += iothread-lock.o
71
stub-obj-y += is-daemonized.o
72
+stub-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
73
stub-obj-y += machine-init-done.o
74
stub-obj-y += migr-blocker.o
75
stub-obj-y += monitor.o
76
diff --git a/tests/Makefile.include b/tests/Makefile.include
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tests/Makefile.include
79
+++ b/tests/Makefile.include
80
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-visitor-serialization$(EXESUF)
81
check-unit-y += tests/test-iov$(EXESUF)
82
gcov-files-test-iov-y = util/iov.c
83
check-unit-y += tests/test-aio$(EXESUF)
84
+gcov-files-test-aio-y = util/async.c util/qemu-timer.o
85
+gcov-files-test-aio-$(CONFIG_WIN32) += util/aio-win32.c
86
+gcov-files-test-aio-$(CONFIG_POSIX) += util/aio-posix.c
87
check-unit-y += tests/test-throttle$(EXESUF)
88
gcov-files-test-aio-$(CONFIG_WIN32) = aio-win32.c
89
gcov-files-test-aio-$(CONFIG_POSIX) = aio-posix.c
90
@@ -XXX,XX +XXX,XX @@ tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
91
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
92
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
93
94
-tests/test-char$(EXESUF): tests/test-char.o qemu-timer.o \
95
-    $(test-util-obj-y) $(qtest-obj-y) $(test-block-obj-y) $(chardev-obj-y)
96
+tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y) $(chardev-obj-y)
97
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
98
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
99
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
100
@@ -XXX,XX +XXX,XX @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
101
    migration/vmstate.o migration/qemu-file.o \
102
migration/qemu-file-channel.o migration/qjson.o \
103
    $(test-io-obj-y)
104
-tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
105
-    $(test-util-obj-y)
106
+tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y)
107
tests/test-base64$(EXESUF): tests/test-base64.o \
108
    libqemuutil.a libqemustub.a
109
tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o libqemustub.a
110
@@ -XXX,XX +XXX,XX @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
111
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
112
tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
113
tests/postcopy-test$(EXESUF): tests/postcopy-test.o
114
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-timer.o \
115
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o $(test-util-obj-y) \
116
    $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \
117
    $(chardev-obj-y)
118
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
119
diff --git a/util/Makefile.objs b/util/Makefile.objs
120
index XXXXXXX..XXXXXXX 100644
121
--- a/util/Makefile.objs
122
+++ b/util/Makefile.objs
123
@@ -XXX,XX +XXX,XX @@
124
util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o
125
util-obj-y += bufferiszero.o
126
util-obj-y += lockcnt.o
127
+util-obj-y += aiocb.o async.o thread-pool.o qemu-timer.o
128
+util-obj-y += main-loop.o iohandler.o
129
+util-obj-$(CONFIG_POSIX) += aio-posix.o
130
util-obj-$(CONFIG_POSIX) += compatfd.o
131
util-obj-$(CONFIG_POSIX) += event_notifier-posix.o
132
util-obj-$(CONFIG_POSIX) += mmap-alloc.o
133
util-obj-$(CONFIG_POSIX) += oslib-posix.o
134
util-obj-$(CONFIG_POSIX) += qemu-openpty.o
135
util-obj-$(CONFIG_POSIX) += qemu-thread-posix.o
136
-util-obj-$(CONFIG_WIN32) += event_notifier-win32.o
137
util-obj-$(CONFIG_POSIX) += memfd.o
138
+util-obj-$(CONFIG_WIN32) += aio-win32.o
139
+util-obj-$(CONFIG_WIN32) += event_notifier-win32.o
140
util-obj-$(CONFIG_WIN32) += oslib-win32.o
141
util-obj-$(CONFIG_WIN32) += qemu-thread-win32.o
142
util-obj-y += envlist.o path.o module.o
48
diff --git a/block/io.c b/block/io.c
143
diff --git a/block/io.c b/block/io.c
49
index XXXXXXX..XXXXXXX 100644
144
index XXXXXXX..XXXXXXX 100644
50
--- a/block/io.c
145
--- a/block/io.c
51
+++ b/block/io.c
146
+++ b/block/io.c
52
@@ -XXX,XX +XXX,XX @@ static int bdrv_check_request32(int64_t offset, int64_t bytes,
147
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *bdrv_aio_flush(BlockDriverState *bs,
53
return 0;
148
return &acb->common;
54
}
149
}
55
150
56
-int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
151
-void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
57
- int64_t bytes, BdrvRequestFlags flags)
152
- BlockCompletionFunc *cb, void *opaque)
58
-{
153
-{
59
- IO_CODE();
154
- BlockAIOCB *acb;
60
- return bdrv_pwritev(child, offset, bytes, NULL,
155
-
61
- BDRV_REQ_ZERO_WRITE | flags);
156
- acb = g_malloc(aiocb_info->aiocb_size);
157
- acb->aiocb_info = aiocb_info;
158
- acb->bs = bs;
159
- acb->cb = cb;
160
- acb->opaque = opaque;
161
- acb->refcnt = 1;
162
- return acb;
62
-}
163
-}
63
-
164
-
165
-void qemu_aio_ref(void *p)
166
-{
167
- BlockAIOCB *acb = p;
168
- acb->refcnt++;
169
-}
170
-
171
-void qemu_aio_unref(void *p)
172
-{
173
- BlockAIOCB *acb = p;
174
- assert(acb->refcnt > 0);
175
- if (--acb->refcnt == 0) {
176
- g_free(acb);
177
- }
178
-}
179
-
180
/**************************************************************/
181
/* Coroutine block device emulation */
182
183
diff --git a/stubs/linux-aio.c b/stubs/linux-aio.c
184
new file mode 100644
185
index XXXXXXX..XXXXXXX
186
--- /dev/null
187
+++ b/stubs/linux-aio.c
188
@@ -XXX,XX +XXX,XX @@
189
+/*
190
+ * Linux native AIO support.
191
+ *
192
+ * Copyright (C) 2009 IBM, Corp.
193
+ * Copyright (C) 2009 Red Hat, Inc.
194
+ *
195
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
196
+ * See the COPYING file in the top-level directory.
197
+ */
198
+#include "qemu/osdep.h"
199
+#include "block/aio.h"
200
+#include "block/raw-aio.h"
201
+
202
+void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
203
+{
204
+ abort();
205
+}
206
+
207
+void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
208
+{
209
+ abort();
210
+}
211
+
212
+LinuxAioState *laio_init(void)
213
+{
214
+ abort();
215
+}
216
+
217
+void laio_cleanup(LinuxAioState *s)
218
+{
219
+ abort();
220
+}
221
diff --git a/stubs/set-fd-handler.c b/stubs/set-fd-handler.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/stubs/set-fd-handler.c
224
+++ b/stubs/set-fd-handler.c
225
@@ -XXX,XX +XXX,XX @@ void qemu_set_fd_handler(int fd,
226
{
227
abort();
228
}
229
-
230
-void aio_set_fd_handler(AioContext *ctx,
231
- int fd,
232
- bool is_external,
233
- IOHandler *io_read,
234
- IOHandler *io_write,
235
- AioPollFn *io_poll,
236
- void *opaque)
237
-{
238
- abort();
239
-}
240
diff --git a/aio-posix.c b/util/aio-posix.c
241
similarity index 99%
242
rename from aio-posix.c
243
rename to util/aio-posix.c
244
index XXXXXXX..XXXXXXX 100644
245
--- a/aio-posix.c
246
+++ b/util/aio-posix.c
247
@@ -XXX,XX +XXX,XX @@
248
#include "qemu/rcu_queue.h"
249
#include "qemu/sockets.h"
250
#include "qemu/cutils.h"
251
-#include "trace-root.h"
252
+#include "trace.h"
253
#ifdef CONFIG_EPOLL_CREATE1
254
#include <sys/epoll.h>
255
#endif
256
diff --git a/aio-win32.c b/util/aio-win32.c
257
similarity index 100%
258
rename from aio-win32.c
259
rename to util/aio-win32.c
260
diff --git a/util/aiocb.c b/util/aiocb.c
261
new file mode 100644
262
index XXXXXXX..XXXXXXX
263
--- /dev/null
264
+++ b/util/aiocb.c
265
@@ -XXX,XX +XXX,XX @@
266
+/*
267
+ * BlockAIOCB allocation
268
+ *
269
+ * Copyright (c) 2003-2017 Fabrice Bellard and other QEMU contributors
270
+ *
271
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
272
+ * of this software and associated documentation files (the "Software"), to deal
273
+ * in the Software without restriction, including without limitation the rights
274
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
275
+ * copies of the Software, and to permit persons to whom the Software is
276
+ * furnished to do so, subject to the following conditions:
277
+ *
278
+ * The above copyright notice and this permission notice shall be included in
279
+ * all copies or substantial portions of the Software.
280
+ *
281
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
282
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
283
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
284
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
285
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
286
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
287
+ * THE SOFTWARE.
288
+ */
289
+
290
+#include "qemu/osdep.h"
291
+#include "block/aio.h"
292
+
293
+void *qemu_aio_get(const AIOCBInfo *aiocb_info, BlockDriverState *bs,
294
+ BlockCompletionFunc *cb, void *opaque)
295
+{
296
+ BlockAIOCB *acb;
297
+
298
+ acb = g_malloc(aiocb_info->aiocb_size);
299
+ acb->aiocb_info = aiocb_info;
300
+ acb->bs = bs;
301
+ acb->cb = cb;
302
+ acb->opaque = opaque;
303
+ acb->refcnt = 1;
304
+ return acb;
305
+}
306
+
307
+void qemu_aio_ref(void *p)
308
+{
309
+ BlockAIOCB *acb = p;
310
+ acb->refcnt++;
311
+}
312
+
313
+void qemu_aio_unref(void *p)
314
+{
315
+ BlockAIOCB *acb = p;
316
+ assert(acb->refcnt > 0);
317
+ if (--acb->refcnt == 0) {
318
+ g_free(acb);
319
+ }
320
+}
321
diff --git a/async.c b/util/async.c
322
similarity index 99%
323
rename from async.c
324
rename to util/async.c
325
index XXXXXXX..XXXXXXX 100644
326
--- a/async.c
327
+++ b/util/async.c
328
@@ -XXX,XX +XXX,XX @@
64
/*
329
/*
65
* Completely zero out a block device with the help of bdrv_pwrite_zeroes.
330
- * QEMU System Emulator
66
* The operation is sped up by checking the block status and only writing
331
+ * Data plane event loop
67
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
332
*
68
}
333
* Copyright (c) 2003-2008 Fabrice Bellard
69
}
334
+ * Copyright (c) 2009-2017 QEMU contributors
70
335
*
71
-/* See bdrv_pwrite() for the return codes */
336
* Permission is hereby granted, free of charge, to any person obtaining a copy
72
-int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
337
* of this software and associated documentation files (the "Software"), to deal
73
- BdrvRequestFlags flags)
338
diff --git a/iohandler.c b/util/iohandler.c
74
-{
339
similarity index 100%
75
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
340
rename from iohandler.c
76
- IO_CODE();
341
rename to util/iohandler.c
77
-
342
diff --git a/main-loop.c b/util/main-loop.c
78
- if (bytes < 0) {
343
similarity index 100%
79
- return -EINVAL;
344
rename from main-loop.c
80
- }
345
rename to util/main-loop.c
81
-
346
diff --git a/qemu-timer.c b/util/qemu-timer.c
82
- return bdrv_preadv(child, offset, bytes, &qiov, flags);
347
similarity index 100%
83
-}
348
rename from qemu-timer.c
84
-
349
rename to util/qemu-timer.c
85
-/* Return no. of bytes on success or < 0 on error. Important errors are:
350
diff --git a/thread-pool.c b/util/thread-pool.c
86
- -EIO generic I/O error (may happen for all errors)
351
similarity index 99%
87
- -ENOMEDIUM No media inserted.
352
rename from thread-pool.c
88
- -EINVAL Invalid offset or number of bytes
353
rename to util/thread-pool.c
89
- -EACCES Trying to write a read-only device
354
index XXXXXXX..XXXXXXX 100644
90
-*/
355
--- a/thread-pool.c
91
-int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
356
+++ b/util/thread-pool.c
92
- const void *buf, BdrvRequestFlags flags)
357
@@ -XXX,XX +XXX,XX @@
93
-{
358
#include "qemu/queue.h"
94
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
359
#include "qemu/thread.h"
95
- IO_CODE();
360
#include "qemu/coroutine.h"
96
-
361
-#include "trace-root.h"
97
- if (bytes < 0) {
362
+#include "trace.h"
98
- return -EINVAL;
363
#include "block/thread-pool.h"
99
- }
364
#include "qemu/main-loop.h"
100
-
365
101
- return bdrv_pwritev(child, offset, bytes, &qiov, flags);
366
diff --git a/trace-events b/trace-events
102
-}
367
index XXXXXXX..XXXXXXX 100644
103
-
368
--- a/trace-events
104
/*
369
+++ b/trace-events
105
* Writes to the file and ensures that no writes are reordered across this
370
@@ -XXX,XX +XXX,XX @@
106
* request (acts as a barrier)
371
#
372
# The <format-string> should be a sprintf()-compatible format string.
373
374
-# aio-posix.c
375
-run_poll_handlers_begin(void *ctx, int64_t max_ns) "ctx %p max_ns %"PRId64
376
-run_poll_handlers_end(void *ctx, bool progress) "ctx %p progress %d"
377
-poll_shrink(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
378
-poll_grow(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
379
-
380
-# thread-pool.c
381
-thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
382
-thread_pool_complete(void *pool, void *req, void *opaque, int ret) "pool %p req %p opaque %p ret %d"
383
-thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
384
-
385
# ioport.c
386
cpu_in(unsigned int addr, char size, unsigned int val) "addr %#x(%c) value %u"
387
cpu_out(unsigned int addr, char size, unsigned int val) "addr %#x(%c) value %u"
388
diff --git a/util/trace-events b/util/trace-events
389
index XXXXXXX..XXXXXXX 100644
390
--- a/util/trace-events
391
+++ b/util/trace-events
392
@@ -XXX,XX +XXX,XX @@
393
# See docs/tracing.txt for syntax documentation.
394
395
+# util/aio-posix.c
396
+run_poll_handlers_begin(void *ctx, int64_t max_ns) "ctx %p max_ns %"PRId64
397
+run_poll_handlers_end(void *ctx, bool progress) "ctx %p progress %d"
398
+poll_shrink(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
399
+poll_grow(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
400
+
401
+# util/thread-pool.c
402
+thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
403
+thread_pool_complete(void *pool, void *req, void *opaque, int ret) "pool %p req %p opaque %p ret %d"
404
+thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
405
+
406
# util/buffer.c
407
buffer_resize(const char *buf, size_t olen, size_t len) "%s: old %zd, new %zd"
408
buffer_move_empty(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
107
--
409
--
108
2.35.3
410
2.9.3
411
412
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Some can be made static, others are unused generated_co_wrappers.
3
aio_co_wake provides the infrastructure to start a coroutine on a "home"
4
4
AioContext. It will be used by CoMutex and CoQueue, so that coroutines
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
5
don't jump from one context to another when they go to sleep on a
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
6
mutex or waitqueue. However, it can also be used as a more efficient
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
7
alternative to one-shot bottom halves, and saves the effort of tracking
8
Message-Id: <20220705161527.1054072-19-afaria@redhat.com>
8
which AioContext a coroutine is running on.
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
10
aio_co_schedule is the part of aio_co_wake that starts a coroutine
11
on a remove AioContext, but it is also useful to implement e.g.
12
bdrv_set_aio_context callbacks.
13
14
The implementation of aio_co_schedule is based on a lock-free
15
multiple-producer, single-consumer queue. The multiple producers use
16
cmpxchg to add to a LIFO stack. The consumer (a per-AioContext bottom
17
half) grabs all items added so far, inverts the list to make it FIFO,
18
and goes through it one item at a time until it's empty. The data
19
structure was inspired by OSv, which uses it in the very code we'll
20
"port" to QEMU for the thread-safe CoMutex.
21
22
Most of the new code is really tests.
23
24
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
25
Reviewed-by: Fam Zheng <famz@redhat.com>
26
Message-id: 20170213135235.12274-3-pbonzini@redhat.com
27
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
28
---
11
block/coroutines.h | 19 -------------------
29
tests/Makefile.include | 8 +-
12
block/block-backend.c | 6 +++---
30
include/block/aio.h | 32 +++++++
13
2 files changed, 3 insertions(+), 22 deletions(-)
31
include/qemu/coroutine_int.h | 11 ++-
14
32
tests/iothread.h | 25 +++++
15
diff --git a/block/coroutines.h b/block/coroutines.h
33
tests/iothread.c | 91 ++++++++++++++++++
34
tests/test-aio-multithread.c | 213 +++++++++++++++++++++++++++++++++++++++++++
35
util/async.c | 65 +++++++++++++
36
util/qemu-coroutine.c | 8 ++
37
util/trace-events | 4 +
38
9 files changed, 453 insertions(+), 4 deletions(-)
39
create mode 100644 tests/iothread.h
40
create mode 100644 tests/iothread.c
41
create mode 100644 tests/test-aio-multithread.c
42
43
diff --git a/tests/Makefile.include b/tests/Makefile.include
16
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
17
--- a/block/coroutines.h
45
--- a/tests/Makefile.include
18
+++ b/block/coroutines.h
46
+++ b/tests/Makefile.include
19
@@ -XXX,XX +XXX,XX @@ nbd_co_do_establish_connection(BlockDriverState *bs, bool blocking,
47
@@ -XXX,XX +XXX,XX @@ check-unit-y += tests/test-aio$(EXESUF)
20
Error **errp);
48
gcov-files-test-aio-y = util/async.c util/qemu-timer.o
21
49
gcov-files-test-aio-$(CONFIG_WIN32) += util/aio-win32.c
22
50
gcov-files-test-aio-$(CONFIG_POSIX) += util/aio-posix.c
23
-int coroutine_fn
51
+check-unit-y += tests/test-aio-multithread$(EXESUF)
24
-blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
52
+gcov-files-test-aio-multithread-y = $(gcov-files-test-aio-y)
25
- QEMUIOVector *qiov, size_t qiov_offset,
53
+gcov-files-test-aio-multithread-y += util/qemu-coroutine.c tests/iothread.c
26
- BdrvRequestFlags flags);
54
check-unit-y += tests/test-throttle$(EXESUF)
27
-
55
-gcov-files-test-aio-$(CONFIG_WIN32) = aio-win32.c
28
-int coroutine_fn
56
-gcov-files-test-aio-$(CONFIG_POSIX) = aio-posix.c
29
-blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
57
check-unit-y += tests/test-thread-pool$(EXESUF)
30
-
58
gcov-files-test-thread-pool-y = thread-pool.c
31
-int coroutine_fn blk_co_do_flush(BlockBackend *blk);
59
gcov-files-test-hbitmap-y = util/hbitmap.c
32
-
60
@@ -XXX,XX +XXX,XX @@ test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
33
-
61
    $(test-qom-obj-y)
34
/*
62
test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
35
* "I/O or GS" API functions. These functions can run without
63
test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
36
* the BQL, but only in one specific iothread/main loop.
64
-test-block-obj-y = $(block-obj-y) $(test-io-obj-y)
37
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_do_flush(BlockBackend *blk);
65
+test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
38
* the "I/O or GS" API.
66
39
*/
67
tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y)
40
68
tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
41
-int generated_co_wrapper
69
@@ -XXX,XX +XXX,XX @@ tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
42
-bdrv_preadv(BdrvChild *child, int64_t offset, int64_t bytes,
70
tests/test-char$(EXESUF): tests/test-char.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y) $(chardev-obj-y)
43
- QEMUIOVector *qiov, BdrvRequestFlags flags);
71
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
44
-
72
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
45
-int generated_co_wrapper
73
+tests/test-aio-multithread$(EXESUF): tests/test-aio-multithread.o $(test-block-obj-y)
46
-bdrv_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
74
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
47
- QEMUIOVector *qiov, BdrvRequestFlags flags);
75
tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y)
48
-
76
tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
49
int generated_co_wrapper
77
diff --git a/include/block/aio.h b/include/block/aio.h
50
bdrv_common_block_status_above(BlockDriverState *bs,
51
BlockDriverState *base,
52
diff --git a/block/block-backend.c b/block/block-backend.c
53
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
54
--- a/block/block-backend.c
79
--- a/include/block/aio.h
55
+++ b/block/block-backend.c
80
+++ b/include/block/aio.h
56
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
81
@@ -XXX,XX +XXX,XX @@ typedef void QEMUBHFunc(void *opaque);
82
typedef bool AioPollFn(void *opaque);
83
typedef void IOHandler(void *opaque);
84
85
+struct Coroutine;
86
struct ThreadPool;
87
struct LinuxAioState;
88
89
@@ -XXX,XX +XXX,XX @@ struct AioContext {
90
bool notified;
91
EventNotifier notifier;
92
93
+ QSLIST_HEAD(, Coroutine) scheduled_coroutines;
94
+ QEMUBH *co_schedule_bh;
95
+
96
/* Thread pool for performing work and receiving completion callbacks.
97
* Has its own locking.
98
*/
99
@@ -XXX,XX +XXX,XX @@ static inline bool aio_node_check(AioContext *ctx, bool is_external)
57
}
100
}
58
101
59
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
102
/**
60
-int coroutine_fn
103
+ * aio_co_schedule:
61
+static int coroutine_fn
104
+ * @ctx: the aio context
62
blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
105
+ * @co: the coroutine
63
QEMUIOVector *qiov, size_t qiov_offset,
106
+ *
64
BdrvRequestFlags flags)
107
+ * Start a coroutine on a remote AioContext.
65
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_ioctl(BlockBackend *blk, unsigned long int req, void *buf,
108
+ *
109
+ * The coroutine must not be entered by anyone else while aio_co_schedule()
110
+ * is active. In addition the coroutine must have yielded unless ctx
111
+ * is the context in which the coroutine is running (i.e. the value of
112
+ * qemu_get_current_aio_context() from the coroutine itself).
113
+ */
114
+void aio_co_schedule(AioContext *ctx, struct Coroutine *co);
115
+
116
+/**
117
+ * aio_co_wake:
118
+ * @co: the coroutine
119
+ *
120
+ * Restart a coroutine on the AioContext where it was running last, thus
121
+ * preventing coroutines from jumping from one context to another when they
122
+ * go to sleep.
123
+ *
124
+ * aio_co_wake may be executed either in coroutine or non-coroutine
125
+ * context. The coroutine must not be entered by anyone else while
126
+ * aio_co_wake() is active.
127
+ */
128
+void aio_co_wake(struct Coroutine *co);
129
+
130
+/**
131
* Return the AioContext whose event loop runs in the current thread.
132
*
133
* If called from an IOThread this will be the IOThread's AioContext. If
134
diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
135
index XXXXXXX..XXXXXXX 100644
136
--- a/include/qemu/coroutine_int.h
137
+++ b/include/qemu/coroutine_int.h
138
@@ -XXX,XX +XXX,XX @@ struct Coroutine {
139
CoroutineEntry *entry;
140
void *entry_arg;
141
Coroutine *caller;
142
+
143
+ /* Only used when the coroutine has terminated. */
144
QSLIST_ENTRY(Coroutine) pool_next;
145
+
146
size_t locks_held;
147
148
- /* Coroutines that should be woken up when we yield or terminate */
149
+ /* Coroutines that should be woken up when we yield or terminate.
150
+ * Only used when the coroutine is running.
151
+ */
152
QSIMPLEQ_HEAD(, Coroutine) co_queue_wakeup;
153
+
154
+ /* Only used when the coroutine has yielded. */
155
+ AioContext *ctx;
156
QSIMPLEQ_ENTRY(Coroutine) co_queue_next;
157
+ QSLIST_ENTRY(Coroutine) co_scheduled_next;
158
};
159
160
Coroutine *qemu_coroutine_new(void);
161
diff --git a/tests/iothread.h b/tests/iothread.h
162
new file mode 100644
163
index XXXXXXX..XXXXXXX
164
--- /dev/null
165
+++ b/tests/iothread.h
166
@@ -XXX,XX +XXX,XX @@
167
+/*
168
+ * Event loop thread implementation for unit tests
169
+ *
170
+ * Copyright Red Hat Inc., 2013, 2016
171
+ *
172
+ * Authors:
173
+ * Stefan Hajnoczi <stefanha@redhat.com>
174
+ * Paolo Bonzini <pbonzini@redhat.com>
175
+ *
176
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
177
+ * See the COPYING file in the top-level directory.
178
+ */
179
+#ifndef TEST_IOTHREAD_H
180
+#define TEST_IOTHREAD_H
181
+
182
+#include "block/aio.h"
183
+#include "qemu/thread.h"
184
+
185
+typedef struct IOThread IOThread;
186
+
187
+IOThread *iothread_new(void);
188
+void iothread_join(IOThread *iothread);
189
+AioContext *iothread_get_aio_context(IOThread *iothread);
190
+
191
+#endif
192
diff --git a/tests/iothread.c b/tests/iothread.c
193
new file mode 100644
194
index XXXXXXX..XXXXXXX
195
--- /dev/null
196
+++ b/tests/iothread.c
197
@@ -XXX,XX +XXX,XX @@
198
+/*
199
+ * Event loop thread implementation for unit tests
200
+ *
201
+ * Copyright Red Hat Inc., 2013, 2016
202
+ *
203
+ * Authors:
204
+ * Stefan Hajnoczi <stefanha@redhat.com>
205
+ * Paolo Bonzini <pbonzini@redhat.com>
206
+ *
207
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
208
+ * See the COPYING file in the top-level directory.
209
+ *
210
+ */
211
+
212
+#include "qemu/osdep.h"
213
+#include "qapi/error.h"
214
+#include "block/aio.h"
215
+#include "qemu/main-loop.h"
216
+#include "qemu/rcu.h"
217
+#include "iothread.h"
218
+
219
+struct IOThread {
220
+ AioContext *ctx;
221
+
222
+ QemuThread thread;
223
+ QemuMutex init_done_lock;
224
+ QemuCond init_done_cond; /* is thread initialization done? */
225
+ bool stopping;
226
+};
227
+
228
+static __thread IOThread *my_iothread;
229
+
230
+AioContext *qemu_get_current_aio_context(void)
231
+{
232
+ return my_iothread ? my_iothread->ctx : qemu_get_aio_context();
233
+}
234
+
235
+static void *iothread_run(void *opaque)
236
+{
237
+ IOThread *iothread = opaque;
238
+
239
+ rcu_register_thread();
240
+
241
+ my_iothread = iothread;
242
+ qemu_mutex_lock(&iothread->init_done_lock);
243
+ iothread->ctx = aio_context_new(&error_abort);
244
+ qemu_cond_signal(&iothread->init_done_cond);
245
+ qemu_mutex_unlock(&iothread->init_done_lock);
246
+
247
+ while (!atomic_read(&iothread->stopping)) {
248
+ aio_poll(iothread->ctx, true);
249
+ }
250
+
251
+ rcu_unregister_thread();
252
+ return NULL;
253
+}
254
+
255
+void iothread_join(IOThread *iothread)
256
+{
257
+ iothread->stopping = true;
258
+ aio_notify(iothread->ctx);
259
+ qemu_thread_join(&iothread->thread);
260
+ qemu_cond_destroy(&iothread->init_done_cond);
261
+ qemu_mutex_destroy(&iothread->init_done_lock);
262
+ aio_context_unref(iothread->ctx);
263
+ g_free(iothread);
264
+}
265
+
266
+IOThread *iothread_new(void)
267
+{
268
+ IOThread *iothread = g_new0(IOThread, 1);
269
+
270
+ qemu_mutex_init(&iothread->init_done_lock);
271
+ qemu_cond_init(&iothread->init_done_cond);
272
+ qemu_thread_create(&iothread->thread, NULL, iothread_run,
273
+ iothread, QEMU_THREAD_JOINABLE);
274
+
275
+ /* Wait for initialization to complete */
276
+ qemu_mutex_lock(&iothread->init_done_lock);
277
+ while (iothread->ctx == NULL) {
278
+ qemu_cond_wait(&iothread->init_done_cond,
279
+ &iothread->init_done_lock);
280
+ }
281
+ qemu_mutex_unlock(&iothread->init_done_lock);
282
+ return iothread;
283
+}
284
+
285
+AioContext *iothread_get_aio_context(IOThread *iothread)
286
+{
287
+ return iothread->ctx;
288
+}
289
diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c
290
new file mode 100644
291
index XXXXXXX..XXXXXXX
292
--- /dev/null
293
+++ b/tests/test-aio-multithread.c
294
@@ -XXX,XX +XXX,XX @@
295
+/*
296
+ * AioContext multithreading tests
297
+ *
298
+ * Copyright Red Hat, Inc. 2016
299
+ *
300
+ * Authors:
301
+ * Paolo Bonzini <pbonzini@redhat.com>
302
+ *
303
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
304
+ * See the COPYING.LIB file in the top-level directory.
305
+ */
306
+
307
+#include "qemu/osdep.h"
308
+#include <glib.h>
309
+#include "block/aio.h"
310
+#include "qapi/error.h"
311
+#include "qemu/coroutine.h"
312
+#include "qemu/thread.h"
313
+#include "qemu/error-report.h"
314
+#include "iothread.h"
315
+
316
+/* AioContext management */
317
+
318
+#define NUM_CONTEXTS 5
319
+
320
+static IOThread *threads[NUM_CONTEXTS];
321
+static AioContext *ctx[NUM_CONTEXTS];
322
+static __thread int id = -1;
323
+
324
+static QemuEvent done_event;
325
+
326
+/* Run a function synchronously on a remote iothread. */
327
+
328
+typedef struct CtxRunData {
329
+ QEMUBHFunc *cb;
330
+ void *arg;
331
+} CtxRunData;
332
+
333
+static void ctx_run_bh_cb(void *opaque)
334
+{
335
+ CtxRunData *data = opaque;
336
+
337
+ data->cb(data->arg);
338
+ qemu_event_set(&done_event);
339
+}
340
+
341
+static void ctx_run(int i, QEMUBHFunc *cb, void *opaque)
342
+{
343
+ CtxRunData data = {
344
+ .cb = cb,
345
+ .arg = opaque
346
+ };
347
+
348
+ qemu_event_reset(&done_event);
349
+ aio_bh_schedule_oneshot(ctx[i], ctx_run_bh_cb, &data);
350
+ qemu_event_wait(&done_event);
351
+}
352
+
353
+/* Starting the iothreads. */
354
+
355
+static void set_id_cb(void *opaque)
356
+{
357
+ int *i = opaque;
358
+
359
+ id = *i;
360
+}
361
+
362
+static void create_aio_contexts(void)
363
+{
364
+ int i;
365
+
366
+ for (i = 0; i < NUM_CONTEXTS; i++) {
367
+ threads[i] = iothread_new();
368
+ ctx[i] = iothread_get_aio_context(threads[i]);
369
+ }
370
+
371
+ qemu_event_init(&done_event, false);
372
+ for (i = 0; i < NUM_CONTEXTS; i++) {
373
+ ctx_run(i, set_id_cb, &i);
374
+ }
375
+}
376
+
377
+/* Stopping the iothreads. */
378
+
379
+static void join_aio_contexts(void)
380
+{
381
+ int i;
382
+
383
+ for (i = 0; i < NUM_CONTEXTS; i++) {
384
+ aio_context_ref(ctx[i]);
385
+ }
386
+ for (i = 0; i < NUM_CONTEXTS; i++) {
387
+ iothread_join(threads[i]);
388
+ }
389
+ for (i = 0; i < NUM_CONTEXTS; i++) {
390
+ aio_context_unref(ctx[i]);
391
+ }
392
+ qemu_event_destroy(&done_event);
393
+}
394
+
395
+/* Basic test for the stuff above. */
396
+
397
+static void test_lifecycle(void)
398
+{
399
+ create_aio_contexts();
400
+ join_aio_contexts();
401
+}
402
+
403
+/* aio_co_schedule test. */
404
+
405
+static Coroutine *to_schedule[NUM_CONTEXTS];
406
+
407
+static bool now_stopping;
408
+
409
+static int count_retry;
410
+static int count_here;
411
+static int count_other;
412
+
413
+static bool schedule_next(int n)
414
+{
415
+ Coroutine *co;
416
+
417
+ co = atomic_xchg(&to_schedule[n], NULL);
418
+ if (!co) {
419
+ atomic_inc(&count_retry);
420
+ return false;
421
+ }
422
+
423
+ if (n == id) {
424
+ atomic_inc(&count_here);
425
+ } else {
426
+ atomic_inc(&count_other);
427
+ }
428
+
429
+ aio_co_schedule(ctx[n], co);
430
+ return true;
431
+}
432
+
433
+static void finish_cb(void *opaque)
434
+{
435
+ schedule_next(id);
436
+}
437
+
438
+static coroutine_fn void test_multi_co_schedule_entry(void *opaque)
439
+{
440
+ g_assert(to_schedule[id] == NULL);
441
+ atomic_mb_set(&to_schedule[id], qemu_coroutine_self());
442
+
443
+ while (!atomic_mb_read(&now_stopping)) {
444
+ int n;
445
+
446
+ n = g_test_rand_int_range(0, NUM_CONTEXTS);
447
+ schedule_next(n);
448
+ qemu_coroutine_yield();
449
+
450
+ g_assert(to_schedule[id] == NULL);
451
+ atomic_mb_set(&to_schedule[id], qemu_coroutine_self());
452
+ }
453
+}
454
+
455
+
456
+static void test_multi_co_schedule(int seconds)
457
+{
458
+ int i;
459
+
460
+ count_here = count_other = count_retry = 0;
461
+ now_stopping = false;
462
+
463
+ create_aio_contexts();
464
+ for (i = 0; i < NUM_CONTEXTS; i++) {
465
+ Coroutine *co1 = qemu_coroutine_create(test_multi_co_schedule_entry, NULL);
466
+ aio_co_schedule(ctx[i], co1);
467
+ }
468
+
469
+ g_usleep(seconds * 1000000);
470
+
471
+ atomic_mb_set(&now_stopping, true);
472
+ for (i = 0; i < NUM_CONTEXTS; i++) {
473
+ ctx_run(i, finish_cb, NULL);
474
+ to_schedule[i] = NULL;
475
+ }
476
+
477
+ join_aio_contexts();
478
+ g_test_message("scheduled %d, queued %d, retry %d, total %d\n",
479
+ count_other, count_here, count_retry,
480
+ count_here + count_other + count_retry);
481
+}
482
+
483
+static void test_multi_co_schedule_1(void)
484
+{
485
+ test_multi_co_schedule(1);
486
+}
487
+
488
+static void test_multi_co_schedule_10(void)
489
+{
490
+ test_multi_co_schedule(10);
491
+}
492
+
493
+/* End of tests. */
494
+
495
+int main(int argc, char **argv)
496
+{
497
+ init_clocks();
498
+
499
+ g_test_init(&argc, &argv, NULL);
500
+ g_test_add_func("/aio/multi/lifecycle", test_lifecycle);
501
+ if (g_test_quick()) {
502
+ g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_1);
503
+ } else {
504
+ g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_10);
505
+ }
506
+ return g_test_run();
507
+}
508
diff --git a/util/async.c b/util/async.c
509
index XXXXXXX..XXXXXXX 100644
510
--- a/util/async.c
511
+++ b/util/async.c
512
@@ -XXX,XX +XXX,XX @@
513
#include "qemu/main-loop.h"
514
#include "qemu/atomic.h"
515
#include "block/raw-aio.h"
516
+#include "qemu/coroutine_int.h"
517
+#include "trace.h"
518
519
/***********************************************************/
520
/* bottom halves (can be seen as timers which expire ASAP) */
521
@@ -XXX,XX +XXX,XX @@ aio_ctx_finalize(GSource *source)
522
}
523
#endif
524
525
+ assert(QSLIST_EMPTY(&ctx->scheduled_coroutines));
526
+ qemu_bh_delete(ctx->co_schedule_bh);
527
+
528
qemu_lockcnt_lock(&ctx->list_lock);
529
assert(!qemu_lockcnt_count(&ctx->list_lock));
530
while (ctx->first_bh) {
531
@@ -XXX,XX +XXX,XX @@ static bool event_notifier_poll(void *opaque)
532
return atomic_read(&ctx->notified);
66
}
533
}
67
534
68
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
535
+static void co_schedule_bh_cb(void *opaque)
69
-int coroutine_fn
536
+{
70
+static int coroutine_fn
537
+ AioContext *ctx = opaque;
71
blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
538
+ QSLIST_HEAD(, Coroutine) straight, reversed;
539
+
540
+ QSLIST_MOVE_ATOMIC(&reversed, &ctx->scheduled_coroutines);
541
+ QSLIST_INIT(&straight);
542
+
543
+ while (!QSLIST_EMPTY(&reversed)) {
544
+ Coroutine *co = QSLIST_FIRST(&reversed);
545
+ QSLIST_REMOVE_HEAD(&reversed, co_scheduled_next);
546
+ QSLIST_INSERT_HEAD(&straight, co, co_scheduled_next);
547
+ }
548
+
549
+ while (!QSLIST_EMPTY(&straight)) {
550
+ Coroutine *co = QSLIST_FIRST(&straight);
551
+ QSLIST_REMOVE_HEAD(&straight, co_scheduled_next);
552
+ trace_aio_co_schedule_bh_cb(ctx, co);
553
+ qemu_coroutine_enter(co);
554
+ }
555
+}
556
+
557
AioContext *aio_context_new(Error **errp)
72
{
558
{
73
int ret;
559
int ret;
74
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
560
@@ -XXX,XX +XXX,XX @@ AioContext *aio_context_new(Error **errp)
561
}
562
g_source_set_can_recurse(&ctx->source, true);
563
qemu_lockcnt_init(&ctx->list_lock);
564
+
565
+ ctx->co_schedule_bh = aio_bh_new(ctx, co_schedule_bh_cb, ctx);
566
+ QSLIST_INIT(&ctx->scheduled_coroutines);
567
+
568
aio_set_event_notifier(ctx, &ctx->notifier,
569
false,
570
(EventNotifierHandler *)
571
@@ -XXX,XX +XXX,XX @@ fail:
572
return NULL;
75
}
573
}
76
574
77
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
575
+void aio_co_schedule(AioContext *ctx, Coroutine *co)
78
-int coroutine_fn blk_co_do_flush(BlockBackend *blk)
576
+{
79
+static int coroutine_fn blk_co_do_flush(BlockBackend *blk)
577
+ trace_aio_co_schedule(ctx, co);
578
+ QSLIST_INSERT_HEAD_ATOMIC(&ctx->scheduled_coroutines,
579
+ co, co_scheduled_next);
580
+ qemu_bh_schedule(ctx->co_schedule_bh);
581
+}
582
+
583
+void aio_co_wake(struct Coroutine *co)
584
+{
585
+ AioContext *ctx;
586
+
587
+ /* Read coroutine before co->ctx. Matches smp_wmb in
588
+ * qemu_coroutine_enter.
589
+ */
590
+ smp_read_barrier_depends();
591
+ ctx = atomic_read(&co->ctx);
592
+
593
+ if (ctx != qemu_get_current_aio_context()) {
594
+ aio_co_schedule(ctx, co);
595
+ return;
596
+ }
597
+
598
+ if (qemu_in_coroutine()) {
599
+ Coroutine *self = qemu_coroutine_self();
600
+ assert(self != co);
601
+ QSIMPLEQ_INSERT_TAIL(&self->co_queue_wakeup, co, co_queue_next);
602
+ } else {
603
+ aio_context_acquire(ctx);
604
+ qemu_coroutine_enter(co);
605
+ aio_context_release(ctx);
606
+ }
607
+}
608
+
609
void aio_context_ref(AioContext *ctx)
80
{
610
{
81
blk_wait_while_drained(blk);
611
g_source_ref(&ctx->source);
82
IO_CODE();
612
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
613
index XXXXXXX..XXXXXXX 100644
614
--- a/util/qemu-coroutine.c
615
+++ b/util/qemu-coroutine.c
616
@@ -XXX,XX +XXX,XX @@
617
#include "qemu/atomic.h"
618
#include "qemu/coroutine.h"
619
#include "qemu/coroutine_int.h"
620
+#include "block/aio.h"
621
622
enum {
623
POOL_BATCH_SIZE = 64,
624
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_enter(Coroutine *co)
625
}
626
627
co->caller = self;
628
+ co->ctx = qemu_get_current_aio_context();
629
+
630
+ /* Store co->ctx before anything that stores co. Matches
631
+ * barrier in aio_co_wake.
632
+ */
633
+ smp_wmb();
634
+
635
ret = qemu_coroutine_switch(self, co, COROUTINE_ENTER);
636
637
qemu_co_queue_run_restart(co);
638
diff --git a/util/trace-events b/util/trace-events
639
index XXXXXXX..XXXXXXX 100644
640
--- a/util/trace-events
641
+++ b/util/trace-events
642
@@ -XXX,XX +XXX,XX @@ run_poll_handlers_end(void *ctx, bool progress) "ctx %p progress %d"
643
poll_shrink(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
644
poll_grow(void *ctx, int64_t old, int64_t new) "ctx %p old %"PRId64" new %"PRId64
645
646
+# util/async.c
647
+aio_co_schedule(void *ctx, void *co) "ctx %p co %p"
648
+aio_co_schedule_bh_cb(void *ctx, void *co) "ctx %p co %p"
649
+
650
# util/thread-pool.c
651
thread_pool_submit(void *pool, void *req, void *opaque) "pool %p req %p opaque %p"
652
thread_pool_complete(void *pool, void *req, void *opaque, int ret) "pool %p req %p opaque %p ret %d"
83
--
653
--
84
2.35.3
654
2.9.3
655
656
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Keep generated_co_wrapper and coroutine_fn pairs together. This should
3
qcow2_create2 calls this. Do not run a nested event loop, as that
4
make it clear that each I/O function has these two versions.
4
breaks when aio_co_wake tries to queue the coroutine on the co_queue_wakeup
5
list of the currently running one.
5
6
6
Also move blk_co_{pread,pwrite}()'s implementations out of the header
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
file for consistency.
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Message-id: 20170213135235.12274-4-pbonzini@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
13
block/block-backend.c | 12 ++++++++----
14
1 file changed, 8 insertions(+), 4 deletions(-)
8
15
9
Signed-off-by: Alberto Faria <afaria@redhat.com>
10
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
11
Message-Id: <20220705161527.1054072-18-afaria@redhat.com>
12
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
14
---
15
include/sysemu/block-backend-io.h | 77 +++++++++++++------------------
16
block/block-backend.c | 22 +++++++++
17
2 files changed, 54 insertions(+), 45 deletions(-)
18
19
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/sysemu/block-backend-io.h
22
+++ b/include/sysemu/block-backend-io.h
23
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
24
int generated_co_wrapper blk_pread(BlockBackend *blk, int64_t offset,
25
int64_t bytes, void *buf,
26
BdrvRequestFlags flags);
27
-int generated_co_wrapper blk_pwrite(BlockBackend *blk, int64_t offset,
28
- int64_t bytes, const void *buf,
29
+int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset, int64_t bytes,
30
+ void *buf, BdrvRequestFlags flags);
31
+
32
+int generated_co_wrapper blk_preadv(BlockBackend *blk, int64_t offset,
33
+ int64_t bytes, QEMUIOVector *qiov,
34
BdrvRequestFlags flags);
35
+int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
36
+ int64_t bytes, QEMUIOVector *qiov,
37
+ BdrvRequestFlags flags);
38
+
39
int generated_co_wrapper blk_preadv_part(BlockBackend *blk, int64_t offset,
40
int64_t bytes, QEMUIOVector *qiov,
41
size_t qiov_offset,
42
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_preadv_part(BlockBackend *blk, int64_t offset,
43
int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
44
int64_t bytes, QEMUIOVector *qiov,
45
size_t qiov_offset, BdrvRequestFlags flags);
46
-int generated_co_wrapper blk_preadv(BlockBackend *blk, int64_t offset,
47
- int64_t bytes, QEMUIOVector *qiov,
48
+
49
+int generated_co_wrapper blk_pwrite(BlockBackend *blk, int64_t offset,
50
+ int64_t bytes, const void *buf,
51
BdrvRequestFlags flags);
52
-int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
53
- int64_t bytes, QEMUIOVector *qiov,
54
- BdrvRequestFlags flags);
55
+int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
56
+ const void *buf, BdrvRequestFlags flags);
57
+
58
+int generated_co_wrapper blk_pwritev(BlockBackend *blk, int64_t offset,
59
+ int64_t bytes, QEMUIOVector *qiov,
60
+ BdrvRequestFlags flags);
61
+int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
62
+ int64_t bytes, QEMUIOVector *qiov,
63
+ BdrvRequestFlags flags);
64
+
65
int generated_co_wrapper blk_pwritev_part(BlockBackend *blk, int64_t offset,
66
int64_t bytes, QEMUIOVector *qiov,
67
size_t qiov_offset,
68
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
69
int64_t bytes,
70
QEMUIOVector *qiov, size_t qiov_offset,
71
BdrvRequestFlags flags);
72
-int generated_co_wrapper blk_pwritev(BlockBackend *blk, int64_t offset,
73
- int64_t bytes, QEMUIOVector *qiov,
74
- BdrvRequestFlags flags);
75
-int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
76
- int64_t bytes, QEMUIOVector *qiov,
77
- BdrvRequestFlags flags);
78
-
79
-static inline int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset,
80
- int64_t bytes, void *buf,
81
- BdrvRequestFlags flags)
82
-{
83
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
84
- IO_OR_GS_CODE();
85
-
86
- assert(bytes <= SIZE_MAX);
87
-
88
- return blk_co_preadv(blk, offset, bytes, &qiov, flags);
89
-}
90
-
91
-static inline int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset,
92
- int64_t bytes, const void *buf,
93
- BdrvRequestFlags flags)
94
-{
95
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
96
- IO_OR_GS_CODE();
97
98
- assert(bytes <= SIZE_MAX);
99
+int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
100
+ int64_t offset, int64_t bytes,
101
+ const void *buf);
102
+int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
103
+ int64_t bytes, const void *buf);
104
105
- return blk_co_pwritev(blk, offset, bytes, &qiov, flags);
106
-}
107
+int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
108
+ int64_t bytes,
109
+ BdrvRequestFlags flags);
110
+int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
111
+ int64_t bytes, BdrvRequestFlags flags);
112
113
int generated_co_wrapper blk_pdiscard(BlockBackend *blk, int64_t offset,
114
int64_t bytes);
115
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_ioctl(BlockBackend *blk, unsigned long int req,
116
int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
117
void *buf);
118
119
-int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
120
- int64_t offset, int64_t bytes,
121
- const void *buf);
122
-int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
123
- int64_t bytes, const void *buf);
124
-int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
125
- int64_t bytes,
126
- BdrvRequestFlags flags);
127
-int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
128
- int64_t bytes, BdrvRequestFlags flags);
129
int generated_co_wrapper blk_truncate(BlockBackend *blk, int64_t offset,
130
bool exact, PreallocMode prealloc,
131
BdrvRequestFlags flags, Error **errp);
132
diff --git a/block/block-backend.c b/block/block-backend.c
16
diff --git a/block/block-backend.c b/block/block-backend.c
133
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
134
--- a/block/block-backend.c
18
--- a/block/block-backend.c
135
+++ b/block/block-backend.c
19
+++ b/block/block-backend.c
136
@@ -XXX,XX +XXX,XX @@ blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
20
@@ -XXX,XX +XXX,XX @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
137
return ret;
21
{
22
QEMUIOVector qiov;
23
struct iovec iov;
24
- Coroutine *co;
25
BlkRwCo rwco;
26
27
iov = (struct iovec) {
28
@@ -XXX,XX +XXX,XX @@ static int blk_prw(BlockBackend *blk, int64_t offset, uint8_t *buf,
29
.ret = NOT_DONE,
30
};
31
32
- co = qemu_coroutine_create(co_entry, &rwco);
33
- qemu_coroutine_enter(co);
34
- BDRV_POLL_WHILE(blk_bs(blk), rwco.ret == NOT_DONE);
35
+ if (qemu_in_coroutine()) {
36
+ /* Fast-path if already in coroutine context */
37
+ co_entry(&rwco);
38
+ } else {
39
+ Coroutine *co = qemu_coroutine_create(co_entry, &rwco);
40
+ qemu_coroutine_enter(co);
41
+ BDRV_POLL_WHILE(blk_bs(blk), rwco.ret == NOT_DONE);
42
+ }
43
44
return rwco.ret;
138
}
45
}
139
140
+int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset, int64_t bytes,
141
+ void *buf, BdrvRequestFlags flags)
142
+{
143
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
144
+ IO_OR_GS_CODE();
145
+
146
+ assert(bytes <= SIZE_MAX);
147
+
148
+ return blk_co_preadv(blk, offset, bytes, &qiov, flags);
149
+}
150
+
151
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
152
int64_t bytes, QEMUIOVector *qiov,
153
BdrvRequestFlags flags)
154
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
155
return ret;
156
}
157
158
+int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
159
+ const void *buf, BdrvRequestFlags flags)
160
+{
161
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
162
+ IO_OR_GS_CODE();
163
+
164
+ assert(bytes <= SIZE_MAX);
165
+
166
+ return blk_co_pwritev(blk, offset, bytes, &qiov, flags);
167
+}
168
+
169
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
170
int64_t bytes, QEMUIOVector *qiov,
171
BdrvRequestFlags flags)
172
--
46
--
173
2.35.3
47
2.9.3
48
49
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
For consistency with other I/O functions, and in preparation to
3
Once the thread pool starts using aio_co_wake, it will also need
4
implement them using generated_co_wrapper.
4
qemu_get_current_aio_context(). Make test-thread-pool create
5
an AioContext with qemu_init_main_loop, so that stubs/iothread.c
6
and tests/iothread.c can provide the rest.
5
7
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Message-Id: <20220705161527.1054072-5-afaria@redhat.com>
11
Message-id: 20170213135235.12274-5-pbonzini@redhat.com
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
11
---
13
---
12
include/sysemu/block-backend-io.h | 6 +++---
14
tests/test-thread-pool.c | 12 +++---------
13
block/block-backend.c | 6 +++---
15
1 file changed, 3 insertions(+), 9 deletions(-)
14
2 files changed, 6 insertions(+), 6 deletions(-)
15
16
16
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
17
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/block-backend-io.h
19
--- a/tests/test-thread-pool.c
19
+++ b/include/sysemu/block-backend-io.h
20
+++ b/tests/test-thread-pool.c
20
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
21
@@ -XXX,XX +XXX,XX @@
21
* the "I/O or GS" API.
22
#include "qapi/error.h"
22
*/
23
#include "qemu/timer.h"
23
24
#include "qemu/error-report.h"
24
-int blk_pread(BlockBackend *blk, int64_t offset, int bytes, void *buf,
25
+#include "qemu/main-loop.h"
25
+int blk_pread(BlockBackend *blk, int64_t offset, int64_t bytes, void *buf,
26
26
BdrvRequestFlags flags);
27
static AioContext *ctx;
27
-int blk_pwrite(BlockBackend *blk, int64_t offset, int bytes, const void *buf,
28
static ThreadPool *pool;
28
- BdrvRequestFlags flags);
29
@@ -XXX,XX +XXX,XX @@ static void test_cancel_async(void)
29
+int blk_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
30
int main(int argc, char **argv)
30
+ const void *buf, BdrvRequestFlags flags);
31
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
32
int64_t bytes, QEMUIOVector *qiov,
33
BdrvRequestFlags flags);
34
diff --git a/block/block-backend.c b/block/block-backend.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/block/block-backend.c
37
+++ b/block/block-backend.c
38
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
39
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
40
}
41
42
-int blk_pread(BlockBackend *blk, int64_t offset, int bytes, void *buf,
43
+int blk_pread(BlockBackend *blk, int64_t offset, int64_t bytes, void *buf,
44
BdrvRequestFlags flags)
45
{
31
{
46
int ret;
32
int ret;
47
@@ -XXX,XX +XXX,XX @@ int blk_pread(BlockBackend *blk, int64_t offset, int bytes, void *buf,
33
- Error *local_error = NULL;
34
35
- init_clocks();
36
-
37
- ctx = aio_context_new(&local_error);
38
- if (!ctx) {
39
- error_reportf_err(local_error, "Failed to create AIO Context: ");
40
- exit(1);
41
- }
42
+ qemu_init_main_loop(&error_abort);
43
+ ctx = qemu_get_current_aio_context();
44
pool = aio_get_thread_pool(ctx);
45
46
g_test_init(&argc, &argv, NULL);
47
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
48
49
ret = g_test_run();
50
51
- aio_context_unref(ctx);
48
return ret;
52
return ret;
49
}
53
}
50
51
-int blk_pwrite(BlockBackend *blk, int64_t offset, int bytes, const void *buf,
52
- BdrvRequestFlags flags)
53
+int blk_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
54
+ const void *buf, BdrvRequestFlags flags)
55
{
56
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
57
IO_OR_GS_CODE();
58
--
54
--
59
2.35.3
55
2.9.3
56
57
diff view generated by jsdifflib
1
e7874a50ff3f5b20fb46f36958ad ("python: update for mypy 0.950") has added
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
`warn_unused_ignores = False` to python/setup.cfg, to be able to keep
2
3
compatibility with both pre- and post-0.950 mypy versions.
3
This is in preparation for making qio_channel_yield work on
4
4
AioContexts other than the main one.
5
The iotests' mypy.ini needs the same, or 297 will fail (on both pre- and
5
6
post-0.950 mypy, as far as I can tell; just for different `ignore`
6
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7
lines).
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
10
Message-Id: <20220621092536.19837-1-hreitz@redhat.com>
10
Message-id: 20170213135235.12274-6-pbonzini@redhat.com
11
Acked-by: John Snow <jsnow@redhat.com>
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
12
---
13
tests/qemu-iotests/mypy.ini | 2 +-
13
include/io/channel.h | 25 +++++++++++++++++++++++++
14
1 file changed, 1 insertion(+), 1 deletion(-)
14
io/channel-command.c | 13 +++++++++++++
15
15
io/channel-file.c | 11 +++++++++++
16
diff --git a/tests/qemu-iotests/mypy.ini b/tests/qemu-iotests/mypy.ini
16
io/channel-socket.c | 16 +++++++++++-----
17
index XXXXXXX..XXXXXXX 100644
17
io/channel-tls.c | 12 ++++++++++++
18
--- a/tests/qemu-iotests/mypy.ini
18
io/channel-watch.c | 6 ++++++
19
+++ b/tests/qemu-iotests/mypy.ini
19
io/channel.c | 11 +++++++++++
20
@@ -XXX,XX +XXX,XX @@ no_implicit_optional = True
20
7 files changed, 89 insertions(+), 5 deletions(-)
21
scripts_are_modules = True
21
22
warn_redundant_casts = True
22
diff --git a/include/io/channel.h b/include/io/channel.h
23
warn_unused_configs = True
23
index XXXXXXX..XXXXXXX 100644
24
-warn_unused_ignores = True
24
--- a/include/io/channel.h
25
+warn_unused_ignores = False
25
+++ b/include/io/channel.h
26
@@ -XXX,XX +XXX,XX @@
27
28
#include "qemu-common.h"
29
#include "qom/object.h"
30
+#include "block/aio.h"
31
32
#define TYPE_QIO_CHANNEL "qio-channel"
33
#define QIO_CHANNEL(obj) \
34
@@ -XXX,XX +XXX,XX @@ struct QIOChannelClass {
35
off_t offset,
36
int whence,
37
Error **errp);
38
+ void (*io_set_aio_fd_handler)(QIOChannel *ioc,
39
+ AioContext *ctx,
40
+ IOHandler *io_read,
41
+ IOHandler *io_write,
42
+ void *opaque);
43
};
44
45
/* General I/O handling functions */
46
@@ -XXX,XX +XXX,XX @@ void qio_channel_yield(QIOChannel *ioc,
47
void qio_channel_wait(QIOChannel *ioc,
48
GIOCondition condition);
49
50
+/**
51
+ * qio_channel_set_aio_fd_handler:
52
+ * @ioc: the channel object
53
+ * @ctx: the AioContext to set the handlers on
54
+ * @io_read: the read handler
55
+ * @io_write: the write handler
56
+ * @opaque: the opaque value passed to the handler
57
+ *
58
+ * This is used internally by qio_channel_yield(). It can
59
+ * be used by channel implementations to forward the handlers
60
+ * to another channel (e.g. from #QIOChannelTLS to the
61
+ * underlying socket).
62
+ */
63
+void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
64
+ AioContext *ctx,
65
+ IOHandler *io_read,
66
+ IOHandler *io_write,
67
+ void *opaque);
68
+
69
#endif /* QIO_CHANNEL_H */
70
diff --git a/io/channel-command.c b/io/channel-command.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/io/channel-command.c
73
+++ b/io/channel-command.c
74
@@ -XXX,XX +XXX,XX @@ static int qio_channel_command_close(QIOChannel *ioc,
75
}
76
77
78
+static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc,
79
+ AioContext *ctx,
80
+ IOHandler *io_read,
81
+ IOHandler *io_write,
82
+ void *opaque)
83
+{
84
+ QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
85
+ aio_set_fd_handler(ctx, cioc->readfd, false, io_read, NULL, NULL, opaque);
86
+ aio_set_fd_handler(ctx, cioc->writefd, false, NULL, io_write, NULL, opaque);
87
+}
88
+
89
+
90
static GSource *qio_channel_command_create_watch(QIOChannel *ioc,
91
GIOCondition condition)
92
{
93
@@ -XXX,XX +XXX,XX @@ static void qio_channel_command_class_init(ObjectClass *klass,
94
ioc_klass->io_set_blocking = qio_channel_command_set_blocking;
95
ioc_klass->io_close = qio_channel_command_close;
96
ioc_klass->io_create_watch = qio_channel_command_create_watch;
97
+ ioc_klass->io_set_aio_fd_handler = qio_channel_command_set_aio_fd_handler;
98
}
99
100
static const TypeInfo qio_channel_command_info = {
101
diff --git a/io/channel-file.c b/io/channel-file.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/io/channel-file.c
104
+++ b/io/channel-file.c
105
@@ -XXX,XX +XXX,XX @@ static int qio_channel_file_close(QIOChannel *ioc,
106
}
107
108
109
+static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc,
110
+ AioContext *ctx,
111
+ IOHandler *io_read,
112
+ IOHandler *io_write,
113
+ void *opaque)
114
+{
115
+ QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc);
116
+ aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write, NULL, opaque);
117
+}
118
+
119
static GSource *qio_channel_file_create_watch(QIOChannel *ioc,
120
GIOCondition condition)
121
{
122
@@ -XXX,XX +XXX,XX @@ static void qio_channel_file_class_init(ObjectClass *klass,
123
ioc_klass->io_seek = qio_channel_file_seek;
124
ioc_klass->io_close = qio_channel_file_close;
125
ioc_klass->io_create_watch = qio_channel_file_create_watch;
126
+ ioc_klass->io_set_aio_fd_handler = qio_channel_file_set_aio_fd_handler;
127
}
128
129
static const TypeInfo qio_channel_file_info = {
130
diff --git a/io/channel-socket.c b/io/channel-socket.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/io/channel-socket.c
133
+++ b/io/channel-socket.c
134
@@ -XXX,XX +XXX,XX @@ qio_channel_socket_set_blocking(QIOChannel *ioc,
135
qemu_set_block(sioc->fd);
136
} else {
137
qemu_set_nonblock(sioc->fd);
138
-#ifdef WIN32
139
- WSAEventSelect(sioc->fd, ioc->event,
140
- FD_READ | FD_ACCEPT | FD_CLOSE |
141
- FD_CONNECT | FD_WRITE | FD_OOB);
142
-#endif
143
}
144
return 0;
145
}
146
@@ -XXX,XX +XXX,XX @@ qio_channel_socket_shutdown(QIOChannel *ioc,
147
return 0;
148
}
149
150
+static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc,
151
+ AioContext *ctx,
152
+ IOHandler *io_read,
153
+ IOHandler *io_write,
154
+ void *opaque)
155
+{
156
+ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
157
+ aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque);
158
+}
159
+
160
static GSource *qio_channel_socket_create_watch(QIOChannel *ioc,
161
GIOCondition condition)
162
{
163
@@ -XXX,XX +XXX,XX @@ static void qio_channel_socket_class_init(ObjectClass *klass,
164
ioc_klass->io_set_cork = qio_channel_socket_set_cork;
165
ioc_klass->io_set_delay = qio_channel_socket_set_delay;
166
ioc_klass->io_create_watch = qio_channel_socket_create_watch;
167
+ ioc_klass->io_set_aio_fd_handler = qio_channel_socket_set_aio_fd_handler;
168
}
169
170
static const TypeInfo qio_channel_socket_info = {
171
diff --git a/io/channel-tls.c b/io/channel-tls.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/io/channel-tls.c
174
+++ b/io/channel-tls.c
175
@@ -XXX,XX +XXX,XX @@ static int qio_channel_tls_close(QIOChannel *ioc,
176
return qio_channel_close(tioc->master, errp);
177
}
178
179
+static void qio_channel_tls_set_aio_fd_handler(QIOChannel *ioc,
180
+ AioContext *ctx,
181
+ IOHandler *io_read,
182
+ IOHandler *io_write,
183
+ void *opaque)
184
+{
185
+ QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
186
+
187
+ qio_channel_set_aio_fd_handler(tioc->master, ctx, io_read, io_write, opaque);
188
+}
189
+
190
static GSource *qio_channel_tls_create_watch(QIOChannel *ioc,
191
GIOCondition condition)
192
{
193
@@ -XXX,XX +XXX,XX @@ static void qio_channel_tls_class_init(ObjectClass *klass,
194
ioc_klass->io_close = qio_channel_tls_close;
195
ioc_klass->io_shutdown = qio_channel_tls_shutdown;
196
ioc_klass->io_create_watch = qio_channel_tls_create_watch;
197
+ ioc_klass->io_set_aio_fd_handler = qio_channel_tls_set_aio_fd_handler;
198
}
199
200
static const TypeInfo qio_channel_tls_info = {
201
diff --git a/io/channel-watch.c b/io/channel-watch.c
202
index XXXXXXX..XXXXXXX 100644
203
--- a/io/channel-watch.c
204
+++ b/io/channel-watch.c
205
@@ -XXX,XX +XXX,XX @@ GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
206
GSource *source;
207
QIOChannelSocketSource *ssource;
208
209
+#ifdef WIN32
210
+ WSAEventSelect(socket, ioc->event,
211
+ FD_READ | FD_ACCEPT | FD_CLOSE |
212
+ FD_CONNECT | FD_WRITE | FD_OOB);
213
+#endif
214
+
215
source = g_source_new(&qio_channel_socket_source_funcs,
216
sizeof(QIOChannelSocketSource));
217
ssource = (QIOChannelSocketSource *)source;
218
diff --git a/io/channel.c b/io/channel.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/io/channel.c
221
+++ b/io/channel.c
222
@@ -XXX,XX +XXX,XX @@ GSource *qio_channel_create_watch(QIOChannel *ioc,
223
}
224
225
226
+void qio_channel_set_aio_fd_handler(QIOChannel *ioc,
227
+ AioContext *ctx,
228
+ IOHandler *io_read,
229
+ IOHandler *io_write,
230
+ void *opaque)
231
+{
232
+ QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
233
+
234
+ klass->io_set_aio_fd_handler(ioc, ctx, io_read, io_write, opaque);
235
+}
236
+
237
guint qio_channel_add_watch(QIOChannel *ioc,
238
GIOCondition condition,
239
QIOChannelFunc func,
26
--
240
--
27
2.35.3
241
2.9.3
242
243
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
They currently return the value of their headerlen/buflen parameter on
3
Support separate coroutines for reading and writing, and place the
4
success. Returning 0 instead makes it clear that short reads/writes are
4
read/write handlers on the AioContext that the QIOChannel is registered
5
not possible.
5
with.
6
6
7
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
8
Reviewed-by: Eric Blake <eblake@redhat.com>
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
10
Message-Id: <20220609152744.3891847-5-afaria@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20170213135235.12274-7-pbonzini@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
13
---
13
---
14
include/crypto/block.h | 32 ++++++++++-----------
14
include/io/channel.h | 47 ++++++++++++++++++++++++++--
15
block/crypto.c | 52 +++++++++++++++++-----------------
15
io/channel.c | 86 +++++++++++++++++++++++++++++++++++++++-------------
16
block/qcow2.c | 22 +++++++-------
16
2 files changed, 109 insertions(+), 24 deletions(-)
17
crypto/block-luks.c | 8 +++---
17
18
crypto/block.c | 6 ++--
18
diff --git a/include/io/channel.h b/include/io/channel.h
19
tests/unit/test-crypto-block.c | 38 ++++++++++++-------------
20
6 files changed, 79 insertions(+), 79 deletions(-)
21
22
diff --git a/include/crypto/block.h b/include/crypto/block.h
23
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
24
--- a/include/crypto/block.h
20
--- a/include/io/channel.h
25
+++ b/include/crypto/block.h
21
+++ b/include/io/channel.h
26
@@ -XXX,XX +XXX,XX @@ typedef struct QCryptoBlock QCryptoBlock;
22
@@ -XXX,XX +XXX,XX @@
27
/* See also QCryptoBlockFormat, QCryptoBlockCreateOptions
23
28
* and QCryptoBlockOpenOptions in qapi/crypto.json */
24
#include "qemu-common.h"
29
25
#include "qom/object.h"
30
-typedef ssize_t (*QCryptoBlockReadFunc)(QCryptoBlock *block,
26
+#include "qemu/coroutine.h"
31
- size_t offset,
27
#include "block/aio.h"
32
- uint8_t *buf,
28
33
- size_t buflen,
29
#define TYPE_QIO_CHANNEL "qio-channel"
34
- void *opaque,
30
@@ -XXX,XX +XXX,XX @@ struct QIOChannel {
35
- Error **errp);
31
Object parent;
36
+typedef int (*QCryptoBlockReadFunc)(QCryptoBlock *block,
32
unsigned int features; /* bitmask of QIOChannelFeatures */
37
+ size_t offset,
33
char *name;
38
+ uint8_t *buf,
34
+ AioContext *ctx;
39
+ size_t buflen,
35
+ Coroutine *read_coroutine;
40
+ void *opaque,
36
+ Coroutine *write_coroutine;
41
+ Error **errp);
37
#ifdef _WIN32
42
38
HANDLE event; /* For use with GSource on Win32 */
43
-typedef ssize_t (*QCryptoBlockInitFunc)(QCryptoBlock *block,
39
#endif
44
- size_t headerlen,
40
@@ -XXX,XX +XXX,XX @@ guint qio_channel_add_watch(QIOChannel *ioc,
45
- void *opaque,
41
46
- Error **errp);
47
+typedef int (*QCryptoBlockInitFunc)(QCryptoBlock *block,
48
+ size_t headerlen,
49
+ void *opaque,
50
+ Error **errp);
51
52
-typedef ssize_t (*QCryptoBlockWriteFunc)(QCryptoBlock *block,
53
- size_t offset,
54
- const uint8_t *buf,
55
- size_t buflen,
56
- void *opaque,
57
- Error **errp);
58
+typedef int (*QCryptoBlockWriteFunc)(QCryptoBlock *block,
59
+ size_t offset,
60
+ const uint8_t *buf,
61
+ size_t buflen,
62
+ void *opaque,
63
+ Error **errp);
64
42
65
/**
43
/**
66
* qcrypto_block_has_format:
44
+ * qio_channel_attach_aio_context:
67
diff --git a/block/crypto.c b/block/crypto.c
45
+ * @ioc: the channel object
46
+ * @ctx: the #AioContext to set the handlers on
47
+ *
48
+ * Request that qio_channel_yield() sets I/O handlers on
49
+ * the given #AioContext. If @ctx is %NULL, qio_channel_yield()
50
+ * uses QEMU's main thread event loop.
51
+ *
52
+ * You can move a #QIOChannel from one #AioContext to another even if
53
+ * I/O handlers are set for a coroutine. However, #QIOChannel provides
54
+ * no synchronization between the calls to qio_channel_yield() and
55
+ * qio_channel_attach_aio_context().
56
+ *
57
+ * Therefore you should first call qio_channel_detach_aio_context()
58
+ * to ensure that the coroutine is not entered concurrently. Then,
59
+ * while the coroutine has yielded, call qio_channel_attach_aio_context(),
60
+ * and then aio_co_schedule() to place the coroutine on the new
61
+ * #AioContext. The calls to qio_channel_detach_aio_context()
62
+ * and qio_channel_attach_aio_context() should be protected with
63
+ * aio_context_acquire() and aio_context_release().
64
+ */
65
+void qio_channel_attach_aio_context(QIOChannel *ioc,
66
+ AioContext *ctx);
67
+
68
+/**
69
+ * qio_channel_detach_aio_context:
70
+ * @ioc: the channel object
71
+ *
72
+ * Disable any I/O handlers set by qio_channel_yield(). With the
73
+ * help of aio_co_schedule(), this allows moving a coroutine that was
74
+ * paused by qio_channel_yield() to another context.
75
+ */
76
+void qio_channel_detach_aio_context(QIOChannel *ioc);
77
+
78
+/**
79
* qio_channel_yield:
80
* @ioc: the channel object
81
* @condition: the I/O condition to wait for
82
*
83
- * Yields execution from the current coroutine until
84
- * the condition indicated by @condition becomes
85
- * available.
86
+ * Yields execution from the current coroutine until the condition
87
+ * indicated by @condition becomes available. @condition must
88
+ * be either %G_IO_IN or %G_IO_OUT; it cannot contain both. In
89
+ * addition, no two coroutine can be waiting on the same condition
90
+ * and channel at the same time.
91
*
92
* This must only be called from coroutine context
93
*/
94
diff --git a/io/channel.c b/io/channel.c
68
index XXXXXXX..XXXXXXX 100644
95
index XXXXXXX..XXXXXXX 100644
69
--- a/block/crypto.c
96
--- a/io/channel.c
70
+++ b/block/crypto.c
97
+++ b/io/channel.c
71
@@ -XXX,XX +XXX,XX @@ static int block_crypto_probe_generic(QCryptoBlockFormat format,
98
@@ -XXX,XX +XXX,XX @@
99
#include "qemu/osdep.h"
100
#include "io/channel.h"
101
#include "qapi/error.h"
102
-#include "qemu/coroutine.h"
103
+#include "qemu/main-loop.h"
104
105
bool qio_channel_has_feature(QIOChannel *ioc,
106
QIOChannelFeature feature)
107
@@ -XXX,XX +XXX,XX @@ off_t qio_channel_io_seek(QIOChannel *ioc,
72
}
108
}
73
109
74
110
75
-static ssize_t block_crypto_read_func(QCryptoBlock *block,
111
-typedef struct QIOChannelYieldData QIOChannelYieldData;
76
- size_t offset,
112
-struct QIOChannelYieldData {
77
- uint8_t *buf,
113
- QIOChannel *ioc;
78
- size_t buflen,
114
- Coroutine *co;
79
- void *opaque,
115
-};
80
- Error **errp)
116
+static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc);
81
+static int block_crypto_read_func(QCryptoBlock *block,
117
82
+ size_t offset,
118
+static void qio_channel_restart_read(void *opaque)
83
+ uint8_t *buf,
119
+{
84
+ size_t buflen,
120
+ QIOChannel *ioc = opaque;
85
+ void *opaque,
121
+ Coroutine *co = ioc->read_coroutine;
86
+ Error **errp)
122
+
123
+ ioc->read_coroutine = NULL;
124
+ qio_channel_set_aio_fd_handlers(ioc);
125
+ aio_co_wake(co);
126
+}
127
128
-static gboolean qio_channel_yield_enter(QIOChannel *ioc,
129
- GIOCondition condition,
130
- gpointer opaque)
131
+static void qio_channel_restart_write(void *opaque)
87
{
132
{
88
BlockDriverState *bs = opaque;
133
- QIOChannelYieldData *data = opaque;
89
ssize_t ret;
134
- qemu_coroutine_enter(data->co);
90
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
135
- return FALSE;
91
error_setg_errno(errp, -ret, "Could not read encryption header");
136
+ QIOChannel *ioc = opaque;
92
return ret;
137
+ Coroutine *co = ioc->write_coroutine;
93
}
138
+
94
- return buflen;
139
+ ioc->write_coroutine = NULL;
95
+ return 0;
140
+ qio_channel_set_aio_fd_handlers(ioc);
141
+ aio_co_wake(co);
96
}
142
}
97
143
98
-static ssize_t block_crypto_write_func(QCryptoBlock *block,
144
+static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
99
- size_t offset,
145
+{
100
- const uint8_t *buf,
146
+ IOHandler *rd_handler = NULL, *wr_handler = NULL;
101
- size_t buflen,
147
+ AioContext *ctx;
102
- void *opaque,
148
+
103
- Error **errp)
149
+ if (ioc->read_coroutine) {
104
+static int block_crypto_write_func(QCryptoBlock *block,
150
+ rd_handler = qio_channel_restart_read;
105
+ size_t offset,
151
+ }
106
+ const uint8_t *buf,
152
+ if (ioc->write_coroutine) {
107
+ size_t buflen,
153
+ wr_handler = qio_channel_restart_write;
108
+ void *opaque,
154
+ }
109
+ Error **errp)
155
+
156
+ ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
157
+ qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
158
+}
159
+
160
+void qio_channel_attach_aio_context(QIOChannel *ioc,
161
+ AioContext *ctx)
162
+{
163
+ AioContext *old_ctx;
164
+ if (ioc->ctx == ctx) {
165
+ return;
166
+ }
167
+
168
+ old_ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
169
+ qio_channel_set_aio_fd_handler(ioc, old_ctx, NULL, NULL, NULL);
170
+ ioc->ctx = ctx;
171
+ qio_channel_set_aio_fd_handlers(ioc);
172
+}
173
+
174
+void qio_channel_detach_aio_context(QIOChannel *ioc)
175
+{
176
+ ioc->read_coroutine = NULL;
177
+ ioc->write_coroutine = NULL;
178
+ qio_channel_set_aio_fd_handlers(ioc);
179
+ ioc->ctx = NULL;
180
+}
181
182
void coroutine_fn qio_channel_yield(QIOChannel *ioc,
183
GIOCondition condition)
110
{
184
{
111
BlockDriverState *bs = opaque;
185
- QIOChannelYieldData data;
112
ssize_t ret;
186
-
113
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
187
assert(qemu_in_coroutine());
114
error_setg_errno(errp, -ret, "Could not write encryption header");
188
- data.ioc = ioc;
115
return ret;
189
- data.co = qemu_coroutine_self();
116
}
190
- qio_channel_add_watch(ioc,
117
- return buflen;
191
- condition,
118
+ return 0;
192
- qio_channel_yield_enter,
193
- &data,
194
- NULL);
195
+ if (condition == G_IO_IN) {
196
+ assert(!ioc->read_coroutine);
197
+ ioc->read_coroutine = qemu_coroutine_self();
198
+ } else if (condition == G_IO_OUT) {
199
+ assert(!ioc->write_coroutine);
200
+ ioc->write_coroutine = qemu_coroutine_self();
201
+ } else {
202
+ abort();
203
+ }
204
+ qio_channel_set_aio_fd_handlers(ioc);
205
qemu_coroutine_yield();
119
}
206
}
120
207
121
122
@@ -XXX,XX +XXX,XX @@ struct BlockCryptoCreateData {
123
};
124
125
126
-static ssize_t block_crypto_create_write_func(QCryptoBlock *block,
127
- size_t offset,
128
- const uint8_t *buf,
129
- size_t buflen,
130
- void *opaque,
131
- Error **errp)
132
+static int block_crypto_create_write_func(QCryptoBlock *block,
133
+ size_t offset,
134
+ const uint8_t *buf,
135
+ size_t buflen,
136
+ void *opaque,
137
+ Error **errp)
138
{
139
struct BlockCryptoCreateData *data = opaque;
140
ssize_t ret;
141
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_create_write_func(QCryptoBlock *block,
142
error_setg_errno(errp, -ret, "Could not write encryption header");
143
return ret;
144
}
145
- return ret;
146
+ return 0;
147
}
148
149
-static ssize_t block_crypto_create_init_func(QCryptoBlock *block,
150
- size_t headerlen,
151
- void *opaque,
152
- Error **errp)
153
+static int block_crypto_create_init_func(QCryptoBlock *block,
154
+ size_t headerlen,
155
+ void *opaque,
156
+ Error **errp)
157
{
158
struct BlockCryptoCreateData *data = opaque;
159
Error *local_error = NULL;
160
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_create_init_func(QCryptoBlock *block,
161
data->prealloc, 0, &local_error);
162
163
if (ret >= 0) {
164
- return ret;
165
+ return 0;
166
}
167
168
error:
169
diff --git a/block/qcow2.c b/block/qcow2.c
170
index XXXXXXX..XXXXXXX 100644
171
--- a/block/qcow2.c
172
+++ b/block/qcow2.c
173
@@ -XXX,XX +XXX,XX @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
174
}
175
176
177
-static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
178
- uint8_t *buf, size_t buflen,
179
- void *opaque, Error **errp)
180
+static int qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
181
+ uint8_t *buf, size_t buflen,
182
+ void *opaque, Error **errp)
183
{
184
BlockDriverState *bs = opaque;
185
BDRVQcow2State *s = bs->opaque;
186
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
187
error_setg_errno(errp, -ret, "Could not read encryption header");
188
return -1;
189
}
190
- return buflen;
191
+ return 0;
192
}
193
194
195
-static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
196
- void *opaque, Error **errp)
197
+static int qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
198
+ void *opaque, Error **errp)
199
{
200
BlockDriverState *bs = opaque;
201
BDRVQcow2State *s = bs->opaque;
202
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t headerlen,
203
return -1;
204
}
205
206
- return ret;
207
+ return 0;
208
}
209
210
211
-static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
212
- const uint8_t *buf, size_t buflen,
213
- void *opaque, Error **errp)
214
+static int qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
215
+ const uint8_t *buf, size_t buflen,
216
+ void *opaque, Error **errp)
217
{
218
BlockDriverState *bs = opaque;
219
BDRVQcow2State *s = bs->opaque;
220
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
221
error_setg_errno(errp, -ret, "Could not read encryption header");
222
return -1;
223
}
224
- return buflen;
225
+ return 0;
226
}
227
228
static QDict*
229
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/crypto/block-luks.c
232
+++ b/crypto/block-luks.c
233
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_load_header(QCryptoBlock *block,
234
void *opaque,
235
Error **errp)
236
{
237
- ssize_t rv;
238
+ int rv;
239
size_t i;
240
QCryptoBlockLUKS *luks = block->opaque;
241
242
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
243
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE,
244
splitkey, splitkeylen,
245
opaque,
246
- errp) != splitkeylen) {
247
+ errp) < 0) {
248
goto cleanup;
249
}
250
251
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_load_key(QCryptoBlock *block,
252
g_autofree uint8_t *splitkey = NULL;
253
size_t splitkeylen;
254
g_autofree uint8_t *possiblekey = NULL;
255
- ssize_t rv;
256
+ int rv;
257
g_autoptr(QCryptoCipher) cipher = NULL;
258
uint8_t keydigest[QCRYPTO_BLOCK_LUKS_DIGEST_LEN];
259
g_autoptr(QCryptoIVGen) ivgen = NULL;
260
@@ -XXX,XX +XXX,XX @@ qcrypto_block_luks_erase_key(QCryptoBlock *block,
261
garbagesplitkey,
262
splitkeylen,
263
opaque,
264
- &local_err) != splitkeylen) {
265
+ &local_err) < 0) {
266
error_propagate(errp, local_err);
267
return -1;
268
}
269
diff --git a/crypto/block.c b/crypto/block.c
270
index XXXXXXX..XXXXXXX 100644
271
--- a/crypto/block.c
272
+++ b/crypto/block.c
273
@@ -XXX,XX +XXX,XX @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
274
}
275
276
277
-static ssize_t qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
278
+static int qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
279
size_t headerlen, void *opaque, Error **errp)
280
{
281
size_t *headerlenp = opaque;
282
@@ -XXX,XX +XXX,XX @@ static ssize_t qcrypto_block_headerlen_hdr_init_func(QCryptoBlock *block,
283
}
284
285
286
-static ssize_t qcrypto_block_headerlen_hdr_write_func(QCryptoBlock *block,
287
+static int qcrypto_block_headerlen_hdr_write_func(QCryptoBlock *block,
288
size_t offset, const uint8_t *buf, size_t buflen,
289
void *opaque, Error **errp)
290
{
291
/* Discard the bytes, we're not actually writing to an image */
292
- return buflen;
293
+ return 0;
294
}
295
296
297
diff --git a/tests/unit/test-crypto-block.c b/tests/unit/test-crypto-block.c
298
index XXXXXXX..XXXXXXX 100644
299
--- a/tests/unit/test-crypto-block.c
300
+++ b/tests/unit/test-crypto-block.c
301
@@ -XXX,XX +XXX,XX @@ static struct QCryptoBlockTestData {
302
};
303
304
305
-static ssize_t test_block_read_func(QCryptoBlock *block,
306
- size_t offset,
307
- uint8_t *buf,
308
- size_t buflen,
309
- void *opaque,
310
- Error **errp)
311
+static int test_block_read_func(QCryptoBlock *block,
312
+ size_t offset,
313
+ uint8_t *buf,
314
+ size_t buflen,
315
+ void *opaque,
316
+ Error **errp)
317
{
318
Buffer *header = opaque;
319
320
@@ -XXX,XX +XXX,XX @@ static ssize_t test_block_read_func(QCryptoBlock *block,
321
322
memcpy(buf, header->buffer + offset, buflen);
323
324
- return buflen;
325
+ return 0;
326
}
327
328
329
-static ssize_t test_block_init_func(QCryptoBlock *block,
330
- size_t headerlen,
331
- void *opaque,
332
- Error **errp)
333
+static int test_block_init_func(QCryptoBlock *block,
334
+ size_t headerlen,
335
+ void *opaque,
336
+ Error **errp)
337
{
338
Buffer *header = opaque;
339
340
@@ -XXX,XX +XXX,XX @@ static ssize_t test_block_init_func(QCryptoBlock *block,
341
342
buffer_reserve(header, headerlen);
343
344
- return headerlen;
345
+ return 0;
346
}
347
348
349
-static ssize_t test_block_write_func(QCryptoBlock *block,
350
- size_t offset,
351
- const uint8_t *buf,
352
- size_t buflen,
353
- void *opaque,
354
- Error **errp)
355
+static int test_block_write_func(QCryptoBlock *block,
356
+ size_t offset,
357
+ const uint8_t *buf,
358
+ size_t buflen,
359
+ void *opaque,
360
+ Error **errp)
361
{
362
Buffer *header = opaque;
363
364
@@ -XXX,XX +XXX,XX @@ static ssize_t test_block_write_func(QCryptoBlock *block,
365
memcpy(header->buffer + offset, buf, buflen);
366
header->offset = offset + buflen;
367
368
- return buflen;
369
+ return 0;
370
}
371
372
373
--
208
--
374
2.35.3
209
2.9.3
210
211
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
For consistency with other I/O functions, and in preparation to
3
In the client, read the reply headers from a coroutine, switching the
4
implement it using generated_co_wrapper.
4
read side between the "read header" coroutine and the I/O coroutine that
5
reads the body of the reply.
5
6
6
Callers were updated using this Coccinelle script:
7
In the server, if the server can read more requests it will create a new
8
"read request" coroutine as soon as a request has been read. Otherwise,
9
the new coroutine is created in nbd_request_put.
7
10
8
@@ expression blk, offset, buf, bytes; @@
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
- blk_pread(blk, offset, buf, bytes)
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
10
+ blk_pread(blk, offset, buf, bytes, 0)
13
Reviewed-by: Fam Zheng <famz@redhat.com>
14
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
15
Message-id: 20170213135235.12274-8-pbonzini@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
block/nbd-client.h | 2 +-
19
block/nbd-client.c | 117 ++++++++++++++++++++++++-----------------------------
20
nbd/client.c | 2 +-
21
nbd/common.c | 9 +----
22
nbd/server.c | 94 +++++++++++++-----------------------------
23
5 files changed, 83 insertions(+), 141 deletions(-)
11
24
12
It had no effect on hw/block/nand.c, presumably due to the #if, so that
25
diff --git a/block/nbd-client.h b/block/nbd-client.h
13
file was updated manually.
14
15
Overly-long lines were then fixed by hand.
16
17
Signed-off-by: Alberto Faria <afaria@redhat.com>
18
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
19
Reviewed-by: Greg Kurz <groug@kaod.org>
20
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
21
Message-Id: <20220705161527.1054072-3-afaria@redhat.com>
22
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
23
---
24
include/sysemu/block-backend-io.h | 3 ++-
25
block.c | 2 +-
26
block/block-backend.c | 5 +++--
27
block/commit.c | 2 +-
28
block/export/fuse.c | 2 +-
29
hw/arm/allwinner-h3.c | 2 +-
30
hw/arm/aspeed.c | 2 +-
31
hw/block/block.c | 2 +-
32
hw/block/fdc.c | 6 +++---
33
hw/block/hd-geometry.c | 2 +-
34
hw/block/m25p80.c | 2 +-
35
hw/block/nand.c | 12 ++++++------
36
hw/block/onenand.c | 12 ++++++------
37
hw/ide/atapi.c | 4 ++--
38
hw/misc/mac_via.c | 2 +-
39
hw/misc/sifive_u_otp.c | 4 ++--
40
hw/nvram/eeprom_at24c.c | 2 +-
41
hw/nvram/spapr_nvram.c | 2 +-
42
hw/nvram/xlnx-bbram.c | 2 +-
43
hw/nvram/xlnx-efuse.c | 2 +-
44
hw/ppc/pnv_pnor.c | 2 +-
45
hw/sd/sd.c | 2 +-
46
migration/block.c | 4 ++--
47
nbd/server.c | 4 ++--
48
qemu-img.c | 12 ++++++------
49
qemu-io-cmds.c | 2 +-
50
tests/unit/test-block-iothread.c | 4 ++--
51
27 files changed, 52 insertions(+), 50 deletions(-)
52
53
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
54
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
55
--- a/include/sysemu/block-backend-io.h
27
--- a/block/nbd-client.h
56
+++ b/include/sysemu/block-backend-io.h
28
+++ b/block/nbd-client.h
57
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
29
@@ -XXX,XX +XXX,XX @@ typedef struct NBDClientSession {
58
* the "I/O or GS" API.
30
59
*/
31
CoMutex send_mutex;
60
32
CoQueue free_sema;
61
-int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes);
33
- Coroutine *send_coroutine;
62
+int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes,
34
+ Coroutine *read_reply_co;
63
+ BdrvRequestFlags flags);
35
int in_flight;
64
int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int bytes,
36
65
BdrvRequestFlags flags);
37
Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
66
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
38
diff --git a/block/nbd-client.c b/block/nbd-client.c
67
diff --git a/block.c b/block.c
68
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
69
--- a/block.c
40
--- a/block/nbd-client.c
70
+++ b/block.c
41
+++ b/block/nbd-client.c
71
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
42
@@ -XXX,XX +XXX,XX @@
43
#define HANDLE_TO_INDEX(bs, handle) ((handle) ^ ((uint64_t)(intptr_t)bs))
44
#define INDEX_TO_HANDLE(bs, index) ((index) ^ ((uint64_t)(intptr_t)bs))
45
46
-static void nbd_recv_coroutines_enter_all(NBDClientSession *s)
47
+static void nbd_recv_coroutines_enter_all(BlockDriverState *bs)
48
{
49
+ NBDClientSession *s = nbd_get_client_session(bs);
50
int i;
51
52
for (i = 0; i < MAX_NBD_REQUESTS; i++) {
53
@@ -XXX,XX +XXX,XX @@ static void nbd_recv_coroutines_enter_all(NBDClientSession *s)
54
qemu_coroutine_enter(s->recv_coroutine[i]);
55
}
56
}
57
+ BDRV_POLL_WHILE(bs, s->read_reply_co);
58
}
59
60
static void nbd_teardown_connection(BlockDriverState *bs)
61
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
62
qio_channel_shutdown(client->ioc,
63
QIO_CHANNEL_SHUTDOWN_BOTH,
64
NULL);
65
- nbd_recv_coroutines_enter_all(client);
66
+ nbd_recv_coroutines_enter_all(bs);
67
68
nbd_client_detach_aio_context(bs);
69
object_unref(OBJECT(client->sioc));
70
@@ -XXX,XX +XXX,XX @@ static void nbd_teardown_connection(BlockDriverState *bs)
71
client->ioc = NULL;
72
}
73
74
-static void nbd_reply_ready(void *opaque)
75
+static coroutine_fn void nbd_read_reply_entry(void *opaque)
76
{
77
- BlockDriverState *bs = opaque;
78
- NBDClientSession *s = nbd_get_client_session(bs);
79
+ NBDClientSession *s = opaque;
80
uint64_t i;
81
int ret;
82
83
- if (!s->ioc) { /* Already closed */
84
- return;
85
- }
86
-
87
- if (s->reply.handle == 0) {
88
- /* No reply already in flight. Fetch a header. It is possible
89
- * that another thread has done the same thing in parallel, so
90
- * the socket is not readable anymore.
91
- */
92
+ for (;;) {
93
+ assert(s->reply.handle == 0);
94
ret = nbd_receive_reply(s->ioc, &s->reply);
95
- if (ret == -EAGAIN) {
96
- return;
97
- }
98
if (ret < 0) {
99
- s->reply.handle = 0;
100
- goto fail;
101
+ break;
102
}
103
- }
104
105
- /* There's no need for a mutex on the receive side, because the
106
- * handler acts as a synchronization point and ensures that only
107
- * one coroutine is called until the reply finishes. */
108
- i = HANDLE_TO_INDEX(s, s->reply.handle);
109
- if (i >= MAX_NBD_REQUESTS) {
110
- goto fail;
111
- }
112
+ /* There's no need for a mutex on the receive side, because the
113
+ * handler acts as a synchronization point and ensures that only
114
+ * one coroutine is called until the reply finishes.
115
+ */
116
+ i = HANDLE_TO_INDEX(s, s->reply.handle);
117
+ if (i >= MAX_NBD_REQUESTS || !s->recv_coroutine[i]) {
118
+ break;
119
+ }
120
121
- if (s->recv_coroutine[i]) {
122
- qemu_coroutine_enter(s->recv_coroutine[i]);
123
- return;
124
+ /* We're woken up by the recv_coroutine itself. Note that there
125
+ * is no race between yielding and reentering read_reply_co. This
126
+ * is because:
127
+ *
128
+ * - if recv_coroutine[i] runs on the same AioContext, it is only
129
+ * entered after we yield
130
+ *
131
+ * - if recv_coroutine[i] runs on a different AioContext, reentering
132
+ * read_reply_co happens through a bottom half, which can only
133
+ * run after we yield.
134
+ */
135
+ aio_co_wake(s->recv_coroutine[i]);
136
+ qemu_coroutine_yield();
137
}
138
-
139
-fail:
140
- nbd_teardown_connection(bs);
141
-}
142
-
143
-static void nbd_restart_write(void *opaque)
144
-{
145
- BlockDriverState *bs = opaque;
146
-
147
- qemu_coroutine_enter(nbd_get_client_session(bs)->send_coroutine);
148
+ s->read_reply_co = NULL;
149
}
150
151
static int nbd_co_send_request(BlockDriverState *bs,
152
@@ -XXX,XX +XXX,XX @@ static int nbd_co_send_request(BlockDriverState *bs,
153
QEMUIOVector *qiov)
154
{
155
NBDClientSession *s = nbd_get_client_session(bs);
156
- AioContext *aio_context;
157
int rc, ret, i;
158
159
qemu_co_mutex_lock(&s->send_mutex);
160
@@ -XXX,XX +XXX,XX @@ static int nbd_co_send_request(BlockDriverState *bs,
161
return -EPIPE;
162
}
163
164
- s->send_coroutine = qemu_coroutine_self();
165
- aio_context = bdrv_get_aio_context(bs);
166
-
167
- aio_set_fd_handler(aio_context, s->sioc->fd, false,
168
- nbd_reply_ready, nbd_restart_write, NULL, bs);
169
if (qiov) {
170
qio_channel_set_cork(s->ioc, true);
171
rc = nbd_send_request(s->ioc, request);
172
@@ -XXX,XX +XXX,XX @@ static int nbd_co_send_request(BlockDriverState *bs,
173
} else {
174
rc = nbd_send_request(s->ioc, request);
175
}
176
- aio_set_fd_handler(aio_context, s->sioc->fd, false,
177
- nbd_reply_ready, NULL, NULL, bs);
178
- s->send_coroutine = NULL;
179
qemu_co_mutex_unlock(&s->send_mutex);
180
return rc;
181
}
182
@@ -XXX,XX +XXX,XX @@ static void nbd_co_receive_reply(NBDClientSession *s,
183
{
184
int ret;
185
186
- /* Wait until we're woken up by the read handler. TODO: perhaps
187
- * peek at the next reply and avoid yielding if it's ours? */
188
+ /* Wait until we're woken up by nbd_read_reply_entry. */
189
qemu_coroutine_yield();
190
*reply = s->reply;
191
if (reply->handle != request->handle ||
192
@@ -XXX,XX +XXX,XX @@ static void nbd_coroutine_start(NBDClientSession *s,
193
/* s->recv_coroutine[i] is set as soon as we get the send_lock. */
194
}
195
196
-static void nbd_coroutine_end(NBDClientSession *s,
197
+static void nbd_coroutine_end(BlockDriverState *bs,
198
NBDRequest *request)
199
{
200
+ NBDClientSession *s = nbd_get_client_session(bs);
201
int i = HANDLE_TO_INDEX(s, request->handle);
202
+
203
s->recv_coroutine[i] = NULL;
204
- if (s->in_flight-- == MAX_NBD_REQUESTS) {
205
- qemu_co_queue_next(&s->free_sema);
206
+ s->in_flight--;
207
+ qemu_co_queue_next(&s->free_sema);
208
+
209
+ /* Kick the read_reply_co to get the next reply. */
210
+ if (s->read_reply_co) {
211
+ aio_co_wake(s->read_reply_co);
212
}
213
}
214
215
@@ -XXX,XX +XXX,XX @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
216
} else {
217
nbd_co_receive_reply(client, &request, &reply, qiov);
218
}
219
- nbd_coroutine_end(client, &request);
220
+ nbd_coroutine_end(bs, &request);
221
return -reply.error;
222
}
223
224
@@ -XXX,XX +XXX,XX @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
225
} else {
226
nbd_co_receive_reply(client, &request, &reply, NULL);
227
}
228
- nbd_coroutine_end(client, &request);
229
+ nbd_coroutine_end(bs, &request);
230
return -reply.error;
231
}
232
233
@@ -XXX,XX +XXX,XX @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
234
} else {
235
nbd_co_receive_reply(client, &request, &reply, NULL);
236
}
237
- nbd_coroutine_end(client, &request);
238
+ nbd_coroutine_end(bs, &request);
239
return -reply.error;
240
}
241
242
@@ -XXX,XX +XXX,XX @@ int nbd_client_co_flush(BlockDriverState *bs)
243
} else {
244
nbd_co_receive_reply(client, &request, &reply, NULL);
245
}
246
- nbd_coroutine_end(client, &request);
247
+ nbd_coroutine_end(bs, &request);
248
return -reply.error;
249
}
250
251
@@ -XXX,XX +XXX,XX @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int count)
252
} else {
253
nbd_co_receive_reply(client, &request, &reply, NULL);
254
}
255
- nbd_coroutine_end(client, &request);
256
+ nbd_coroutine_end(bs, &request);
257
return -reply.error;
258
259
}
260
261
void nbd_client_detach_aio_context(BlockDriverState *bs)
262
{
263
- aio_set_fd_handler(bdrv_get_aio_context(bs),
264
- nbd_get_client_session(bs)->sioc->fd,
265
- false, NULL, NULL, NULL, NULL);
266
+ NBDClientSession *client = nbd_get_client_session(bs);
267
+ qio_channel_detach_aio_context(QIO_CHANNEL(client->sioc));
268
}
269
270
void nbd_client_attach_aio_context(BlockDriverState *bs,
271
AioContext *new_context)
272
{
273
- aio_set_fd_handler(new_context, nbd_get_client_session(bs)->sioc->fd,
274
- false, nbd_reply_ready, NULL, NULL, bs);
275
+ NBDClientSession *client = nbd_get_client_session(bs);
276
+ qio_channel_attach_aio_context(QIO_CHANNEL(client->sioc), new_context);
277
+ aio_co_schedule(new_context, client->read_reply_co);
278
}
279
280
void nbd_client_close(BlockDriverState *bs)
281
@@ -XXX,XX +XXX,XX @@ int nbd_client_init(BlockDriverState *bs,
282
/* Now that we're connected, set the socket to be non-blocking and
283
* kick the reply mechanism. */
284
qio_channel_set_blocking(QIO_CHANNEL(sioc), false, NULL);
285
-
286
+ client->read_reply_co = qemu_coroutine_create(nbd_read_reply_entry, client);
287
nbd_client_attach_aio_context(bs, bdrv_get_aio_context(bs));
288
289
logout("Established connection with NBD server\n");
290
diff --git a/nbd/client.c b/nbd/client.c
291
index XXXXXXX..XXXXXXX 100644
292
--- a/nbd/client.c
293
+++ b/nbd/client.c
294
@@ -XXX,XX +XXX,XX @@ ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply)
295
ssize_t ret;
296
297
ret = read_sync(ioc, buf, sizeof(buf));
298
- if (ret < 0) {
299
+ if (ret <= 0) {
72
return ret;
300
return ret;
73
}
301
}
74
302
75
- ret = blk_pread(file, 0, buf, sizeof(buf));
303
diff --git a/nbd/common.c b/nbd/common.c
76
+ ret = blk_pread(file, 0, buf, sizeof(buf), 0);
77
if (ret < 0) {
78
error_setg_errno(errp, -ret, "Could not read image for determining its "
79
"format");
80
diff --git a/block/block-backend.c b/block/block-backend.c
81
index XXXXXXX..XXXXXXX 100644
304
index XXXXXXX..XXXXXXX 100644
82
--- a/block/block-backend.c
305
--- a/nbd/common.c
83
+++ b/block/block-backend.c
306
+++ b/nbd/common.c
84
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
307
@@ -XXX,XX +XXX,XX @@ ssize_t nbd_wr_syncv(QIOChannel *ioc,
85
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
86
}
87
88
-int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes)
89
+int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes,
90
+ BdrvRequestFlags flags)
91
{
92
int ret;
93
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
94
IO_OR_GS_CODE();
95
96
blk_inc_in_flight(blk);
97
- ret = blk_do_preadv(blk, offset, bytes, &qiov, 0);
98
+ ret = blk_do_preadv(blk, offset, bytes, &qiov, flags);
99
blk_dec_in_flight(blk);
100
101
return ret;
102
diff --git a/block/commit.c b/block/commit.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/block/commit.c
105
+++ b/block/commit.c
106
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
107
goto ro_cleanup;
108
}
308
}
109
if (ret) {
309
if (len == QIO_CHANNEL_ERR_BLOCK) {
110
- ret = blk_pread(src, offset, buf, n);
310
if (qemu_in_coroutine()) {
111
+ ret = blk_pread(src, offset, buf, n, 0);
311
- /* XXX figure out if we can create a variant on
112
if (ret < 0) {
312
- * qio_channel_yield() that works with AIO contexts
113
goto ro_cleanup;
313
- * and consider using that in this branch */
314
- qemu_coroutine_yield();
315
- } else if (done) {
316
- /* XXX this is needed by nbd_reply_ready. */
317
- qio_channel_wait(ioc,
318
- do_read ? G_IO_IN : G_IO_OUT);
319
+ qio_channel_yield(ioc, do_read ? G_IO_IN : G_IO_OUT);
320
} else {
321
return -EAGAIN;
114
}
322
}
115
diff --git a/block/export/fuse.c b/block/export/fuse.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/block/export/fuse.c
118
+++ b/block/export/fuse.c
119
@@ -XXX,XX +XXX,XX @@ static void fuse_read(fuse_req_t req, fuse_ino_t inode,
120
return;
121
}
122
123
- ret = blk_pread(exp->common.blk, offset, buf, size);
124
+ ret = blk_pread(exp->common.blk, offset, buf, size, 0);
125
if (ret >= 0) {
126
fuse_reply_buf(req, buf, size);
127
} else {
128
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/hw/arm/allwinner-h3.c
131
+++ b/hw/arm/allwinner-h3.c
132
@@ -XXX,XX +XXX,XX @@ void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk)
133
const int64_t rom_size = 32 * KiB;
134
g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
135
136
- if (blk_pread(blk, 8 * KiB, buffer, rom_size) < 0) {
137
+ if (blk_pread(blk, 8 * KiB, buffer, rom_size, 0) < 0) {
138
error_setg(&error_fatal, "%s: failed to read BlockBackend data",
139
__func__);
140
return;
141
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/arm/aspeed.c
144
+++ b/hw/arm/aspeed.c
145
@@ -XXX,XX +XXX,XX @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
146
}
147
148
storage = g_malloc0(rom_size);
149
- if (blk_pread(blk, 0, storage, rom_size) < 0) {
150
+ if (blk_pread(blk, 0, storage, rom_size, 0) < 0) {
151
error_setg(errp, "failed to read the initial flash content");
152
return;
153
}
154
diff --git a/hw/block/block.c b/hw/block/block.c
155
index XXXXXXX..XXXXXXX 100644
156
--- a/hw/block/block.c
157
+++ b/hw/block/block.c
158
@@ -XXX,XX +XXX,XX @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
159
* block device and read only on demand.
160
*/
161
assert(size <= BDRV_REQUEST_MAX_BYTES);
162
- ret = blk_pread(blk, 0, buf, size);
163
+ ret = blk_pread(blk, 0, buf, size, 0);
164
if (ret < 0) {
165
error_setg_errno(errp, -ret, "can't read block backend");
166
return false;
167
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/hw/block/fdc.c
170
+++ b/hw/block/fdc.c
171
@@ -XXX,XX +XXX,XX @@ int fdctrl_transfer_handler(void *opaque, int nchan, int dma_pos, int dma_len)
172
if (fdctrl->data_dir != FD_DIR_WRITE ||
173
len < FD_SECTOR_LEN || rel_pos != 0) {
174
/* READ & SCAN commands and realign to a sector for WRITE */
175
- if (blk_pread(cur_drv->blk, fd_offset(cur_drv),
176
- fdctrl->fifo, BDRV_SECTOR_SIZE) < 0) {
177
+ if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
178
+ BDRV_SECTOR_SIZE, 0) < 0) {
179
FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
180
fd_sector(cur_drv));
181
/* Sure, image size is too small... */
182
@@ -XXX,XX +XXX,XX @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
183
return 0;
184
}
185
if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
186
- BDRV_SECTOR_SIZE)
187
+ BDRV_SECTOR_SIZE, 0)
188
< 0) {
189
FLOPPY_DPRINTF("error getting sector %d\n",
190
fd_sector(cur_drv));
191
diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/hw/block/hd-geometry.c
194
+++ b/hw/block/hd-geometry.c
195
@@ -XXX,XX +XXX,XX @@ static int guess_disk_lchs(BlockBackend *blk,
196
197
blk_get_geometry(blk, &nb_sectors);
198
199
- if (blk_pread(blk, 0, buf, BDRV_SECTOR_SIZE) < 0) {
200
+ if (blk_pread(blk, 0, buf, BDRV_SECTOR_SIZE, 0) < 0) {
201
return -1;
202
}
203
/* test msdos magic */
204
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/hw/block/m25p80.c
207
+++ b/hw/block/m25p80.c
208
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSIPeripheral *ss, Error **errp)
209
trace_m25p80_binding(s);
210
s->storage = blk_blockalign(s->blk, s->size);
211
212
- if (blk_pread(s->blk, 0, s->storage, s->size) < 0) {
213
+ if (blk_pread(s->blk, 0, s->storage, s->size, 0) < 0) {
214
error_setg(errp, "failed to read the initial flash content");
215
return;
216
}
217
diff --git a/hw/block/nand.c b/hw/block/nand.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/hw/block/nand.c
220
+++ b/hw/block/nand.c
221
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_write_, NAND_PAGE_SIZE)(NANDFlashState *s)
222
off = (s->addr & PAGE_MASK) + s->offset;
223
soff = SECTOR_OFFSET(s->addr);
224
if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
225
- PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
226
+ PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
227
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
228
return;
229
}
230
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_write_, NAND_PAGE_SIZE)(NANDFlashState *s)
231
sector = off >> 9;
232
soff = off & 0x1ff;
233
if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
234
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
235
+ (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
236
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
237
return;
238
}
239
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
240
addr = PAGE_START(addr);
241
page = addr >> 9;
242
if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
243
- BDRV_SECTOR_SIZE) < 0) {
244
+ BDRV_SECTOR_SIZE, 0) < 0) {
245
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
246
}
247
memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
248
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
249
250
page = i >> 9;
251
if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
252
- BDRV_SECTOR_SIZE) < 0) {
253
+ BDRV_SECTOR_SIZE, 0) < 0) {
254
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
255
}
256
memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
257
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
258
if (s->blk) {
259
if (s->mem_oob) {
260
if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io,
261
- PAGE_SECTORS << BDRV_SECTOR_BITS) < 0) {
262
+ PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
263
printf("%s: read error in sector %" PRIu64 "\n",
264
__func__, SECTOR(addr));
265
}
266
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
267
s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
268
} else {
269
if (blk_pread(s->blk, PAGE_START(addr), s->io,
270
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS) < 0) {
271
+ (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
272
printf("%s: read error in sector %" PRIu64 "\n",
273
__func__, PAGE_START(addr) >> 9);
274
}
275
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
276
index XXXXXXX..XXXXXXX 100644
277
--- a/hw/block/onenand.c
278
+++ b/hw/block/onenand.c
279
@@ -XXX,XX +XXX,XX @@ static void onenand_reset(OneNANDState *s, int cold)
280
memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
281
282
if (s->blk_cur && blk_pread(s->blk_cur, 0, s->boot[0],
283
- 8 << BDRV_SECTOR_BITS) < 0) {
284
+ 8 << BDRV_SECTOR_BITS, 0) < 0) {
285
hw_error("%s: Loading the BootRAM failed.\n", __func__);
286
}
287
}
288
@@ -XXX,XX +XXX,XX @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
289
assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
290
if (s->blk_cur) {
291
return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS, dest,
292
- secn << BDRV_SECTOR_BITS) < 0;
293
+ secn << BDRV_SECTOR_BITS, 0) < 0;
294
} else if (sec + secn > s->secs_cur) {
295
return 1;
296
}
297
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
298
uint8_t *dp = 0;
299
if (s->blk_cur) {
300
dp = g_malloc(size);
301
- if (!dp || blk_pread(s->blk_cur, offset, dp, size) < 0) {
302
+ if (!dp || blk_pread(s->blk_cur, offset, dp, size, 0) < 0) {
303
result = 1;
304
}
305
} else {
306
@@ -XXX,XX +XXX,XX @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
307
308
if (s->blk_cur) {
309
uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
310
- if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE) < 0) {
311
+ if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE, 0) < 0) {
312
return 1;
313
}
314
memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
315
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
316
if (s->blk_cur) {
317
dp = g_malloc(512);
318
if (!dp
319
- || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE) < 0) {
320
+ || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE, 0) < 0) {
321
result = 1;
322
} else {
323
dpp = dp + ((sec & 31) << 4);
324
@@ -XXX,XX +XXX,XX @@ static inline int onenand_erase(OneNANDState *s, int sec, int num)
325
goto fail;
326
}
327
if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
328
- BDRV_SECTOR_SIZE) < 0) {
329
+ BDRV_SECTOR_SIZE, 0) < 0) {
330
goto fail;
331
}
332
memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
333
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
334
index XXXXXXX..XXXXXXX 100644
335
--- a/hw/ide/atapi.c
336
+++ b/hw/ide/atapi.c
337
@@ -XXX,XX +XXX,XX @@ cd_read_sector_sync(IDEState *s)
338
switch (s->cd_sector_size) {
339
case 2048:
340
ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
341
- s->io_buffer, ATAPI_SECTOR_SIZE);
342
+ s->io_buffer, ATAPI_SECTOR_SIZE, 0);
343
break;
344
case 2352:
345
ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
346
- s->io_buffer + 16, ATAPI_SECTOR_SIZE);
347
+ s->io_buffer + 16, ATAPI_SECTOR_SIZE, 0);
348
if (ret >= 0) {
349
cd_data_to_raw(s->io_buffer, s->lba);
350
}
351
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
352
index XXXXXXX..XXXXXXX 100644
353
--- a/hw/misc/mac_via.c
354
+++ b/hw/misc/mac_via.c
355
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
356
return;
357
}
358
359
- ret = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM));
360
+ ret = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM), 0);
361
if (ret < 0) {
362
error_setg(errp, "can't read PRAM contents");
363
return;
364
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
365
index XXXXXXX..XXXXXXX 100644
366
--- a/hw/misc/sifive_u_otp.c
367
+++ b/hw/misc/sifive_u_otp.c
368
@@ -XXX,XX +XXX,XX @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
369
int32_t buf;
370
371
if (blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
372
- SIFIVE_U_OTP_FUSE_WORD) < 0) {
373
+ SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
374
error_report("read error index<%d>", s->pa);
375
return 0xff;
376
}
377
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
378
return;
379
}
380
381
- if (blk_pread(s->blk, 0, s->fuse, filesize) < 0) {
382
+ if (blk_pread(s->blk, 0, s->fuse, filesize, 0) < 0) {
383
error_setg(errp, "failed to read the initial flash content");
384
return;
385
}
386
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
387
index XXXXXXX..XXXXXXX 100644
388
--- a/hw/nvram/eeprom_at24c.c
389
+++ b/hw/nvram/eeprom_at24c.c
390
@@ -XXX,XX +XXX,XX @@ void at24c_eeprom_reset(DeviceState *state)
391
memset(ee->mem, 0, ee->rsize);
392
393
if (ee->blk) {
394
- int ret = blk_pread(ee->blk, 0, ee->mem, ee->rsize);
395
+ int ret = blk_pread(ee->blk, 0, ee->mem, ee->rsize, 0);
396
397
if (ret < 0) {
398
ERR(TYPE_AT24C_EE
399
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
400
index XXXXXXX..XXXXXXX 100644
401
--- a/hw/nvram/spapr_nvram.c
402
+++ b/hw/nvram/spapr_nvram.c
403
@@ -XXX,XX +XXX,XX @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
404
}
405
406
if (nvram->blk) {
407
- ret = blk_pread(nvram->blk, 0, nvram->buf, nvram->size);
408
+ ret = blk_pread(nvram->blk, 0, nvram->buf, nvram->size, 0);
409
410
if (ret < 0) {
411
error_setg(errp, "can't read spapr-nvram contents");
412
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
413
index XXXXXXX..XXXXXXX 100644
414
--- a/hw/nvram/xlnx-bbram.c
415
+++ b/hw/nvram/xlnx-bbram.c
416
@@ -XXX,XX +XXX,XX @@ static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
417
blk_name(s->blk));
418
}
419
420
- if (blk_pread(s->blk, 0, ram, nr) < 0) {
421
+ if (blk_pread(s->blk, 0, ram, nr, 0) < 0) {
422
error_setg(errp,
423
"%s: Failed to read %u bytes from BBRAM backstore.",
424
blk_name(s->blk), nr);
425
diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
426
index XXXXXXX..XXXXXXX 100644
427
--- a/hw/nvram/xlnx-efuse.c
428
+++ b/hw/nvram/xlnx-efuse.c
429
@@ -XXX,XX +XXX,XX @@ static int efuse_bdrv_read(XlnxEFuse *s, Error **errp)
430
blk_name(s->blk));
431
}
432
433
- if (blk_pread(s->blk, 0, ram, nr) < 0) {
434
+ if (blk_pread(s->blk, 0, ram, nr, 0) < 0) {
435
error_setg(errp, "%s: Failed to read %u bytes from eFUSE backstore.",
436
blk_name(s->blk), nr);
437
return -1;
438
diff --git a/hw/ppc/pnv_pnor.c b/hw/ppc/pnv_pnor.c
439
index XXXXXXX..XXXXXXX 100644
440
--- a/hw/ppc/pnv_pnor.c
441
+++ b/hw/ppc/pnv_pnor.c
442
@@ -XXX,XX +XXX,XX @@ static void pnv_pnor_realize(DeviceState *dev, Error **errp)
443
444
s->storage = blk_blockalign(s->blk, s->size);
445
446
- if (blk_pread(s->blk, 0, s->storage, s->size) < 0) {
447
+ if (blk_pread(s->blk, 0, s->storage, s->size, 0) < 0) {
448
error_setg(errp, "failed to read the initial flash content");
449
return;
450
}
451
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
452
index XXXXXXX..XXXXXXX 100644
453
--- a/hw/sd/sd.c
454
+++ b/hw/sd/sd.c
455
@@ -XXX,XX +XXX,XX @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
456
static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
457
{
458
trace_sdcard_read_block(addr, len);
459
- if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) {
460
+ if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len, 0) < 0) {
461
fprintf(stderr, "sd_blk_read: read error on host side\n");
462
}
463
}
464
diff --git a/migration/block.c b/migration/block.c
465
index XXXXXXX..XXXXXXX 100644
466
--- a/migration/block.c
467
+++ b/migration/block.c
468
@@ -XXX,XX +XXX,XX @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
469
bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
470
blk_mig_unlock();
471
} else {
472
- ret = blk_pread(bmds->blk, sector * BDRV_SECTOR_SIZE, blk->buf,
473
- nr_sectors * BDRV_SECTOR_SIZE);
474
+ ret = blk_pread(bmds->blk, sector * BDRV_SECTOR_SIZE,
475
+ blk->buf, nr_sectors * BDRV_SECTOR_SIZE, 0);
476
if (ret < 0) {
477
goto error;
478
}
479
diff --git a/nbd/server.c b/nbd/server.c
323
diff --git a/nbd/server.c b/nbd/server.c
480
index XXXXXXX..XXXXXXX 100644
324
index XXXXXXX..XXXXXXX 100644
481
--- a/nbd/server.c
325
--- a/nbd/server.c
482
+++ b/nbd/server.c
326
+++ b/nbd/server.c
483
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
327
@@ -XXX,XX +XXX,XX @@ struct NBDClient {
484
ret = nbd_co_send_iov(client, iov, 1, errp);
328
CoMutex send_lock;
485
} else {
329
Coroutine *send_coroutine;
486
ret = blk_pread(exp->common.blk, offset + progress,
330
487
- data + progress, pnum);
331
- bool can_read;
488
+ data + progress, pnum, 0);
332
-
489
if (ret < 0) {
333
QTAILQ_ENTRY(NBDClient) next;
490
error_setg_errno(errp, -ret, "reading from file failed");
334
int nb_requests;
491
break;
335
bool closing;
492
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
336
@@ -XXX,XX +XXX,XX @@ struct NBDClient {
493
data, request->len, errp);
337
494
}
338
/* That's all folks */
495
339
496
- ret = blk_pread(exp->common.blk, request->from, data, request->len);
340
-static void nbd_set_handlers(NBDClient *client);
497
+ ret = blk_pread(exp->common.blk, request->from, data, request->len, 0);
341
-static void nbd_unset_handlers(NBDClient *client);
498
if (ret < 0) {
342
-static void nbd_update_can_read(NBDClient *client);
499
return nbd_send_generic_reply(client, request->handle, ret,
343
+static void nbd_client_receive_next_request(NBDClient *client);
500
"reading from file failed", errp);
344
501
diff --git a/qemu-img.c b/qemu-img.c
345
static gboolean nbd_negotiate_continue(QIOChannel *ioc,
502
index XXXXXXX..XXXXXXX 100644
346
GIOCondition condition,
503
--- a/qemu-img.c
347
@@ -XXX,XX +XXX,XX @@ void nbd_client_put(NBDClient *client)
504
+++ b/qemu-img.c
348
*/
505
@@ -XXX,XX +XXX,XX @@ static int check_empty_sectors(BlockBackend *blk, int64_t offset,
349
assert(client->closing);
506
int ret = 0;
350
507
int64_t idx;
351
- nbd_unset_handlers(client);
508
352
+ qio_channel_detach_aio_context(client->ioc);
509
- ret = blk_pread(blk, offset, buffer, bytes);
353
object_unref(OBJECT(client->sioc));
510
+ ret = blk_pread(blk, offset, buffer, bytes, 0);
354
object_unref(OBJECT(client->ioc));
511
if (ret < 0) {
355
if (client->tlscreds) {
512
error_report("Error while reading offset %" PRId64 " of %s: %s",
356
@@ -XXX,XX +XXX,XX @@ static NBDRequestData *nbd_request_get(NBDClient *client)
513
offset, filename, strerror(-ret));
357
514
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
358
assert(client->nb_requests <= MAX_NBD_REQUESTS - 1);
515
int64_t pnum;
359
client->nb_requests++;
516
360
- nbd_update_can_read(client);
517
chunk = MIN(chunk, IO_BUF_SIZE);
361
518
- ret = blk_pread(blk1, offset, buf1, chunk);
362
req = g_new0(NBDRequestData, 1);
519
+ ret = blk_pread(blk1, offset, buf1, chunk, 0);
363
nbd_client_get(client);
520
if (ret < 0) {
364
@@ -XXX,XX +XXX,XX @@ static void nbd_request_put(NBDRequestData *req)
521
error_report("Error while reading offset %" PRId64
365
g_free(req);
522
" of %s: %s",
366
523
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
367
client->nb_requests--;
524
ret = 4;
368
- nbd_update_can_read(client);
525
goto out;
369
+ nbd_client_receive_next_request(client);
526
}
370
+
527
- ret = blk_pread(blk2, offset, buf2, chunk);
371
nbd_client_put(client);
528
+ ret = blk_pread(blk2, offset, buf2, chunk, 0);
372
}
529
if (ret < 0) {
373
530
error_report("Error while reading offset %" PRId64
374
@@ -XXX,XX +XXX,XX @@ static void blk_aio_attached(AioContext *ctx, void *opaque)
531
" of %s: %s",
375
exp->ctx = ctx;
532
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
376
533
n = old_backing_size - offset;
377
QTAILQ_FOREACH(client, &exp->clients, next) {
534
}
378
- nbd_set_handlers(client);
535
379
+ qio_channel_attach_aio_context(client->ioc, ctx);
536
- ret = blk_pread(blk_old_backing, offset, buf_old, n);
380
+ if (client->recv_coroutine) {
537
+ ret = blk_pread(blk_old_backing, offset, buf_old, n, 0);
381
+ aio_co_schedule(ctx, client->recv_coroutine);
538
if (ret < 0) {
382
+ }
539
error_report("error while reading from old backing file");
383
+ if (client->send_coroutine) {
540
goto out;
384
+ aio_co_schedule(ctx, client->send_coroutine);
541
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
385
+ }
542
n = new_backing_size - offset;
386
}
543
}
387
}
544
388
545
- ret = blk_pread(blk_new_backing, offset, buf_new, n);
389
@@ -XXX,XX +XXX,XX @@ static void blk_aio_detach(void *opaque)
546
+ ret = blk_pread(blk_new_backing, offset, buf_new, n, 0);
390
TRACE("Export %s: Detaching clients from AIO context %p\n", exp->name, exp->ctx);
547
if (ret < 0) {
391
548
error_report("error while reading from new backing file");
392
QTAILQ_FOREACH(client, &exp->clients, next) {
549
goto out;
393
- nbd_unset_handlers(client);
550
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
394
+ qio_channel_detach_aio_context(client->ioc);
551
for (out_pos = 0; in_pos < size; block_count++) {
395
}
552
int bytes = (in_pos + in.bsz > size) ? size - in_pos : in.bsz;
396
553
397
exp->ctx = NULL;
554
- ret = blk_pread(blk1, in_pos, in.buf, bytes);
398
@@ -XXX,XX +XXX,XX @@ static ssize_t nbd_co_send_reply(NBDRequestData *req, NBDReply *reply,
555
+ ret = blk_pread(blk1, in_pos, in.buf, bytes, 0);
399
g_assert(qemu_in_coroutine());
556
if (ret < 0) {
400
qemu_co_mutex_lock(&client->send_lock);
557
error_report("error while reading from input image file: %s",
401
client->send_coroutine = qemu_coroutine_self();
558
strerror(-ret));
402
- nbd_set_handlers(client);
559
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
403
560
index XXXXXXX..XXXXXXX 100644
404
if (!len) {
561
--- a/qemu-io-cmds.c
405
rc = nbd_send_reply(client->ioc, reply);
562
+++ b/qemu-io-cmds.c
406
@@ -XXX,XX +XXX,XX @@ static ssize_t nbd_co_send_reply(NBDRequestData *req, NBDReply *reply,
563
@@ -XXX,XX +XXX,XX @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
407
}
564
return -ERANGE;
408
565
}
409
client->send_coroutine = NULL;
566
410
- nbd_set_handlers(client);
567
- ret = blk_pread(blk, offset, (uint8_t *)buf, bytes);
411
qemu_co_mutex_unlock(&client->send_lock);
568
+ ret = blk_pread(blk, offset, (uint8_t *)buf, bytes, 0);
412
return rc;
569
if (ret < 0) {
413
}
570
return ret;
414
@@ -XXX,XX +XXX,XX @@ static ssize_t nbd_co_receive_request(NBDRequestData *req,
571
}
415
ssize_t rc;
572
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
416
573
index XXXXXXX..XXXXXXX 100644
417
g_assert(qemu_in_coroutine());
574
--- a/tests/unit/test-block-iothread.c
418
- client->recv_coroutine = qemu_coroutine_self();
575
+++ b/tests/unit/test-block-iothread.c
419
- nbd_update_can_read(client);
576
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pread(BlockBackend *blk)
420
-
577
int ret;
421
+ assert(client->recv_coroutine == qemu_coroutine_self());
578
422
rc = nbd_receive_request(client->ioc, request);
579
/* Success */
423
if (rc < 0) {
580
- ret = blk_pread(blk, 0, buf, sizeof(buf));
424
if (rc != -EAGAIN) {
581
+ ret = blk_pread(blk, 0, buf, sizeof(buf), 0);
425
@@ -XXX,XX +XXX,XX @@ static ssize_t nbd_co_receive_request(NBDRequestData *req,
582
g_assert_cmpint(ret, ==, 0);
426
583
427
out:
584
/* Early error: Negative offset */
428
client->recv_coroutine = NULL;
585
- ret = blk_pread(blk, -2, buf, sizeof(buf));
429
- nbd_update_can_read(client);
586
+ ret = blk_pread(blk, -2, buf, sizeof(buf), 0);
430
+ nbd_client_receive_next_request(client);
587
g_assert_cmpint(ret, ==, -EIO);
431
588
}
432
return rc;
589
433
}
434
435
-static void nbd_trip(void *opaque)
436
+/* Owns a reference to the NBDClient passed as opaque. */
437
+static coroutine_fn void nbd_trip(void *opaque)
438
{
439
NBDClient *client = opaque;
440
NBDExport *exp = client->exp;
441
NBDRequestData *req;
442
- NBDRequest request;
443
+ NBDRequest request = { 0 }; /* GCC thinks it can be used uninitialized */
444
NBDReply reply;
445
ssize_t ret;
446
int flags;
447
448
TRACE("Reading request.");
449
if (client->closing) {
450
+ nbd_client_put(client);
451
return;
452
}
453
454
@@ -XXX,XX +XXX,XX @@ static void nbd_trip(void *opaque)
455
456
done:
457
nbd_request_put(req);
458
+ nbd_client_put(client);
459
return;
460
461
out:
462
nbd_request_put(req);
463
client_close(client);
464
+ nbd_client_put(client);
465
}
466
467
-static void nbd_read(void *opaque)
468
+static void nbd_client_receive_next_request(NBDClient *client)
469
{
470
- NBDClient *client = opaque;
471
-
472
- if (client->recv_coroutine) {
473
- qemu_coroutine_enter(client->recv_coroutine);
474
- } else {
475
- qemu_coroutine_enter(qemu_coroutine_create(nbd_trip, client));
476
- }
477
-}
478
-
479
-static void nbd_restart_write(void *opaque)
480
-{
481
- NBDClient *client = opaque;
482
-
483
- qemu_coroutine_enter(client->send_coroutine);
484
-}
485
-
486
-static void nbd_set_handlers(NBDClient *client)
487
-{
488
- if (client->exp && client->exp->ctx) {
489
- aio_set_fd_handler(client->exp->ctx, client->sioc->fd, true,
490
- client->can_read ? nbd_read : NULL,
491
- client->send_coroutine ? nbd_restart_write : NULL,
492
- NULL, client);
493
- }
494
-}
495
-
496
-static void nbd_unset_handlers(NBDClient *client)
497
-{
498
- if (client->exp && client->exp->ctx) {
499
- aio_set_fd_handler(client->exp->ctx, client->sioc->fd, true, NULL,
500
- NULL, NULL, NULL);
501
- }
502
-}
503
-
504
-static void nbd_update_can_read(NBDClient *client)
505
-{
506
- bool can_read = client->recv_coroutine ||
507
- client->nb_requests < MAX_NBD_REQUESTS;
508
-
509
- if (can_read != client->can_read) {
510
- client->can_read = can_read;
511
- nbd_set_handlers(client);
512
-
513
- /* There is no need to invoke aio_notify(), since aio_set_fd_handler()
514
- * in nbd_set_handlers() will have taken care of that */
515
+ if (!client->recv_coroutine && client->nb_requests < MAX_NBD_REQUESTS) {
516
+ nbd_client_get(client);
517
+ client->recv_coroutine = qemu_coroutine_create(nbd_trip, client);
518
+ aio_co_schedule(client->exp->ctx, client->recv_coroutine);
519
}
520
}
521
522
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void nbd_co_client_start(void *opaque)
523
goto out;
524
}
525
qemu_co_mutex_init(&client->send_lock);
526
- nbd_set_handlers(client);
527
528
if (exp) {
529
QTAILQ_INSERT_TAIL(&exp->clients, client, next);
530
}
531
+
532
+ nbd_client_receive_next_request(client);
533
+
534
out:
535
g_free(data);
536
}
537
@@ -XXX,XX +XXX,XX @@ void nbd_client_new(NBDExport *exp,
538
object_ref(OBJECT(client->sioc));
539
client->ioc = QIO_CHANNEL(sioc);
540
object_ref(OBJECT(client->ioc));
541
- client->can_read = true;
542
client->close = close_fn;
543
544
data->client = client;
590
--
545
--
591
2.35.3
546
2.9.3
547
548
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Also convert blk_ioctl() into a generated_co_wrapper.
3
As a small step towards the introduction of multiqueue, we want
4
coroutines to remain on the same AioContext that started them,
5
unless they are moved explicitly with e.g. aio_co_schedule. This patch
6
avoids that coroutines switch AioContext when they use a CoMutex.
7
For now it does not make much of a difference, because the CoMutex
8
is not thread-safe and the AioContext itself is used to protect the
9
CoMutex from concurrent access. However, this is going to change.
4
10
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
11
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
12
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
13
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Message-Id: <20220705161527.1054072-16-afaria@redhat.com>
14
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
15
Message-id: 20170213135235.12274-9-pbonzini@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
17
---
11
block/coroutines.h | 6 ------
18
util/qemu-coroutine-lock.c | 5 ++---
12
include/sysemu/block-backend-io.h | 5 ++++-
19
util/trace-events | 1 -
13
block/block-backend.c | 7 ++++---
20
2 files changed, 2 insertions(+), 4 deletions(-)
14
3 files changed, 8 insertions(+), 10 deletions(-)
15
21
16
diff --git a/block/coroutines.h b/block/coroutines.h
22
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
17
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
18
--- a/block/coroutines.h
24
--- a/util/qemu-coroutine-lock.c
19
+++ b/block/coroutines.h
25
+++ b/util/qemu-coroutine-lock.c
20
@@ -XXX,XX +XXX,XX @@ blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
26
@@ -XXX,XX +XXX,XX @@
21
QEMUIOVector *qiov, size_t qiov_offset,
27
#include "qemu/coroutine.h"
22
BdrvRequestFlags flags);
28
#include "qemu/coroutine_int.h"
23
29
#include "qemu/queue.h"
24
-int coroutine_fn
30
+#include "block/aio.h"
25
-blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
31
#include "trace.h"
26
-
32
27
int coroutine_fn
33
void qemu_co_queue_init(CoQueue *queue)
28
blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
34
@@ -XXX,XX +XXX,XX @@ void qemu_co_queue_run_restart(Coroutine *co)
29
35
30
@@ -XXX,XX +XXX,XX @@ bdrv_common_block_status_above(BlockDriverState *bs,
36
static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
31
int generated_co_wrapper
37
{
32
nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
38
- Coroutine *self = qemu_coroutine_self();
33
39
Coroutine *next;
34
-int generated_co_wrapper
40
35
-blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
41
if (QSIMPLEQ_EMPTY(&queue->entries)) {
36
-
42
@@ -XXX,XX +XXX,XX @@ static bool qemu_co_queue_do_restart(CoQueue *queue, bool single)
37
#endif /* BLOCK_COROUTINES_H */
43
38
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
44
while ((next = QSIMPLEQ_FIRST(&queue->entries)) != NULL) {
45
QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next);
46
- QSIMPLEQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next);
47
- trace_qemu_co_queue_next(next);
48
+ aio_co_wake(next);
49
if (single) {
50
break;
51
}
52
diff --git a/util/trace-events b/util/trace-events
39
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
40
--- a/include/sysemu/block-backend-io.h
54
--- a/util/trace-events
41
+++ b/include/sysemu/block-backend-io.h
55
+++ b/util/trace-events
42
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
56
@@ -XXX,XX +XXX,XX @@ qemu_coroutine_terminate(void *co) "self %p"
43
int generated_co_wrapper blk_flush(BlockBackend *blk);
57
44
int coroutine_fn blk_co_flush(BlockBackend *blk);
58
# util/qemu-coroutine-lock.c
45
59
qemu_co_queue_run_restart(void *co) "co %p"
46
-int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
60
-qemu_co_queue_next(void *nxt) "next %p"
47
+int generated_co_wrapper blk_ioctl(BlockBackend *blk, unsigned long int req,
61
qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
48
+ void *buf);
62
qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
49
+int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
63
qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
50
+ void *buf);
51
52
int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
53
int64_t offset, int64_t bytes,
54
diff --git a/block/block-backend.c b/block/block-backend.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/block/block-backend.c
57
+++ b/block/block-backend.c
58
@@ -XXX,XX +XXX,XX @@ void blk_aio_cancel_async(BlockAIOCB *acb)
59
}
60
61
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
62
-int coroutine_fn
63
+static int coroutine_fn
64
blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
65
{
66
IO_CODE();
67
@@ -XXX,XX +XXX,XX @@ blk_co_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
68
return bdrv_co_ioctl(blk_bs(blk), req, buf);
69
}
70
71
-int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf)
72
+int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req,
73
+ void *buf)
74
{
75
int ret;
76
IO_OR_GS_CODE();
77
78
blk_inc_in_flight(blk);
79
- ret = blk_do_ioctl(blk, req, buf);
80
+ ret = blk_co_do_ioctl(blk, req, buf);
81
blk_dec_in_flight(blk);
82
83
return ret;
84
--
64
--
85
2.35.3
65
2.9.3
66
67
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
3
Keep the coroutine on the same AioContext. Without this change,
4
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
4
there would be a race between yielding the coroutine and reentering it.
5
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
While the race cannot happen now, because the code only runs from a single
6
Message-Id: <20220705161527.1054072-15-afaria@redhat.com>
6
AioContext, this will change with multiqueue support in the block layer.
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
8
While doing the change, replace custom bottom half with aio_co_schedule.
9
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
Reviewed-by: Fam Zheng <famz@redhat.com>
12
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
13
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
14
Message-id: 20170213135235.12274-10-pbonzini@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
16
---
9
block/coroutines.h | 2 --
17
block/blkdebug.c | 9 +--------
10
include/sysemu/block-backend-io.h | 2 +-
18
1 file changed, 1 insertion(+), 8 deletions(-)
11
block/block-backend.c | 11 -----------
12
3 files changed, 1 insertion(+), 14 deletions(-)
13
19
14
diff --git a/block/coroutines.h b/block/coroutines.h
20
diff --git a/block/blkdebug.c b/block/blkdebug.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/block/coroutines.h
22
--- a/block/blkdebug.c
17
+++ b/block/coroutines.h
23
+++ b/block/blkdebug.c
18
@@ -XXX,XX +XXX,XX @@ nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
24
@@ -XXX,XX +XXX,XX @@ out:
19
int generated_co_wrapper
20
blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
21
22
-int generated_co_wrapper blk_do_flush(BlockBackend *blk);
23
-
24
#endif /* BLOCK_COROUTINES_H */
25
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/sysemu/block-backend-io.h
28
+++ b/include/sysemu/block-backend-io.h
29
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pdiscard(BlockBackend *blk, int64_t offset,
30
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
31
int64_t bytes);
32
33
+int generated_co_wrapper blk_flush(BlockBackend *blk);
34
int coroutine_fn blk_co_flush(BlockBackend *blk);
35
-int blk_flush(BlockBackend *blk);
36
37
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
38
39
diff --git a/block/block-backend.c b/block/block-backend.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/block/block-backend.c
42
+++ b/block/block-backend.c
43
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_flush(BlockBackend *blk)
44
return ret;
25
return ret;
45
}
26
}
46
27
47
-int blk_flush(BlockBackend *blk)
28
-static void error_callback_bh(void *opaque)
48
-{
29
-{
49
- int ret;
30
- Coroutine *co = opaque;
50
-
31
- qemu_coroutine_enter(co);
51
- blk_inc_in_flight(blk);
52
- ret = blk_do_flush(blk);
53
- blk_dec_in_flight(blk);
54
-
55
- return ret;
56
-}
32
-}
57
-
33
-
58
void blk_drain(BlockBackend *blk)
34
static int inject_error(BlockDriverState *bs, BlkdebugRule *rule)
59
{
35
{
60
BlockDriverState *bs = blk_bs(blk);
36
BDRVBlkdebugState *s = bs->opaque;
37
@@ -XXX,XX +XXX,XX @@ static int inject_error(BlockDriverState *bs, BlkdebugRule *rule)
38
}
39
40
if (!immediately) {
41
- aio_bh_schedule_oneshot(bdrv_get_aio_context(bs), error_callback_bh,
42
- qemu_coroutine_self());
43
+ aio_co_schedule(qemu_get_current_aio_context(), qemu_coroutine_self());
44
qemu_coroutine_yield();
45
}
46
61
--
47
--
62
2.35.3
48
2.9.3
49
50
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Implement blk_preadv_part() using generated_co_wrapper.
3
qed_aio_start_io and qed_aio_next_io will not have to acquire/release
4
the AioContext, while qed_aio_next_io_cb will. Split the functionality
5
and gain a little type-safety in the process.
4
6
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
9
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Message-Id: <20220705161527.1054072-9-afaria@redhat.com>
10
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20170213135235.12274-11-pbonzini@redhat.com
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
13
---
11
block/coroutines.h | 5 -----
14
block/qed.c | 39 +++++++++++++++++++++++++--------------
12
include/sysemu/block-backend-io.h | 7 +++++++
15
1 file changed, 25 insertions(+), 14 deletions(-)
13
block/block-backend.c | 30 +++++++++++++++++++++++-------
14
tests/unit/test-block-iothread.c | 19 +++++++++++++++++++
15
4 files changed, 49 insertions(+), 12 deletions(-)
16
16
17
diff --git a/block/coroutines.h b/block/coroutines.h
17
diff --git a/block/qed.c b/block/qed.c
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/coroutines.h
19
--- a/block/qed.c
20
+++ b/block/coroutines.h
20
+++ b/block/qed.c
21
@@ -XXX,XX +XXX,XX @@ nbd_co_do_establish_connection(BlockDriverState *bs, bool blocking,
21
@@ -XXX,XX +XXX,XX @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
22
Error **errp);
22
return l2_table;
23
24
25
-int coroutine_fn
26
-blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
27
- QEMUIOVector *qiov, BdrvRequestFlags flags);
28
-
29
-
30
int coroutine_fn
31
blk_co_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
32
QEMUIOVector *qiov, size_t qiov_offset,
33
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/sysemu/block-backend-io.h
36
+++ b/include/sysemu/block-backend-io.h
37
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pread(BlockBackend *blk, int64_t offset,
38
int generated_co_wrapper blk_pwrite(BlockBackend *blk, int64_t offset,
39
int64_t bytes, const void *buf,
40
BdrvRequestFlags flags);
41
+int generated_co_wrapper blk_preadv_part(BlockBackend *blk, int64_t offset,
42
+ int64_t bytes, QEMUIOVector *qiov,
43
+ size_t qiov_offset,
44
+ BdrvRequestFlags flags);
45
+int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
46
+ int64_t bytes, QEMUIOVector *qiov,
47
+ size_t qiov_offset, BdrvRequestFlags flags);
48
int generated_co_wrapper blk_preadv(BlockBackend *blk, int64_t offset,
49
int64_t bytes, QEMUIOVector *qiov,
50
BdrvRequestFlags flags);
51
diff --git a/block/block-backend.c b/block/block-backend.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/block/block-backend.c
54
+++ b/block/block-backend.c
55
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn blk_wait_while_drained(BlockBackend *blk)
56
}
23
}
57
24
58
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
25
-static void qed_aio_next_io(void *opaque, int ret);
59
-int coroutine_fn
26
+static void qed_aio_next_io(QEDAIOCB *acb, int ret);
60
-blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
61
- QEMUIOVector *qiov, BdrvRequestFlags flags)
62
+static int coroutine_fn
63
+blk_co_do_preadv_part(BlockBackend *blk, int64_t offset, int64_t bytes,
64
+ QEMUIOVector *qiov, size_t qiov_offset,
65
+ BdrvRequestFlags flags)
66
{
67
int ret;
68
BlockDriverState *bs;
69
@@ -XXX,XX +XXX,XX @@ blk_co_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
70
bytes, false);
71
}
72
73
- ret = bdrv_co_preadv(blk->root, offset, bytes, qiov, flags);
74
+ ret = bdrv_co_preadv_part(blk->root, offset, bytes, qiov, qiov_offset,
75
+ flags);
76
bdrv_dec_in_flight(bs);
77
return ret;
78
}
79
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
80
IO_OR_GS_CODE();
81
82
blk_inc_in_flight(blk);
83
- ret = blk_co_do_preadv(blk, offset, bytes, qiov, flags);
84
+ ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, 0, flags);
85
+ blk_dec_in_flight(blk);
86
+
27
+
87
+ return ret;
28
+static void qed_aio_start_io(QEDAIOCB *acb)
29
+{
30
+ qed_aio_next_io(acb, 0);
88
+}
31
+}
89
+
32
+
90
+int coroutine_fn blk_co_preadv_part(BlockBackend *blk, int64_t offset,
33
+static void qed_aio_next_io_cb(void *opaque, int ret)
91
+ int64_t bytes, QEMUIOVector *qiov,
92
+ size_t qiov_offset, BdrvRequestFlags flags)
93
+{
34
+{
94
+ int ret;
35
+ QEDAIOCB *acb = opaque;
95
+ IO_OR_GS_CODE();
96
+
36
+
97
+ blk_inc_in_flight(blk);
37
+ qed_aio_next_io(acb, ret);
98
+ ret = blk_co_do_preadv_part(blk, offset, bytes, qiov, qiov_offset, flags);
38
+}
99
blk_dec_in_flight(blk);
39
100
40
static void qed_plug_allocating_write_reqs(BDRVQEDState *s)
101
return ret;
41
{
102
@@ -XXX,XX +XXX,XX @@ static void blk_aio_read_entry(void *opaque)
42
@@ -XXX,XX +XXX,XX @@ static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
103
QEMUIOVector *qiov = rwco->iobuf;
43
104
44
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
105
assert(qiov->size == acb->bytes);
45
if (acb) {
106
- rwco->ret = blk_co_do_preadv(rwco->blk, rwco->offset, acb->bytes,
46
- qed_aio_next_io(acb, 0);
107
- qiov, rwco->flags);
47
+ qed_aio_start_io(acb);
108
+ rwco->ret = blk_co_do_preadv_part(rwco->blk, rwco->offset, acb->bytes, qiov,
48
}
109
+ 0, rwco->flags);
110
blk_aio_complete(acb);
111
}
49
}
112
50
113
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
51
@@ -XXX,XX +XXX,XX @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
114
index XXXXXXX..XXXXXXX 100644
52
QSIMPLEQ_REMOVE_HEAD(&s->allocating_write_reqs, next);
115
--- a/tests/unit/test-block-iothread.c
53
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
116
+++ b/tests/unit/test-block-iothread.c
54
if (acb) {
117
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwritev(BlockBackend *blk)
55
- qed_aio_next_io(acb, 0);
118
g_assert_cmpint(ret, ==, -EIO);
56
+ qed_aio_start_io(acb);
57
} else if (s->header.features & QED_F_NEED_CHECK) {
58
qed_start_need_check_timer(s);
59
}
60
@@ -XXX,XX +XXX,XX @@ static void qed_commit_l2_update(void *opaque, int ret)
61
acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
62
assert(acb->request.l2_table != NULL);
63
64
- qed_aio_next_io(opaque, ret);
65
+ qed_aio_next_io(acb, ret);
119
}
66
}
120
67
121
+static void test_sync_op_blk_preadv_part(BlockBackend *blk)
68
/**
122
+{
69
@@ -XXX,XX +XXX,XX @@ static void qed_aio_write_l2_update(QEDAIOCB *acb, int ret, uint64_t offset)
123
+ uint8_t buf[512];
70
if (need_alloc) {
124
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, sizeof(buf));
71
/* Write out the whole new L2 table */
125
+ int ret;
72
qed_write_l2_table(s, &acb->request, 0, s->table_nelems, true,
126
+
73
- qed_aio_write_l1_update, acb);
127
+ /* Success */
74
+ qed_aio_write_l1_update, acb);
128
+ ret = blk_preadv_part(blk, 0, sizeof(buf), &qiov, 0, 0);
75
} else {
129
+ g_assert_cmpint(ret, ==, 0);
76
/* Write out only the updated part of the L2 table */
130
+
77
qed_write_l2_table(s, &acb->request, index, acb->cur_nclusters, false,
131
+ /* Early error: Negative offset */
78
- qed_aio_next_io, acb);
132
+ ret = blk_preadv_part(blk, -2, sizeof(buf), &qiov, 0, 0);
79
+ qed_aio_next_io_cb, acb);
133
+ g_assert_cmpint(ret, ==, -EIO);
80
}
134
+}
81
return;
135
+
82
136
static void test_sync_op_load_vmstate(BdrvChild *c)
83
@@ -XXX,XX +XXX,XX @@ static void qed_aio_write_main(void *opaque, int ret)
84
}
85
86
if (acb->find_cluster_ret == QED_CLUSTER_FOUND) {
87
- next_fn = qed_aio_next_io;
88
+ next_fn = qed_aio_next_io_cb;
89
} else {
90
if (s->bs->backing) {
91
next_fn = qed_aio_write_flush_before_l2_update;
92
@@ -XXX,XX +XXX,XX @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
93
if (acb->flags & QED_AIOCB_ZERO) {
94
/* Skip ahead if the clusters are already zero */
95
if (acb->find_cluster_ret == QED_CLUSTER_ZERO) {
96
- qed_aio_next_io(acb, 0);
97
+ qed_aio_start_io(acb);
98
return;
99
}
100
101
@@ -XXX,XX +XXX,XX @@ static void qed_aio_read_data(void *opaque, int ret,
102
/* Handle zero cluster and backing file reads */
103
if (ret == QED_CLUSTER_ZERO) {
104
qemu_iovec_memset(&acb->cur_qiov, 0, 0, acb->cur_qiov.size);
105
- qed_aio_next_io(acb, 0);
106
+ qed_aio_start_io(acb);
107
return;
108
} else if (ret != QED_CLUSTER_FOUND) {
109
qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
110
- &acb->backing_qiov, qed_aio_next_io, acb);
111
+ &acb->backing_qiov, qed_aio_next_io_cb, acb);
112
return;
113
}
114
115
BLKDBG_EVENT(bs->file, BLKDBG_READ_AIO);
116
bdrv_aio_readv(bs->file, offset / BDRV_SECTOR_SIZE,
117
&acb->cur_qiov, acb->cur_qiov.size / BDRV_SECTOR_SIZE,
118
- qed_aio_next_io, acb);
119
+ qed_aio_next_io_cb, acb);
120
return;
121
122
err:
123
@@ -XXX,XX +XXX,XX @@ err:
124
/**
125
* Begin next I/O or complete the request
126
*/
127
-static void qed_aio_next_io(void *opaque, int ret)
128
+static void qed_aio_next_io(QEDAIOCB *acb, int ret)
137
{
129
{
138
uint8_t buf[512];
130
- QEDAIOCB *acb = opaque;
139
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
131
BDRVQEDState *s = acb_to_s(acb);
140
.name = "/sync-op/pwritev",
132
QEDFindClusterFunc *io_fn = (acb->flags & QED_AIOCB_WRITE) ?
141
.fn = NULL,
133
qed_aio_write_data : qed_aio_read_data;
142
.blkfn = test_sync_op_blk_pwritev,
134
@@ -XXX,XX +XXX,XX @@ static BlockAIOCB *qed_aio_setup(BlockDriverState *bs,
143
+ }, {
135
qemu_iovec_init(&acb->cur_qiov, qiov->niov);
144
+ .name = "/sync-op/preadv_part",
136
145
+ .fn = NULL,
137
/* Start request */
146
+ .blkfn = test_sync_op_blk_preadv_part,
138
- qed_aio_next_io(acb, 0);
147
}, {
139
+ qed_aio_start_io(acb);
148
.name = "/sync-op/load_vmstate",
140
return &acb->common;
149
.fn = test_sync_op_load_vmstate,
141
}
142
150
--
143
--
151
2.35.3
144
2.9.3
145
146
diff view generated by jsdifflib
1
After writing the PID file, we register an atexit() handler to unlink it
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
when the process terminates. However, if the process has changed its
3
working directory in the meantime (e.g. in os_setup_post() when
4
daemonizing), this will not work when the PID file path was relative.
5
Therefore, pass the absolute path (created with realpath()) to the
6
unlink() call in the atexit() handler.
7
2
8
(realpath() needs a path pointing to an existing file, so we cannot use
3
The AioContext data structures are now protected by list_lock and/or
9
it before qemu_write_pidfile().)
4
they are walked with FOREACH_RCU primitives. There is no need anymore
5
to acquire the AioContext for the entire duration of aio_dispatch.
6
Instead, just acquire it before and after invoking the callbacks.
7
The next step is then to push it further down.
10
8
11
Reproducer:
9
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
12
$ cd /tmp
10
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
13
$ qemu-storage-daemon --daemonize --pidfile qsd.pid
11
Reviewed-by: Fam Zheng <famz@redhat.com>
14
$ file qsd.pid
12
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
15
qsd.pid: ASCII text
13
Message-id: 20170213135235.12274-12-pbonzini@redhat.com
16
$ kill $(cat qsd.pid)
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
$ file qsd.pid
15
---
18
qsd.pid: ASCII text
16
util/aio-posix.c | 25 +++++++++++--------------
17
util/aio-win32.c | 15 +++++++--------
18
util/async.c | 2 ++
19
3 files changed, 20 insertions(+), 22 deletions(-)
19
20
20
(qsd.pid should be gone after the process has terminated.)
21
diff --git a/util/aio-posix.c b/util/aio-posix.c
21
22
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2092322
23
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
24
Message-Id: <20220609122701.17172-2-hreitz@redhat.com>
25
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
26
---
27
storage-daemon/qemu-storage-daemon.c | 11 ++++++++++-
28
1 file changed, 10 insertions(+), 1 deletion(-)
29
30
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
31
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
32
--- a/storage-daemon/qemu-storage-daemon.c
23
--- a/util/aio-posix.c
33
+++ b/storage-daemon/qemu-storage-daemon.c
24
+++ b/util/aio-posix.c
34
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
35
#include "trace/control.h"
26
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
36
27
aio_node_check(ctx, node->is_external) &&
37
static const char *pid_file;
28
node->io_read) {
38
+static char *pid_file_realpath;
29
+ aio_context_acquire(ctx);
39
static volatile bool exit_requested = false;
30
node->io_read(node->opaque);
40
31
+ aio_context_release(ctx);
41
void qemu_system_killed(int signal, pid_t pid)
32
42
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[], bool pre_init_pass)
33
/* aio_notify() does not count as progress */
43
34
if (node->opaque != &ctx->notifier) {
44
static void pid_file_cleanup(void)
35
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
45
{
36
(revents & (G_IO_OUT | G_IO_ERR)) &&
46
- unlink(pid_file);
37
aio_node_check(ctx, node->is_external) &&
47
+ unlink(pid_file_realpath);
38
node->io_write) {
39
+ aio_context_acquire(ctx);
40
node->io_write(node->opaque);
41
+ aio_context_release(ctx);
42
progress = true;
43
}
44
45
@@ -XXX,XX +XXX,XX @@ bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
46
}
47
48
/* Run our timers */
49
+ aio_context_acquire(ctx);
50
progress |= timerlistgroup_run_timers(&ctx->tlg);
51
+ aio_context_release(ctx);
52
53
return progress;
48
}
54
}
49
55
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
50
static void pid_file_init(void)
56
int64_t timeout;
51
@@ -XXX,XX +XXX,XX @@ static void pid_file_init(void)
57
int64_t start = 0;
52
exit(EXIT_FAILURE);
58
59
- aio_context_acquire(ctx);
60
- progress = false;
61
-
62
/* aio_notify can avoid the expensive event_notifier_set if
63
* everything (file descriptors, bottom halves, timers) will
64
* be re-evaluated before the next blocking poll(). This is
65
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
66
start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
53
}
67
}
54
68
55
+ pid_file_realpath = g_malloc(PATH_MAX);
69
- if (try_poll_mode(ctx, blocking)) {
56
+ if (!realpath(pid_file, pid_file_realpath)) {
70
- progress = true;
57
+ error_report("cannot resolve PID file path: %s: %s",
71
- } else {
58
+ pid_file, strerror(errno));
72
+ aio_context_acquire(ctx);
59
+ unlink(pid_file);
73
+ progress = try_poll_mode(ctx, blocking);
60
+ exit(EXIT_FAILURE);
74
+ aio_context_release(ctx);
61
+ }
62
+
75
+
63
atexit(pid_file_cleanup);
76
+ if (!progress) {
77
assert(npfd == 0);
78
79
/* fill pollfds */
80
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
81
timeout = blocking ? aio_compute_timeout(ctx) : 0;
82
83
/* wait until next event */
84
- if (timeout) {
85
- aio_context_release(ctx);
86
- }
87
if (aio_epoll_check_poll(ctx, pollfds, npfd, timeout)) {
88
AioHandler epoll_handler;
89
90
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
91
} else {
92
ret = qemu_poll_ns(pollfds, npfd, timeout);
93
}
94
- if (timeout) {
95
- aio_context_acquire(ctx);
96
- }
97
}
98
99
if (blocking) {
100
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
101
progress = true;
102
}
103
104
- aio_context_release(ctx);
105
-
106
return progress;
64
}
107
}
65
108
109
diff --git a/util/aio-win32.c b/util/aio-win32.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/util/aio-win32.c
112
+++ b/util/aio-win32.c
113
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
114
(revents || event_notifier_get_handle(node->e) == event) &&
115
node->io_notify) {
116
node->pfd.revents = 0;
117
+ aio_context_acquire(ctx);
118
node->io_notify(node->e);
119
+ aio_context_release(ctx);
120
121
/* aio_notify() does not count as progress */
122
if (node->e != &ctx->notifier) {
123
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
124
(node->io_read || node->io_write)) {
125
node->pfd.revents = 0;
126
if ((revents & G_IO_IN) && node->io_read) {
127
+ aio_context_acquire(ctx);
128
node->io_read(node->opaque);
129
+ aio_context_release(ctx);
130
progress = true;
131
}
132
if ((revents & G_IO_OUT) && node->io_write) {
133
+ aio_context_acquire(ctx);
134
node->io_write(node->opaque);
135
+ aio_context_release(ctx);
136
progress = true;
137
}
138
139
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
140
int count;
141
int timeout;
142
143
- aio_context_acquire(ctx);
144
progress = false;
145
146
/* aio_notify can avoid the expensive event_notifier_set if
147
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
148
149
timeout = blocking && !have_select_revents
150
? qemu_timeout_ns_to_ms(aio_compute_timeout(ctx)) : 0;
151
- if (timeout) {
152
- aio_context_release(ctx);
153
- }
154
ret = WaitForMultipleObjects(count, events, FALSE, timeout);
155
if (blocking) {
156
assert(first);
157
atomic_sub(&ctx->notify_me, 2);
158
}
159
- if (timeout) {
160
- aio_context_acquire(ctx);
161
- }
162
163
if (first) {
164
aio_notify_accept(ctx);
165
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
166
progress |= aio_dispatch_handlers(ctx, event);
167
} while (count > 0);
168
169
+ aio_context_acquire(ctx);
170
progress |= timerlistgroup_run_timers(&ctx->tlg);
171
-
172
aio_context_release(ctx);
173
return progress;
174
}
175
diff --git a/util/async.c b/util/async.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/util/async.c
178
+++ b/util/async.c
179
@@ -XXX,XX +XXX,XX @@ int aio_bh_poll(AioContext *ctx)
180
ret = 1;
181
}
182
bh->idle = 0;
183
+ aio_context_acquire(ctx);
184
aio_bh_call(bh);
185
+ aio_context_release(ctx);
186
}
187
if (bh->deleted) {
188
deleted = true;
66
--
189
--
67
2.35.3
190
2.9.3
68
191
69
192
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
They currently return the value of their 'bytes' parameter on success.
4
5
Make them return 0 instead, for consistency with other I/O functions and
6
in preparation to implement them using generated_co_wrapper. This also
7
makes it clear that short reads/writes are not possible.
8
9
The few callers that rely on the previous behavior are adjusted
10
accordingly by hand.
11
12
Signed-off-by: Alberto Faria <afaria@redhat.com>
13
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
14
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
15
Message-Id: <20220609152744.3891847-4-afaria@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
16
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
Reviewed-by: Fam Zheng <famz@redhat.com>
17
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
6
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7
Message-id: 20170213135235.12274-13-pbonzini@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
18
---
9
---
19
block/cloop.c | 2 +-
10
block/qed.h | 3 +++
20
block/crypto.c | 4 ++--
11
block/curl.c | 2 ++
21
block/dmg.c | 10 +++++-----
12
block/io.c | 5 +++++
22
block/io.c | 10 ++--------
13
block/iscsi.c | 8 ++++++--
23
block/qcow.c | 2 +-
14
block/null.c | 4 ++++
24
block/qcow2.c | 4 ++--
15
block/qed.c | 12 ++++++++++++
25
block/qed.c | 7 +------
16
block/throttle-groups.c | 2 ++
26
block/vdi.c | 2 +-
17
util/aio-posix.c | 2 --
27
block/vmdk.c | 5 ++---
18
util/aio-win32.c | 2 --
28
tests/unit/test-block-iothread.c | 4 ++--
19
util/qemu-coroutine-sleep.c | 2 +-
29
10 files changed, 19 insertions(+), 31 deletions(-)
20
10 files changed, 35 insertions(+), 7 deletions(-)
30
21
31
diff --git a/block/cloop.c b/block/cloop.c
22
diff --git a/block/qed.h b/block/qed.h
32
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
33
--- a/block/cloop.c
24
--- a/block/qed.h
34
+++ b/block/cloop.c
25
+++ b/block/qed.h
35
@@ -XXX,XX +XXX,XX @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
26
@@ -XXX,XX +XXX,XX @@ enum {
36
27
*/
37
ret = bdrv_pread(bs->file, s->offsets[block_num], bytes,
28
typedef void QEDFindClusterFunc(void *opaque, int ret, uint64_t offset, size_t len);
38
s->compressed_block, 0);
29
39
- if (ret != bytes) {
30
+void qed_acquire(BDRVQEDState *s);
40
+ if (ret < 0) {
31
+void qed_release(BDRVQEDState *s);
41
return -1;
32
+
42
}
33
/**
43
34
* Generic callback for chaining async callbacks
44
diff --git a/block/crypto.c b/block/crypto.c
35
*/
45
index XXXXXXX..XXXXXXX 100644
36
diff --git a/block/curl.c b/block/curl.c
46
--- a/block/crypto.c
37
index XXXXXXX..XXXXXXX 100644
47
+++ b/block/crypto.c
38
--- a/block/curl.c
48
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
39
+++ b/block/curl.c
49
error_setg_errno(errp, -ret, "Could not read encryption header");
40
@@ -XXX,XX +XXX,XX @@ static void curl_multi_timeout_do(void *arg)
50
return ret;
41
return;
51
}
42
}
52
- return ret;
43
53
+ return buflen;
44
+ aio_context_acquire(s->aio_context);
54
}
45
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
55
46
56
static ssize_t block_crypto_write_func(QCryptoBlock *block,
47
curl_multi_check_completion(s);
57
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
48
+ aio_context_release(s->aio_context);
58
error_setg_errno(errp, -ret, "Could not write encryption header");
49
#else
59
return ret;
50
abort();
60
}
51
#endif
61
- return ret;
62
+ return buflen;
63
}
64
65
66
diff --git a/block/dmg.c b/block/dmg.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/dmg.c
69
+++ b/block/dmg.c
70
@@ -XXX,XX +XXX,XX @@ static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
71
buffer = g_malloc(info_length + 1);
72
buffer[info_length] = '\0';
73
ret = bdrv_pread(bs->file, info_begin, info_length, buffer, 0);
74
- if (ret != info_length) {
75
+ if (ret < 0) {
76
ret = -EINVAL;
77
goto fail;
78
}
79
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
80
* inflated. */
81
ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
82
s->compressed_chunk, 0);
83
- if (ret != s->lengths[chunk]) {
84
+ if (ret < 0) {
85
return -1;
86
}
87
88
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
89
* inflated. */
90
ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
91
s->compressed_chunk, 0);
92
- if (ret != s->lengths[chunk]) {
93
+ if (ret < 0) {
94
return -1;
95
}
96
97
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
98
* inflated. */
99
ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
100
s->compressed_chunk, 0);
101
- if (ret != s->lengths[chunk]) {
102
+ if (ret < 0) {
103
return -1;
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
107
case UDRW: /* copy */
108
ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
109
s->uncompressed_chunk, 0);
110
- if (ret != s->lengths[chunk]) {
111
+ if (ret < 0) {
112
return -1;
113
}
114
break;
115
diff --git a/block/io.c b/block/io.c
52
diff --git a/block/io.c b/block/io.c
116
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
117
--- a/block/io.c
54
--- a/block/io.c
118
+++ b/block/io.c
55
+++ b/block/io.c
119
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
56
@@ -XXX,XX +XXX,XX @@ void bdrv_aio_cancel(BlockAIOCB *acb)
120
int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
57
if (acb->aiocb_info->get_aio_context) {
121
BdrvRequestFlags flags)
58
aio_poll(acb->aiocb_info->get_aio_context(acb), true);
59
} else if (acb->bs) {
60
+ /* qemu_aio_ref and qemu_aio_unref are not thread-safe, so
61
+ * assert that we're not using an I/O thread. Thread-safe
62
+ * code should use bdrv_aio_cancel_async exclusively.
63
+ */
64
+ assert(bdrv_get_aio_context(acb->bs) == qemu_get_aio_context());
65
aio_poll(bdrv_get_aio_context(acb->bs), true);
66
} else {
67
abort();
68
diff --git a/block/iscsi.c b/block/iscsi.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/block/iscsi.c
71
+++ b/block/iscsi.c
72
@@ -XXX,XX +XXX,XX @@ static void iscsi_retry_timer_expired(void *opaque)
73
struct IscsiTask *iTask = opaque;
74
iTask->complete = 1;
75
if (iTask->co) {
76
- qemu_coroutine_enter(iTask->co);
77
+ aio_co_wake(iTask->co);
78
}
79
}
80
81
@@ -XXX,XX +XXX,XX @@ static void iscsi_nop_timed_event(void *opaque)
122
{
82
{
123
- int ret;
83
IscsiLun *iscsilun = opaque;
124
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
84
125
IO_CODE();
85
+ aio_context_acquire(iscsilun->aio_context);
126
86
if (iscsi_get_nops_in_flight(iscsilun->iscsi) >= MAX_NOP_FAILURES) {
127
@@ -XXX,XX +XXX,XX @@ int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
87
error_report("iSCSI: NOP timeout. Reconnecting...");
128
return -EINVAL;
88
iscsilun->request_timed_out = true;
129
}
89
} else if (iscsi_nop_out_async(iscsilun->iscsi, NULL, NULL, 0, NULL) != 0) {
130
90
error_report("iSCSI: failed to sent NOP-Out. Disabling NOP messages.");
131
- ret = bdrv_preadv(child, offset, bytes, &qiov, flags);
91
- return;
132
-
92
+ goto out;
133
- return ret < 0 ? ret : bytes;
93
}
134
+ return bdrv_preadv(child, offset, bytes, &qiov, flags);
94
135
}
95
timer_mod(iscsilun->nop_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
136
96
iscsi_set_events(iscsilun);
137
/* Return no. of bytes on success or < 0 on error. Important errors are:
97
+
138
@@ -XXX,XX +XXX,XX @@ int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
98
+out:
139
int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
99
+ aio_context_release(iscsilun->aio_context);
140
const void *buf, BdrvRequestFlags flags)
100
}
101
102
static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
103
diff --git a/block/null.c b/block/null.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/null.c
106
+++ b/block/null.c
107
@@ -XXX,XX +XXX,XX @@ static void null_bh_cb(void *opaque)
108
static void null_timer_cb(void *opaque)
141
{
109
{
142
- int ret;
110
NullAIOCB *acb = opaque;
143
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
111
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
144
IO_CODE();
112
+
145
113
+ aio_context_acquire(ctx);
146
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
114
acb->common.cb(acb->common.opaque, 0);
147
return -EINVAL;
115
+ aio_context_release(ctx);
148
}
116
timer_deinit(&acb->timer);
149
117
qemu_aio_unref(acb);
150
- ret = bdrv_pwritev(child, offset, bytes, &qiov, flags);
118
}
151
-
152
- return ret < 0 ? ret : bytes;
153
+ return bdrv_pwritev(child, offset, bytes, &qiov, flags);
154
}
155
156
/*
157
diff --git a/block/qcow.c b/block/qcow.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/block/qcow.c
160
+++ b/block/qcow.c
161
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
162
csize &= (s->cluster_size - 1);
163
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
164
ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
165
- if (ret != csize)
166
+ if (ret < 0)
167
return -1;
168
if (decompress_buffer(s->cluster_cache, s->cluster_size,
169
s->cluster_data, csize) < 0) {
170
diff --git a/block/qcow2.c b/block/qcow2.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/block/qcow2.c
173
+++ b/block/qcow2.c
174
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
175
error_setg_errno(errp, -ret, "Could not read encryption header");
176
return -1;
177
}
178
- return ret;
179
+ return buflen;
180
}
181
182
183
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
184
error_setg_errno(errp, -ret, "Could not read encryption header");
185
return -1;
186
}
187
- return ret;
188
+ return buflen;
189
}
190
191
static QDict*
192
diff --git a/block/qed.c b/block/qed.c
119
diff --git a/block/qed.c b/block/qed.c
193
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
194
--- a/block/qed.c
121
--- a/block/qed.c
195
+++ b/block/qed.c
122
+++ b/block/qed.c
196
@@ -XXX,XX +XXX,XX @@ static void qed_header_cpu_to_le(const QEDHeader *cpu, QEDHeader *le)
123
@@ -XXX,XX +XXX,XX @@ static void qed_need_check_timer_cb(void *opaque)
197
int qed_write_header_sync(BDRVQEDState *s)
124
125
trace_qed_need_check_timer_cb(s);
126
127
+ qed_acquire(s);
128
qed_plug_allocating_write_reqs(s);
129
130
/* Ensure writes are on disk before clearing flag */
131
bdrv_aio_flush(s->bs->file->bs, qed_clear_need_check, s);
132
+ qed_release(s);
133
+}
134
+
135
+void qed_acquire(BDRVQEDState *s)
136
+{
137
+ aio_context_acquire(bdrv_get_aio_context(s->bs));
138
+}
139
+
140
+void qed_release(BDRVQEDState *s)
141
+{
142
+ aio_context_release(bdrv_get_aio_context(s->bs));
143
}
144
145
static void qed_start_need_check_timer(BDRVQEDState *s)
146
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/block/throttle-groups.c
149
+++ b/block/throttle-groups.c
150
@@ -XXX,XX +XXX,XX @@ static void timer_cb(BlockBackend *blk, bool is_write)
151
qemu_mutex_unlock(&tg->lock);
152
153
/* Run the request that was waiting for this timer */
154
+ aio_context_acquire(blk_get_aio_context(blk));
155
empty_queue = !qemu_co_enter_next(&blkp->throttled_reqs[is_write]);
156
+ aio_context_release(blk_get_aio_context(blk));
157
158
/* If the request queue was empty then we have to take care of
159
* scheduling the next one */
160
diff --git a/util/aio-posix.c b/util/aio-posix.c
161
index XXXXXXX..XXXXXXX 100644
162
--- a/util/aio-posix.c
163
+++ b/util/aio-posix.c
164
@@ -XXX,XX +XXX,XX @@ bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
165
}
166
167
/* Run our timers */
168
- aio_context_acquire(ctx);
169
progress |= timerlistgroup_run_timers(&ctx->tlg);
170
- aio_context_release(ctx);
171
172
return progress;
173
}
174
diff --git a/util/aio-win32.c b/util/aio-win32.c
175
index XXXXXXX..XXXXXXX 100644
176
--- a/util/aio-win32.c
177
+++ b/util/aio-win32.c
178
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
179
progress |= aio_dispatch_handlers(ctx, event);
180
} while (count > 0);
181
182
- aio_context_acquire(ctx);
183
progress |= timerlistgroup_run_timers(&ctx->tlg);
184
- aio_context_release(ctx);
185
return progress;
186
}
187
188
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c
189
index XXXXXXX..XXXXXXX 100644
190
--- a/util/qemu-coroutine-sleep.c
191
+++ b/util/qemu-coroutine-sleep.c
192
@@ -XXX,XX +XXX,XX @@ static void co_sleep_cb(void *opaque)
198
{
193
{
199
QEDHeader le;
194
CoSleepCB *sleep_cb = opaque;
200
- int ret;
195
201
196
- qemu_coroutine_enter(sleep_cb->co);
202
qed_header_cpu_to_le(&s->header, &le);
197
+ aio_co_wake(sleep_cb->co);
203
- ret = bdrv_pwrite(s->bs->file, 0, sizeof(le), &le, 0);
198
}
204
- if (ret != sizeof(le)) {
199
205
- return ret;
200
void coroutine_fn co_aio_sleep_ns(AioContext *ctx, QEMUClockType type,
206
- }
207
- return 0;
208
+ return bdrv_pwrite(s->bs->file, 0, sizeof(le), &le, 0);
209
}
210
211
/**
212
diff --git a/block/vdi.c b/block/vdi.c
213
index XXXXXXX..XXXXXXX 100644
214
--- a/block/vdi.c
215
+++ b/block/vdi.c
216
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
217
n_sectors * SECTOR_SIZE, base, 0);
218
}
219
220
- return ret < 0 ? ret : 0;
221
+ return ret;
222
}
223
224
static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
225
diff --git a/block/vmdk.c b/block/vmdk.c
226
index XXXXXXX..XXXXXXX 100644
227
--- a/block/vmdk.c
228
+++ b/block/vmdk.c
229
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
230
if (ret < 0) {
231
goto out;
232
}
233
- ret = 0;
234
235
p_name = strstr(desc, "parentFileNameHint");
236
if (p_name != NULL) {
237
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
238
g_free(buf);
239
return NULL;
240
}
241
- buf[ret] = 0;
242
+ buf[size] = 0;
243
244
return buf;
245
}
246
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
247
l2_size_bytes,
248
l2_table,
249
0
250
- ) != l2_size_bytes) {
251
+ ) < 0) {
252
return VMDK_ERROR;
253
}
254
255
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
256
index XXXXXXX..XXXXXXX 100644
257
--- a/tests/unit/test-block-iothread.c
258
+++ b/tests/unit/test-block-iothread.c
259
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pread(BdrvChild *c)
260
261
/* Success */
262
ret = bdrv_pread(c, 0, sizeof(buf), buf, 0);
263
- g_assert_cmpint(ret, ==, 512);
264
+ g_assert_cmpint(ret, ==, 0);
265
266
/* Early error: Negative offset */
267
ret = bdrv_pread(c, -2, sizeof(buf), buf, 0);
268
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pwrite(BdrvChild *c)
269
270
/* Success */
271
ret = bdrv_pwrite(c, 0, sizeof(buf), buf, 0);
272
- g_assert_cmpint(ret, ==, 512);
273
+ g_assert_cmpint(ret, ==, 0);
274
275
/* Early error: Negative offset */
276
ret = bdrv_pwrite(c, -2, sizeof(buf), buf, 0);
277
--
201
--
278
2.35.3
202
2.9.3
203
204
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
3
This covers both file descriptor callbacks and polling callbacks,
4
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
4
since they execute related code.
5
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
6
Message-Id: <20220705161527.1054072-13-afaria@redhat.com>
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
10
Message-id: 20170213135235.12274-14-pbonzini@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
12
---
9
include/sysemu/block-backend-io.h | 5 +++--
13
block/curl.c | 16 +++++++++++++---
10
block/block-backend.c | 8 --------
14
block/iscsi.c | 4 ++++
11
tests/unit/test-block-iothread.c | 17 +++++++++++++++++
15
block/linux-aio.c | 4 ++++
12
3 files changed, 20 insertions(+), 10 deletions(-)
16
block/nfs.c | 6 ++++++
17
block/sheepdog.c | 29 +++++++++++++++--------------
18
block/ssh.c | 29 +++++++++--------------------
19
block/win32-aio.c | 10 ++++++----
20
hw/block/virtio-blk.c | 5 ++++-
21
hw/scsi/virtio-scsi.c | 7 +++++++
22
util/aio-posix.c | 7 -------
23
util/aio-win32.c | 6 ------
24
11 files changed, 68 insertions(+), 55 deletions(-)
13
25
14
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
26
diff --git a/block/curl.c b/block/curl.c
15
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
16
--- a/include/sysemu/block-backend-io.h
28
--- a/block/curl.c
17
+++ b/include/sysemu/block-backend-io.h
29
+++ b/block/curl.c
18
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
30
@@ -XXX,XX +XXX,XX @@ static void curl_multi_check_completion(BDRVCURLState *s)
19
int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
31
}
20
int64_t bytes, const void *buf);
32
}
21
int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
33
22
-int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
34
-static void curl_multi_do(void *arg)
23
- int64_t bytes, BdrvRequestFlags flags);
35
+static void curl_multi_do_locked(CURLState *s)
24
+int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
36
{
25
+ int64_t bytes,
37
- CURLState *s = (CURLState *)arg;
26
+ BdrvRequestFlags flags);
38
CURLSocket *socket, *next_socket;
27
int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
39
int running;
28
int64_t bytes, BdrvRequestFlags flags);
40
int r;
29
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
41
@@ -XXX,XX +XXX,XX @@ static void curl_multi_do(void *arg)
30
diff --git a/block/block-backend.c b/block/block-backend.c
42
}
31
index XXXXXXX..XXXXXXX 100644
43
}
32
--- a/block/block-backend.c
44
33
+++ b/block/block-backend.c
45
+static void curl_multi_do(void *arg)
34
@@ -XXX,XX +XXX,XX @@ typedef struct BlkRwCo {
46
+{
35
BdrvRequestFlags flags;
47
+ CURLState *s = (CURLState *)arg;
36
} BlkRwCo;
48
+
37
49
+ aio_context_acquire(s->s->aio_context);
38
-int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
50
+ curl_multi_do_locked(s);
39
- int64_t bytes, BdrvRequestFlags flags)
51
+ aio_context_release(s->s->aio_context);
52
+}
53
+
54
static void curl_multi_read(void *arg)
55
{
56
CURLState *s = (CURLState *)arg;
57
58
- curl_multi_do(arg);
59
+ aio_context_acquire(s->s->aio_context);
60
+ curl_multi_do_locked(s);
61
curl_multi_check_completion(s->s);
62
+ aio_context_release(s->s->aio_context);
63
}
64
65
static void curl_multi_timeout_do(void *arg)
66
diff --git a/block/iscsi.c b/block/iscsi.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/block/iscsi.c
69
+++ b/block/iscsi.c
70
@@ -XXX,XX +XXX,XX @@ iscsi_process_read(void *arg)
71
IscsiLun *iscsilun = arg;
72
struct iscsi_context *iscsi = iscsilun->iscsi;
73
74
+ aio_context_acquire(iscsilun->aio_context);
75
iscsi_service(iscsi, POLLIN);
76
iscsi_set_events(iscsilun);
77
+ aio_context_release(iscsilun->aio_context);
78
}
79
80
static void
81
@@ -XXX,XX +XXX,XX @@ iscsi_process_write(void *arg)
82
IscsiLun *iscsilun = arg;
83
struct iscsi_context *iscsi = iscsilun->iscsi;
84
85
+ aio_context_acquire(iscsilun->aio_context);
86
iscsi_service(iscsi, POLLOUT);
87
iscsi_set_events(iscsilun);
88
+ aio_context_release(iscsilun->aio_context);
89
}
90
91
static int64_t sector_lun2qemu(int64_t sector, IscsiLun *iscsilun)
92
diff --git a/block/linux-aio.c b/block/linux-aio.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/block/linux-aio.c
95
+++ b/block/linux-aio.c
96
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_completion_cb(EventNotifier *e)
97
LinuxAioState *s = container_of(e, LinuxAioState, e);
98
99
if (event_notifier_test_and_clear(&s->e)) {
100
+ aio_context_acquire(s->aio_context);
101
qemu_laio_process_completions_and_submit(s);
102
+ aio_context_release(s->aio_context);
103
}
104
}
105
106
@@ -XXX,XX +XXX,XX @@ static bool qemu_laio_poll_cb(void *opaque)
107
return false;
108
}
109
110
+ aio_context_acquire(s->aio_context);
111
qemu_laio_process_completions_and_submit(s);
112
+ aio_context_release(s->aio_context);
113
return true;
114
}
115
116
diff --git a/block/nfs.c b/block/nfs.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/block/nfs.c
119
+++ b/block/nfs.c
120
@@ -XXX,XX +XXX,XX @@ static void nfs_set_events(NFSClient *client)
121
static void nfs_process_read(void *arg)
122
{
123
NFSClient *client = arg;
124
+
125
+ aio_context_acquire(client->aio_context);
126
nfs_service(client->context, POLLIN);
127
nfs_set_events(client);
128
+ aio_context_release(client->aio_context);
129
}
130
131
static void nfs_process_write(void *arg)
132
{
133
NFSClient *client = arg;
134
+
135
+ aio_context_acquire(client->aio_context);
136
nfs_service(client->context, POLLOUT);
137
nfs_set_events(client);
138
+ aio_context_release(client->aio_context);
139
}
140
141
static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
142
diff --git a/block/sheepdog.c b/block/sheepdog.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/block/sheepdog.c
145
+++ b/block/sheepdog.c
146
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int send_co_req(int sockfd, SheepdogReq *hdr, void *data,
147
return ret;
148
}
149
150
-static void restart_co_req(void *opaque)
40
-{
151
-{
41
- IO_OR_GS_CODE();
152
- Coroutine *co = opaque;
42
- return blk_pwritev_part(blk, offset, bytes, NULL, 0,
153
-
43
- flags | BDRV_REQ_ZERO_WRITE);
154
- qemu_coroutine_enter(co);
44
-}
155
-}
45
-
156
-
46
int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
157
typedef struct SheepdogReqCo {
47
{
158
int sockfd;
48
GLOBAL_STATE_CODE();
159
BlockDriverState *bs;
49
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
160
@@ -XXX,XX +XXX,XX @@ typedef struct SheepdogReqCo {
50
index XXXXXXX..XXXXXXX 100644
161
unsigned int *rlen;
51
--- a/tests/unit/test-block-iothread.c
162
int ret;
52
+++ b/tests/unit/test-block-iothread.c
163
bool finished;
53
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwrite_compressed(BlockBackend *blk)
164
+ Coroutine *co;
54
g_assert_cmpint(ret, ==, -EIO);
165
} SheepdogReqCo;
55
}
166
56
167
+static void restart_co_req(void *opaque)
57
+static void test_sync_op_blk_pwrite_zeroes(BlockBackend *blk)
58
+{
168
+{
59
+ int ret;
169
+ SheepdogReqCo *srco = opaque;
60
+
170
+
61
+ /* Success */
171
+ aio_co_wake(srco->co);
62
+ ret = blk_pwrite_zeroes(blk, 0, 512, 0);
63
+ g_assert_cmpint(ret, ==, 0);
64
+
65
+ /* Early error: Negative offset */
66
+ ret = blk_pwrite_zeroes(blk, -2, 512, 0);
67
+ g_assert_cmpint(ret, ==, -EIO);
68
+}
172
+}
69
+
173
+
70
static void test_sync_op_load_vmstate(BdrvChild *c)
174
static coroutine_fn void do_co_req(void *opaque)
71
{
175
{
72
uint8_t buf[512];
176
int ret;
73
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
177
- Coroutine *co;
74
.name = "/sync-op/pwrite_compressed",
178
SheepdogReqCo *srco = opaque;
75
.fn = NULL,
179
int sockfd = srco->sockfd;
76
.blkfn = test_sync_op_blk_pwrite_compressed,
180
SheepdogReq *hdr = srco->hdr;
77
+ }, {
181
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void do_co_req(void *opaque)
78
+ .name = "/sync-op/pwrite_zeroes",
182
unsigned int *wlen = srco->wlen;
79
+ .fn = NULL,
183
unsigned int *rlen = srco->rlen;
80
+ .blkfn = test_sync_op_blk_pwrite_zeroes,
184
81
}, {
185
- co = qemu_coroutine_self();
82
.name = "/sync-op/load_vmstate",
186
+ srco->co = qemu_coroutine_self();
83
.fn = test_sync_op_load_vmstate,
187
aio_set_fd_handler(srco->aio_context, sockfd, false,
188
- NULL, restart_co_req, NULL, co);
189
+ NULL, restart_co_req, NULL, srco);
190
191
ret = send_co_req(sockfd, hdr, data, wlen);
192
if (ret < 0) {
193
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void do_co_req(void *opaque)
194
}
195
196
aio_set_fd_handler(srco->aio_context, sockfd, false,
197
- restart_co_req, NULL, NULL, co);
198
+ restart_co_req, NULL, NULL, srco);
199
200
ret = qemu_co_recv(sockfd, hdr, sizeof(*hdr));
201
if (ret != sizeof(*hdr)) {
202
@@ -XXX,XX +XXX,XX @@ out:
203
aio_set_fd_handler(srco->aio_context, sockfd, false,
204
NULL, NULL, NULL, NULL);
205
206
+ srco->co = NULL;
207
srco->ret = ret;
208
srco->finished = true;
209
if (srco->bs) {
210
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn aio_read_response(void *opaque)
211
* We've finished all requests which belong to the AIOCB, so
212
* we can switch back to sd_co_readv/writev now.
213
*/
214
- qemu_coroutine_enter(acb->coroutine);
215
+ aio_co_wake(acb->coroutine);
216
}
217
218
return;
219
@@ -XXX,XX +XXX,XX @@ static void co_read_response(void *opaque)
220
s->co_recv = qemu_coroutine_create(aio_read_response, opaque);
221
}
222
223
- qemu_coroutine_enter(s->co_recv);
224
+ aio_co_wake(s->co_recv);
225
}
226
227
static void co_write_request(void *opaque)
228
{
229
BDRVSheepdogState *s = opaque;
230
231
- qemu_coroutine_enter(s->co_send);
232
+ aio_co_wake(s->co_send);
233
}
234
235
/*
236
diff --git a/block/ssh.c b/block/ssh.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/block/ssh.c
239
+++ b/block/ssh.c
240
@@ -XXX,XX +XXX,XX @@ static void restart_coroutine(void *opaque)
241
242
DPRINTF("co=%p", co);
243
244
- qemu_coroutine_enter(co);
245
+ aio_co_wake(co);
246
}
247
248
-static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
249
+/* A non-blocking call returned EAGAIN, so yield, ensuring the
250
+ * handlers are set up so that we'll be rescheduled when there is an
251
+ * interesting event on the socket.
252
+ */
253
+static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
254
{
255
int r;
256
IOHandler *rd_handler = NULL, *wr_handler = NULL;
257
@@ -XXX,XX +XXX,XX @@ static coroutine_fn void set_fd_handler(BDRVSSHState *s, BlockDriverState *bs)
258
259
aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
260
false, rd_handler, wr_handler, NULL, co);
261
-}
262
-
263
-static coroutine_fn void clear_fd_handler(BDRVSSHState *s,
264
- BlockDriverState *bs)
265
-{
266
- DPRINTF("s->sock=%d", s->sock);
267
- aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock,
268
- false, NULL, NULL, NULL, NULL);
269
-}
270
-
271
-/* A non-blocking call returned EAGAIN, so yield, ensuring the
272
- * handlers are set up so that we'll be rescheduled when there is an
273
- * interesting event on the socket.
274
- */
275
-static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs)
276
-{
277
- set_fd_handler(s, bs);
278
qemu_coroutine_yield();
279
- clear_fd_handler(s, bs);
280
+ DPRINTF("s->sock=%d - back", s->sock);
281
+ aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, false,
282
+ NULL, NULL, NULL, NULL);
283
}
284
285
/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position
286
diff --git a/block/win32-aio.c b/block/win32-aio.c
287
index XXXXXXX..XXXXXXX 100644
288
--- a/block/win32-aio.c
289
+++ b/block/win32-aio.c
290
@@ -XXX,XX +XXX,XX @@ struct QEMUWin32AIOState {
291
HANDLE hIOCP;
292
EventNotifier e;
293
int count;
294
- bool is_aio_context_attached;
295
+ AioContext *aio_ctx;
296
};
297
298
typedef struct QEMUWin32AIOCB {
299
@@ -XXX,XX +XXX,XX @@ static void win32_aio_process_completion(QEMUWin32AIOState *s,
300
}
301
302
303
+ aio_context_acquire(s->aio_ctx);
304
waiocb->common.cb(waiocb->common.opaque, ret);
305
+ aio_context_release(s->aio_ctx);
306
qemu_aio_unref(waiocb);
307
}
308
309
@@ -XXX,XX +XXX,XX @@ void win32_aio_detach_aio_context(QEMUWin32AIOState *aio,
310
AioContext *old_context)
311
{
312
aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL);
313
- aio->is_aio_context_attached = false;
314
+ aio->aio_ctx = NULL;
315
}
316
317
void win32_aio_attach_aio_context(QEMUWin32AIOState *aio,
318
AioContext *new_context)
319
{
320
- aio->is_aio_context_attached = true;
321
+ aio->aio_ctx = new_context;
322
aio_set_event_notifier(new_context, &aio->e, false,
323
win32_aio_completion_cb, NULL);
324
}
325
@@ -XXX,XX +XXX,XX @@ out_free_state:
326
327
void win32_aio_cleanup(QEMUWin32AIOState *aio)
328
{
329
- assert(!aio->is_aio_context_attached);
330
+ assert(!aio->aio_ctx);
331
CloseHandle(aio->hIOCP);
332
event_notifier_cleanup(&aio->e);
333
g_free(aio);
334
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/hw/block/virtio-blk.c
337
+++ b/hw/block/virtio-blk.c
338
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_ioctl_complete(void *opaque, int status)
339
{
340
VirtIOBlockIoctlReq *ioctl_req = opaque;
341
VirtIOBlockReq *req = ioctl_req->req;
342
- VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
343
+ VirtIOBlock *s = req->dev;
344
+ VirtIODevice *vdev = VIRTIO_DEVICE(s);
345
struct virtio_scsi_inhdr *scsi;
346
struct sg_io_hdr *hdr;
347
348
@@ -XXX,XX +XXX,XX @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
349
MultiReqBuffer mrb = {};
350
bool progress = false;
351
352
+ aio_context_acquire(blk_get_aio_context(s->blk));
353
blk_io_plug(s->blk);
354
355
do {
356
@@ -XXX,XX +XXX,XX @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
357
}
358
359
blk_io_unplug(s->blk);
360
+ aio_context_release(blk_get_aio_context(s->blk));
361
return progress;
362
}
363
364
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
365
index XXXXXXX..XXXXXXX 100644
366
--- a/hw/scsi/virtio-scsi.c
367
+++ b/hw/scsi/virtio-scsi.c
368
@@ -XXX,XX +XXX,XX @@ bool virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
369
VirtIOSCSIReq *req;
370
bool progress = false;
371
372
+ virtio_scsi_acquire(s);
373
while ((req = virtio_scsi_pop_req(s, vq))) {
374
progress = true;
375
virtio_scsi_handle_ctrl_req(s, req);
376
}
377
+ virtio_scsi_release(s);
378
return progress;
379
}
380
381
@@ -XXX,XX +XXX,XX @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
382
383
QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
384
385
+ virtio_scsi_acquire(s);
386
do {
387
virtio_queue_set_notification(vq, 0);
388
389
@@ -XXX,XX +XXX,XX @@ bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
390
QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
391
virtio_scsi_handle_cmd_req_submit(s, req);
392
}
393
+ virtio_scsi_release(s);
394
return progress;
395
}
396
397
@@ -XXX,XX +XXX,XX @@ out:
398
399
bool virtio_scsi_handle_event_vq(VirtIOSCSI *s, VirtQueue *vq)
400
{
401
+ virtio_scsi_acquire(s);
402
if (s->events_dropped) {
403
virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
404
+ virtio_scsi_release(s);
405
return true;
406
}
407
+ virtio_scsi_release(s);
408
return false;
409
}
410
411
diff --git a/util/aio-posix.c b/util/aio-posix.c
412
index XXXXXXX..XXXXXXX 100644
413
--- a/util/aio-posix.c
414
+++ b/util/aio-posix.c
415
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
416
(revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) &&
417
aio_node_check(ctx, node->is_external) &&
418
node->io_read) {
419
- aio_context_acquire(ctx);
420
node->io_read(node->opaque);
421
- aio_context_release(ctx);
422
423
/* aio_notify() does not count as progress */
424
if (node->opaque != &ctx->notifier) {
425
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
426
(revents & (G_IO_OUT | G_IO_ERR)) &&
427
aio_node_check(ctx, node->is_external) &&
428
node->io_write) {
429
- aio_context_acquire(ctx);
430
node->io_write(node->opaque);
431
- aio_context_release(ctx);
432
progress = true;
433
}
434
435
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
436
start = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
437
}
438
439
- aio_context_acquire(ctx);
440
progress = try_poll_mode(ctx, blocking);
441
- aio_context_release(ctx);
442
-
443
if (!progress) {
444
assert(npfd == 0);
445
446
diff --git a/util/aio-win32.c b/util/aio-win32.c
447
index XXXXXXX..XXXXXXX 100644
448
--- a/util/aio-win32.c
449
+++ b/util/aio-win32.c
450
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
451
(revents || event_notifier_get_handle(node->e) == event) &&
452
node->io_notify) {
453
node->pfd.revents = 0;
454
- aio_context_acquire(ctx);
455
node->io_notify(node->e);
456
- aio_context_release(ctx);
457
458
/* aio_notify() does not count as progress */
459
if (node->e != &ctx->notifier) {
460
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
461
(node->io_read || node->io_write)) {
462
node->pfd.revents = 0;
463
if ((revents & G_IO_IN) && node->io_read) {
464
- aio_context_acquire(ctx);
465
node->io_read(node->opaque);
466
- aio_context_release(ctx);
467
progress = true;
468
}
469
if ((revents & G_IO_OUT) && node->io_write) {
470
- aio_context_acquire(ctx);
471
node->io_write(node->opaque);
472
- aio_context_release(ctx);
473
progress = true;
474
}
475
84
--
476
--
85
2.35.3
477
2.9.3
478
479
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
For consistency with other I/O functions, and in preparation to
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
implement them using generated_co_wrapper.
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
Reviewed-by: Fam Zheng <famz@redhat.com>
6
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7
Message-id: 20170213135235.12274-15-pbonzini@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
block/archipelago.c | 3 +++
11
block/blkreplay.c | 2 +-
12
block/block-backend.c | 6 ++++++
13
block/curl.c | 26 ++++++++++++++++++--------
14
block/gluster.c | 9 +--------
15
block/io.c | 6 +++++-
16
block/iscsi.c | 6 +++++-
17
block/linux-aio.c | 15 +++++++++------
18
block/nfs.c | 3 ++-
19
block/null.c | 4 ++++
20
block/qed.c | 3 +++
21
block/rbd.c | 4 ++++
22
dma-helpers.c | 2 ++
23
hw/block/virtio-blk.c | 2 ++
24
hw/scsi/scsi-bus.c | 2 ++
25
util/async.c | 4 ++--
26
util/thread-pool.c | 2 ++
27
17 files changed, 71 insertions(+), 28 deletions(-)
5
28
6
Callers were updated using this Coccinelle script:
29
diff --git a/block/archipelago.c b/block/archipelago.c
7
30
index XXXXXXX..XXXXXXX 100644
8
@@ expression child, offset, buf, bytes; @@
31
--- a/block/archipelago.c
9
- bdrv_pread(child, offset, buf, bytes)
32
+++ b/block/archipelago.c
10
+ bdrv_pread(child, offset, buf, bytes, 0)
33
@@ -XXX,XX +XXX,XX @@ static void qemu_archipelago_complete_aio(void *opaque)
11
34
{
12
@@ expression child, offset, buf, bytes; @@
35
AIORequestData *reqdata = (AIORequestData *) opaque;
13
- bdrv_pwrite(child, offset, buf, bytes)
36
ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) reqdata->aio_cb;
14
+ bdrv_pwrite(child, offset, buf, bytes, 0)
37
+ AioContext *ctx = bdrv_get_aio_context(aio_cb->common.bs);
15
38
16
@@ expression child, offset, buf, bytes; @@
39
+ aio_context_acquire(ctx);
17
- bdrv_pwrite_sync(child, offset, buf, bytes)
40
aio_cb->common.cb(aio_cb->common.opaque, aio_cb->ret);
18
+ bdrv_pwrite_sync(child, offset, buf, bytes, 0)
41
+ aio_context_release(ctx);
19
42
aio_cb->status = 0;
20
Resulting overly-long lines were then fixed by hand.
43
21
44
qemu_aio_unref(aio_cb);
22
Signed-off-by: Alberto Faria <afaria@redhat.com>
45
diff --git a/block/blkreplay.c b/block/blkreplay.c
23
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
46
index XXXXXXX..XXXXXXX 100755
24
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
47
--- a/block/blkreplay.c
25
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
48
+++ b/block/blkreplay.c
26
Message-Id: <20220609152744.3891847-2-afaria@redhat.com>
49
@@ -XXX,XX +XXX,XX @@ static int64_t blkreplay_getlength(BlockDriverState *bs)
27
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
50
static void blkreplay_bh_cb(void *opaque)
28
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
51
{
29
---
52
Request *req = opaque;
30
include/block/block-io.h | 7 ++--
53
- qemu_coroutine_enter(req->co);
31
block/blklogwrites.c | 4 +--
54
+ aio_co_wake(req->co);
32
block/bochs.c | 6 ++--
55
qemu_bh_delete(req->bh);
33
block/cloop.c | 10 +++---
56
g_free(req);
34
block/crypto.c | 4 +--
57
}
35
block/dmg.c | 24 +++++++-------
58
diff --git a/block/block-backend.c b/block/block-backend.c
36
block/io.c | 13 ++++----
59
index XXXXXXX..XXXXXXX 100644
37
block/parallels-ext.c | 4 +--
60
--- a/block/block-backend.c
38
block/parallels.c | 12 +++----
61
+++ b/block/block-backend.c
39
block/qcow.c | 27 ++++++++-------
62
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
40
block/qcow2-bitmap.c | 14 ++++----
63
static void error_callback_bh(void *opaque)
41
block/qcow2-cache.c | 7 ++--
64
{
42
block/qcow2-cluster.c | 21 ++++++------
65
struct BlockBackendAIOCB *acb = opaque;
43
block/qcow2-refcount.c | 42 +++++++++++------------
66
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
44
block/qcow2-snapshot.c | 39 +++++++++++-----------
67
45
block/qcow2.c | 44 ++++++++++++------------
68
bdrv_dec_in_flight(acb->common.bs);
46
block/qed.c | 8 ++---
69
+ aio_context_acquire(ctx);
47
block/vdi.c | 10 +++---
70
acb->common.cb(acb->common.opaque, acb->ret);
48
block/vhdx-log.c | 19 +++++------
71
+ aio_context_release(ctx);
49
block/vhdx.c | 32 ++++++++++--------
72
qemu_aio_unref(acb);
50
block/vmdk.c | 57 ++++++++++++++------------------
73
}
51
block/vpc.c | 19 ++++++-----
74
52
block/vvfat.c | 7 ++--
75
@@ -XXX,XX +XXX,XX @@ static void blk_aio_complete(BlkAioEmAIOCB *acb)
53
tests/unit/test-block-iothread.c | 8 ++---
76
static void blk_aio_complete_bh(void *opaque)
54
24 files changed, 219 insertions(+), 219 deletions(-)
77
{
55
78
BlkAioEmAIOCB *acb = opaque;
56
diff --git a/include/block/block-io.h b/include/block/block-io.h
79
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
57
index XXXXXXX..XXXXXXX 100644
80
58
--- a/include/block/block-io.h
81
assert(acb->has_returned);
59
+++ b/include/block/block-io.h
82
+ aio_context_acquire(ctx);
60
@@ -XXX,XX +XXX,XX @@
83
blk_aio_complete(acb);
61
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
84
+ aio_context_release(ctx);
62
int64_t bytes, BdrvRequestFlags flags);
85
}
63
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
86
64
-int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes);
87
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
65
+int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes,
88
diff --git a/block/curl.c b/block/curl.c
66
+ BdrvRequestFlags flags);
89
index XXXXXXX..XXXXXXX 100644
67
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
90
--- a/block/curl.c
68
- int64_t bytes);
91
+++ b/block/curl.c
69
+ int64_t bytes, BdrvRequestFlags flags);
92
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
70
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
93
{
71
- const void *buf, int64_t bytes);
94
CURLState *state;
72
+ const void *buf, int64_t bytes, BdrvRequestFlags flags);
95
int running;
96
+ int ret = -EINPROGRESS;
97
98
CURLAIOCB *acb = p;
99
- BDRVCURLState *s = acb->common.bs->opaque;
100
+ BlockDriverState *bs = acb->common.bs;
101
+ BDRVCURLState *s = bs->opaque;
102
+ AioContext *ctx = bdrv_get_aio_context(bs);
103
104
size_t start = acb->sector_num * BDRV_SECTOR_SIZE;
105
size_t end;
106
107
+ aio_context_acquire(ctx);
108
+
109
// In case we have the requested data already (e.g. read-ahead),
110
// we can just call the callback and be done.
111
switch (curl_find_buf(s, start, acb->nb_sectors * BDRV_SECTOR_SIZE, acb)) {
112
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
113
qemu_aio_unref(acb);
114
// fall through
115
case FIND_RET_WAIT:
116
- return;
117
+ goto out;
118
default:
119
break;
120
}
121
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
122
// No cache found, so let's start a new request
123
state = curl_init_state(acb->common.bs, s);
124
if (!state) {
125
- acb->common.cb(acb->common.opaque, -EIO);
126
- qemu_aio_unref(acb);
127
- return;
128
+ ret = -EIO;
129
+ goto out;
130
}
131
132
acb->start = 0;
133
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
134
state->orig_buf = g_try_malloc(state->buf_len);
135
if (state->buf_len && state->orig_buf == NULL) {
136
curl_clean_state(state);
137
- acb->common.cb(acb->common.opaque, -ENOMEM);
138
- qemu_aio_unref(acb);
139
- return;
140
+ ret = -ENOMEM;
141
+ goto out;
142
}
143
state->acb[0] = acb;
144
145
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
146
147
/* Tell curl it needs to kick things off */
148
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
149
+
150
+out:
151
+ if (ret != -EINPROGRESS) {
152
+ acb->common.cb(acb->common.opaque, ret);
153
+ qemu_aio_unref(acb);
154
+ }
155
+ aio_context_release(ctx);
156
}
157
158
static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
159
diff --git a/block/gluster.c b/block/gluster.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/block/gluster.c
162
+++ b/block/gluster.c
163
@@ -XXX,XX +XXX,XX @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
164
return qemu_gluster_glfs_init(gconf, errp);
165
}
166
167
-static void qemu_gluster_complete_aio(void *opaque)
168
-{
169
- GlusterAIOCB *acb = (GlusterAIOCB *)opaque;
170
-
171
- qemu_coroutine_enter(acb->coroutine);
172
-}
173
-
73
/*
174
/*
74
* Efficiently zero a region of the disk image. Note that this is a regular
175
* AIO callback routine called from GlusterFS thread.
75
* I/O request like read or write and should have a reasonable size. This
176
*/
76
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
177
@@ -XXX,XX +XXX,XX @@ static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg)
77
index XXXXXXX..XXXXXXX 100644
178
acb->ret = -EIO; /* Partial read/write - fail it */
78
--- a/block/blklogwrites.c
179
}
79
+++ b/block/blklogwrites.c
180
80
@@ -XXX,XX +XXX,XX @@ static uint64_t blk_log_writes_find_cur_log_sector(BdrvChild *log,
181
- aio_bh_schedule_oneshot(acb->aio_context, qemu_gluster_complete_aio, acb);
81
182
+ aio_co_schedule(acb->aio_context, acb->coroutine);
82
while (cur_idx < nr_entries) {
183
}
83
int read_ret = bdrv_pread(log, cur_sector << sector_bits, &cur_entry,
184
84
- sizeof(cur_entry));
185
static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
85
+ sizeof(cur_entry), 0);
86
if (read_ret < 0) {
87
error_setg_errno(errp, -read_ret,
88
"Failed to read log entry %"PRIu64, cur_idx);
89
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
90
log_sb.nr_entries = cpu_to_le64(0);
91
log_sb.sectorsize = cpu_to_le32(BDRV_SECTOR_SIZE);
92
} else {
93
- ret = bdrv_pread(s->log_file, 0, &log_sb, sizeof(log_sb));
94
+ ret = bdrv_pread(s->log_file, 0, &log_sb, sizeof(log_sb), 0);
95
if (ret < 0) {
96
error_setg_errno(errp, -ret, "Could not read log superblock");
97
goto fail_log;
98
diff --git a/block/bochs.c b/block/bochs.c
99
index XXXXXXX..XXXXXXX 100644
100
--- a/block/bochs.c
101
+++ b/block/bochs.c
102
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
103
return -EINVAL;
104
}
105
106
- ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
107
+ ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs), 0);
108
if (ret < 0) {
109
return ret;
110
}
111
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
112
}
113
114
ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
115
- s->catalog_size * 4);
116
+ s->catalog_size * 4, 0);
117
if (ret < 0) {
118
goto fail;
119
}
120
@@ -XXX,XX +XXX,XX @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
121
122
/* read in bitmap for current extent */
123
ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
124
- &bitmap_entry, 1);
125
+ &bitmap_entry, 1, 0);
126
if (ret < 0) {
127
return ret;
128
}
129
diff --git a/block/cloop.c b/block/cloop.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/block/cloop.c
132
+++ b/block/cloop.c
133
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
134
}
135
136
/* read header */
137
- ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
138
+ ret = bdrv_pread(bs->file, 128, &s->block_size, 4, 0);
139
if (ret < 0) {
140
return ret;
141
}
142
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
143
return -EINVAL;
144
}
145
146
- ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
147
+ ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4, 0);
148
if (ret < 0) {
149
return ret;
150
}
151
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
152
return -ENOMEM;
153
}
154
155
- ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
156
+ ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size, 0);
157
if (ret < 0) {
158
goto fail;
159
}
160
@@ -XXX,XX +XXX,XX @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
161
int ret;
162
uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
163
164
- ret = bdrv_pread(bs->file, s->offsets[block_num],
165
- s->compressed_block, bytes);
166
+ ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
167
+ bytes, 0);
168
if (ret != bytes) {
169
return -1;
170
}
171
diff --git a/block/crypto.c b/block/crypto.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/block/crypto.c
174
+++ b/block/crypto.c
175
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
176
BlockDriverState *bs = opaque;
177
ssize_t ret;
178
179
- ret = bdrv_pread(bs->file, offset, buf, buflen);
180
+ ret = bdrv_pread(bs->file, offset, buf, buflen, 0);
181
if (ret < 0) {
182
error_setg_errno(errp, -ret, "Could not read encryption header");
183
return ret;
184
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
185
BlockDriverState *bs = opaque;
186
ssize_t ret;
187
188
- ret = bdrv_pwrite(bs->file, offset, buf, buflen);
189
+ ret = bdrv_pwrite(bs->file, offset, buf, buflen, 0);
190
if (ret < 0) {
191
error_setg_errno(errp, -ret, "Could not write encryption header");
192
return ret;
193
diff --git a/block/dmg.c b/block/dmg.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/block/dmg.c
196
+++ b/block/dmg.c
197
@@ -XXX,XX +XXX,XX @@ static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
198
uint64_t buffer;
199
int ret;
200
201
- ret = bdrv_pread(bs->file, offset, &buffer, 8);
202
+ ret = bdrv_pread(bs->file, offset, &buffer, 8, 0);
203
if (ret < 0) {
204
return ret;
205
}
206
@@ -XXX,XX +XXX,XX @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
207
uint32_t buffer;
208
int ret;
209
210
- ret = bdrv_pread(bs->file, offset, &buffer, 4);
211
+ ret = bdrv_pread(bs->file, offset, &buffer, 4, 0);
212
if (ret < 0) {
213
return ret;
214
}
215
@@ -XXX,XX +XXX,XX @@ static int64_t dmg_find_koly_offset(BdrvChild *file, Error **errp)
216
offset = length - 511 - 512;
217
}
218
length = length < 515 ? length : 515;
219
- ret = bdrv_pread(file, offset, buffer, length);
220
+ ret = bdrv_pread(file, offset, buffer, length, 0);
221
if (ret < 0) {
222
error_setg_errno(errp, -ret, "Failed while reading UDIF trailer");
223
return ret;
224
@@ -XXX,XX +XXX,XX @@ static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
225
offset += 4;
226
227
buffer = g_realloc(buffer, count);
228
- ret = bdrv_pread(bs->file, offset, buffer, count);
229
+ ret = bdrv_pread(bs->file, offset, buffer, count, 0);
230
if (ret < 0) {
231
goto fail;
232
}
233
@@ -XXX,XX +XXX,XX @@ static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
234
235
buffer = g_malloc(info_length + 1);
236
buffer[info_length] = '\0';
237
- ret = bdrv_pread(bs->file, info_begin, buffer, info_length);
238
+ ret = bdrv_pread(bs->file, info_begin, buffer, info_length, 0);
239
if (ret != info_length) {
240
ret = -EINVAL;
241
goto fail;
242
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
243
case UDZO: { /* zlib compressed */
244
/* we need to buffer, because only the chunk as whole can be
245
* inflated. */
246
- ret = bdrv_pread(bs->file, s->offsets[chunk],
247
- s->compressed_chunk, s->lengths[chunk]);
248
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
249
+ s->lengths[chunk], 0);
250
if (ret != s->lengths[chunk]) {
251
return -1;
252
}
253
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
254
}
255
/* we need to buffer, because only the chunk as whole can be
256
* inflated. */
257
- ret = bdrv_pread(bs->file, s->offsets[chunk],
258
- s->compressed_chunk, s->lengths[chunk]);
259
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
260
+ s->lengths[chunk], 0);
261
if (ret != s->lengths[chunk]) {
262
return -1;
263
}
264
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
265
}
266
/* we need to buffer, because only the chunk as whole can be
267
* inflated. */
268
- ret = bdrv_pread(bs->file, s->offsets[chunk],
269
- s->compressed_chunk, s->lengths[chunk]);
270
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
271
+ s->lengths[chunk], 0);
272
if (ret != s->lengths[chunk]) {
273
return -1;
274
}
275
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
276
break;
277
case UDRW: /* copy */
278
ret = bdrv_pread(bs->file, s->offsets[chunk],
279
- s->uncompressed_chunk, s->lengths[chunk]);
280
+ s->uncompressed_chunk, s->lengths[chunk], 0);
281
if (ret != s->lengths[chunk]) {
282
return -1;
283
}
284
diff --git a/block/io.c b/block/io.c
186
diff --git a/block/io.c b/block/io.c
285
index XXXXXXX..XXXXXXX 100644
187
index XXXXXXX..XXXXXXX 100644
286
--- a/block/io.c
188
--- a/block/io.c
287
+++ b/block/io.c
189
+++ b/block/io.c
288
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
190
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_drain_bh_cb(void *opaque)
289
}
191
bdrv_dec_in_flight(bs);
290
192
bdrv_drained_begin(bs);
291
/* See bdrv_pwrite() for the return codes */
193
data->done = true;
292
-int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes)
194
- qemu_coroutine_enter(co);
293
+int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes,
195
+ aio_co_wake(co);
294
+ BdrvRequestFlags flags)
196
}
295
{
197
198
static void coroutine_fn bdrv_co_yield_to_drain(BlockDriverState *bs)
199
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_complete(BlockAIOCBCoroutine *acb)
200
static void bdrv_co_em_bh(void *opaque)
201
{
202
BlockAIOCBCoroutine *acb = opaque;
203
+ BlockDriverState *bs = acb->common.bs;
204
+ AioContext *ctx = bdrv_get_aio_context(bs);
205
206
assert(!acb->need_bh);
207
+ aio_context_acquire(ctx);
208
bdrv_co_complete(acb);
209
+ aio_context_release(ctx);
210
}
211
212
static void bdrv_co_maybe_schedule_bh(BlockAIOCBCoroutine *acb)
213
diff --git a/block/iscsi.c b/block/iscsi.c
214
index XXXXXXX..XXXXXXX 100644
215
--- a/block/iscsi.c
216
+++ b/block/iscsi.c
217
@@ -XXX,XX +XXX,XX @@ static void
218
iscsi_bh_cb(void *p)
219
{
220
IscsiAIOCB *acb = p;
221
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
222
223
qemu_bh_delete(acb->bh);
224
225
g_free(acb->buf);
226
acb->buf = NULL;
227
228
+ aio_context_acquire(ctx);
229
acb->common.cb(acb->common.opaque, acb->status);
230
+ aio_context_release(ctx);
231
232
if (acb->task != NULL) {
233
scsi_free_scsi_task(acb->task);
234
@@ -XXX,XX +XXX,XX @@ iscsi_schedule_bh(IscsiAIOCB *acb)
235
static void iscsi_co_generic_bh_cb(void *opaque)
236
{
237
struct IscsiTask *iTask = opaque;
238
+
239
iTask->complete = 1;
240
- qemu_coroutine_enter(iTask->co);
241
+ aio_co_wake(iTask->co);
242
}
243
244
static void iscsi_retry_timer_expired(void *opaque)
245
diff --git a/block/linux-aio.c b/block/linux-aio.c
246
index XXXXXXX..XXXXXXX 100644
247
--- a/block/linux-aio.c
248
+++ b/block/linux-aio.c
249
@@ -XXX,XX +XXX,XX @@ struct LinuxAioState {
250
io_context_t ctx;
251
EventNotifier e;
252
253
- /* io queue for submit at batch */
254
+ /* io queue for submit at batch. Protected by AioContext lock. */
255
LaioQueue io_q;
256
257
- /* I/O completion processing */
258
+ /* I/O completion processing. Only runs in I/O thread. */
259
QEMUBH *completion_bh;
260
int event_idx;
261
int event_max;
262
@@ -XXX,XX +XXX,XX @@ static inline ssize_t io_event_ret(struct io_event *ev)
263
*/
264
static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
265
{
266
+ LinuxAioState *s = laiocb->ctx;
296
int ret;
267
int ret;
297
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
268
298
@@ -XXX,XX +XXX,XX @@ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes)
269
ret = laiocb->ret;
299
return -EINVAL;
270
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
300
}
271
}
301
272
302
- ret = bdrv_preadv(child, offset, bytes, &qiov, 0);
273
laiocb->ret = ret;
303
+ ret = bdrv_preadv(child, offset, bytes, &qiov, flags);
274
+ aio_context_acquire(s->aio_context);
304
275
if (laiocb->co) {
305
return ret < 0 ? ret : bytes;
276
/* If the coroutine is already entered it must be in ioq_submit() and
306
}
277
* will notice laio->ret has been filled in when it eventually runs
307
@@ -XXX,XX +XXX,XX @@ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes)
278
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
308
-EACCES Trying to write a read-only device
279
laiocb->common.cb(laiocb->common.opaque, ret);
309
*/
280
qemu_aio_unref(laiocb);
310
int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
281
}
311
- int64_t bytes)
282
+ aio_context_release(s->aio_context);
312
+ int64_t bytes, BdrvRequestFlags flags)
283
}
313
{
284
314
int ret;
285
/**
315
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
286
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completions(LinuxAioState *s)
316
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
287
static void qemu_laio_process_completions_and_submit(LinuxAioState *s)
317
return -EINVAL;
288
{
318
}
289
qemu_laio_process_completions(s);
319
290
+
320
- ret = bdrv_pwritev(child, offset, bytes, &qiov, 0);
291
+ aio_context_acquire(s->aio_context);
321
+ ret = bdrv_pwritev(child, offset, bytes, &qiov, flags);
292
if (!s->io_q.plugged && !QSIMPLEQ_EMPTY(&s->io_q.pending)) {
322
293
ioq_submit(s);
323
return ret < 0 ? ret : bytes;
294
}
324
}
295
+ aio_context_release(s->aio_context);
325
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
296
}
326
* Returns 0 on success, -errno in error cases.
297
327
*/
298
static void qemu_laio_completion_bh(void *opaque)
328
int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
299
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_completion_cb(EventNotifier *e)
329
- const void *buf, int64_t count)
300
LinuxAioState *s = container_of(e, LinuxAioState, e);
330
+ const void *buf, int64_t count, BdrvRequestFlags flags)
301
331
{
302
if (event_notifier_test_and_clear(&s->e)) {
332
int ret;
303
- aio_context_acquire(s->aio_context);
333
IO_CODE();
304
qemu_laio_process_completions_and_submit(s);
334
305
- aio_context_release(s->aio_context);
335
- ret = bdrv_pwrite(child, offset, buf, count);
306
}
336
+ ret = bdrv_pwrite(child, offset, buf, count, flags);
307
}
337
if (ret < 0) {
308
338
return ret;
309
@@ -XXX,XX +XXX,XX @@ static bool qemu_laio_poll_cb(void *opaque)
339
}
310
return false;
340
diff --git a/block/parallels-ext.c b/block/parallels-ext.c
311
}
341
index XXXXXXX..XXXXXXX 100644
312
342
--- a/block/parallels-ext.c
313
- aio_context_acquire(s->aio_context);
343
+++ b/block/parallels-ext.c
314
qemu_laio_process_completions_and_submit(s);
344
@@ -XXX,XX +XXX,XX @@ static int parallels_load_bitmap_data(BlockDriverState *bs,
315
- aio_context_release(s->aio_context);
345
bdrv_dirty_bitmap_deserialize_ones(bitmap, offset, count, false);
316
return true;
346
} else {
317
}
347
ret = bdrv_pread(bs->file, entry << BDRV_SECTOR_BITS, buf,
318
348
- s->cluster_size);
319
@@ -XXX,XX +XXX,XX @@ void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context)
349
+ s->cluster_size, 0);
320
{
350
if (ret < 0) {
321
aio_set_event_notifier(old_context, &s->e, false, NULL, NULL);
351
error_setg_errno(errp, -ret,
322
qemu_bh_delete(s->completion_bh);
352
"Failed to read bitmap data cluster");
323
+ s->aio_context = NULL;
353
@@ -XXX,XX +XXX,XX @@ int parallels_read_format_extension(BlockDriverState *bs,
324
}
354
325
355
assert(ext_off > 0);
326
void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context)
356
327
diff --git a/block/nfs.c b/block/nfs.c
357
- ret = bdrv_pread(bs->file, ext_off, ext_cluster, s->cluster_size);
328
index XXXXXXX..XXXXXXX 100644
358
+ ret = bdrv_pread(bs->file, ext_off, ext_cluster, s->cluster_size, 0);
329
--- a/block/nfs.c
359
if (ret < 0) {
330
+++ b/block/nfs.c
360
error_setg_errno(errp, -ret, "Failed to read Format Extension cluster");
331
@@ -XXX,XX +XXX,XX @@ static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task)
361
goto out;
332
static void nfs_co_generic_bh_cb(void *opaque)
362
diff --git a/block/parallels.c b/block/parallels.c
333
{
363
index XXXXXXX..XXXXXXX 100644
334
NFSRPC *task = opaque;
364
--- a/block/parallels.c
335
+
365
+++ b/block/parallels.c
336
task->complete = 1;
366
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
337
- qemu_coroutine_enter(task->co);
367
if (off + to_write > s->header_size) {
338
+ aio_co_wake(task->co);
368
to_write = s->header_size - off;
339
}
369
}
340
370
- ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off,
341
static void
371
- to_write);
342
diff --git a/block/null.c b/block/null.c
372
+ ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off, to_write,
343
index XXXXXXX..XXXXXXX 100644
373
+ 0);
344
--- a/block/null.c
374
if (ret < 0) {
345
+++ b/block/null.c
375
qemu_co_mutex_unlock(&s->lock);
346
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo null_aiocb_info = {
376
return ret;
347
static void null_bh_cb(void *opaque)
377
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
348
{
378
349
NullAIOCB *acb = opaque;
379
ret = 0;
350
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
380
if (flush_bat) {
351
+
381
- ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size);
352
+ aio_context_acquire(ctx);
382
+ ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size, 0);
353
acb->common.cb(acb->common.opaque, 0);
383
if (ret < 0) {
354
+ aio_context_release(ctx);
384
res->check_errors++;
355
qemu_aio_unref(acb);
385
goto out;
356
}
386
@@ -XXX,XX +XXX,XX @@ static int parallels_update_header(BlockDriverState *bs)
357
387
if (size > s->header_size) {
388
size = s->header_size;
389
}
390
- return bdrv_pwrite_sync(bs->file, 0, s->header, size);
391
+ return bdrv_pwrite_sync(bs->file, 0, s->header, size, 0);
392
}
393
394
static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
395
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
396
return -EINVAL;
397
}
398
399
- ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
400
+ ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph), 0);
401
if (ret < 0) {
402
goto fail;
403
}
404
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
405
s->header_size = size;
406
}
407
408
- ret = bdrv_pread(bs->file, 0, s->header, s->header_size);
409
+ ret = bdrv_pread(bs->file, 0, s->header, s->header_size, 0);
410
if (ret < 0) {
411
goto fail;
412
}
413
diff --git a/block/qcow.c b/block/qcow.c
414
index XXXXXXX..XXXXXXX 100644
415
--- a/block/qcow.c
416
+++ b/block/qcow.c
417
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
418
goto fail;
419
}
420
421
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
422
+ ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
423
if (ret < 0) {
424
goto fail;
425
}
426
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
427
}
428
429
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
430
- s->l1_size * sizeof(uint64_t));
431
+ s->l1_size * sizeof(uint64_t), 0);
432
if (ret < 0) {
433
goto fail;
434
}
435
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
436
goto fail;
437
}
438
ret = bdrv_pread(bs->file, header.backing_file_offset,
439
- bs->auto_backing_file, len);
440
+ bs->auto_backing_file, len, 0);
441
if (ret < 0) {
442
goto fail;
443
}
444
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
445
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
446
ret = bdrv_pwrite_sync(bs->file,
447
s->l1_table_offset + l1_index * sizeof(tmp),
448
- &tmp, sizeof(tmp));
449
+ &tmp, sizeof(tmp), 0);
450
if (ret < 0) {
451
return ret;
452
}
453
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
454
if (new_l2_table) {
455
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
456
ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
457
- s->l2_size * sizeof(uint64_t));
458
+ s->l2_size * sizeof(uint64_t), 0);
459
if (ret < 0) {
460
return ret;
461
}
462
} else {
463
ret = bdrv_pread(bs->file, l2_offset, l2_table,
464
- s->l2_size * sizeof(uint64_t));
465
+ s->l2_size * sizeof(uint64_t), 0);
466
if (ret < 0) {
467
return ret;
468
}
469
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
470
/* write the cluster content */
471
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
472
ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
473
- s->cluster_size);
474
+ s->cluster_size, 0);
475
if (ret < 0) {
476
return ret;
477
}
478
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
479
return -EIO;
480
}
481
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
482
- ret = bdrv_pwrite(bs->file,
483
- cluster_offset + i,
484
+ ret = bdrv_pwrite(bs->file, cluster_offset + i,
485
s->cluster_data,
486
- BDRV_SECTOR_SIZE);
487
+ BDRV_SECTOR_SIZE, 0);
488
if (ret < 0) {
489
return ret;
490
}
491
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
492
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
493
}
494
ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
495
- &tmp, sizeof(tmp));
496
+ &tmp, sizeof(tmp), 0);
497
if (ret < 0) {
498
return ret;
499
}
500
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
501
csize = cluster_offset >> (63 - s->cluster_bits);
502
csize &= (s->cluster_size - 1);
503
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
504
- ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize);
505
+ ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize, 0);
506
if (ret != csize)
507
return -1;
508
if (decompress_buffer(s->cluster_cache, s->cluster_size,
509
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
510
int ret;
511
512
memset(s->l1_table, 0, l1_length);
513
- if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table,
514
- l1_length) < 0)
515
+ if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table, l1_length,
516
+ 0) < 0)
517
return -1;
518
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
519
PREALLOC_MODE_OFF, 0, NULL);
520
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
521
index XXXXXXX..XXXXXXX 100644
522
--- a/block/qcow2-bitmap.c
523
+++ b/block/qcow2-bitmap.c
524
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
525
}
526
527
assert(tb->size <= BME_MAX_TABLE_SIZE);
528
- ret = bdrv_pread(bs->file, tb->offset,
529
- table, tb->size * BME_TABLE_ENTRY_SIZE);
530
+ ret = bdrv_pread(bs->file, tb->offset, table,
531
+ tb->size * BME_TABLE_ENTRY_SIZE, 0);
532
if (ret < 0) {
533
goto fail;
534
}
535
@@ -XXX,XX +XXX,XX @@ static int load_bitmap_data(BlockDriverState *bs,
536
* already cleared */
537
}
538
} else {
539
- ret = bdrv_pread(bs->file, data_offset, buf, s->cluster_size);
540
+ ret = bdrv_pread(bs->file, data_offset, buf, s->cluster_size, 0);
541
if (ret < 0) {
542
goto finish;
543
}
544
@@ -XXX,XX +XXX,XX @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset,
545
}
546
dir_end = dir + size;
547
548
- ret = bdrv_pread(bs->file, offset, dir, size);
549
+ ret = bdrv_pread(bs->file, offset, dir, size, 0);
550
if (ret < 0) {
551
error_setg_errno(errp, -ret, "Failed to read bitmap directory");
552
goto fail;
553
@@ -XXX,XX +XXX,XX @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
554
goto fail;
555
}
556
557
- ret = bdrv_pwrite(bs->file, dir_offset, dir, dir_size);
558
+ ret = bdrv_pwrite(bs->file, dir_offset, dir, dir_size, 0);
559
if (ret < 0) {
560
goto fail;
561
}
562
@@ -XXX,XX +XXX,XX @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
563
goto fail;
564
}
565
566
- ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size);
567
+ ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size, 0);
568
if (ret < 0) {
569
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
570
bm_name);
571
@@ -XXX,XX +XXX,XX @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
572
}
573
574
bitmap_table_to_be(tb, tb_size);
575
- ret = bdrv_pwrite(bs->file, tb_offset, tb, tb_size * sizeof(tb[0]));
576
+ ret = bdrv_pwrite(bs->file, tb_offset, tb, tb_size * sizeof(tb[0]), 0);
577
if (ret < 0) {
578
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
579
bm_name);
580
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
581
index XXXXXXX..XXXXXXX 100644
582
--- a/block/qcow2-cache.c
583
+++ b/block/qcow2-cache.c
584
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
585
}
586
587
ret = bdrv_pwrite(bs->file, c->entries[i].offset,
588
- qcow2_cache_get_table_addr(c, i), c->table_size);
589
+ qcow2_cache_get_table_addr(c, i), c->table_size, 0);
590
if (ret < 0) {
591
return ret;
592
}
593
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
594
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
595
}
596
597
- ret = bdrv_pread(bs->file, offset,
598
- qcow2_cache_get_table_addr(c, i),
599
- c->table_size);
600
+ ret = bdrv_pread(bs->file, offset, qcow2_cache_get_table_addr(c, i),
601
+ c->table_size, 0);
602
if (ret < 0) {
603
return ret;
604
}
605
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
606
index XXXXXXX..XXXXXXX 100644
607
--- a/block/qcow2-cluster.c
608
+++ b/block/qcow2-cluster.c
609
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
610
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
611
for(i = 0; i < s->l1_size; i++)
612
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
613
- ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset,
614
- new_l1_table, new_l1_size2);
615
+ ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_table,
616
+ new_l1_size2, 0);
617
if (ret < 0)
618
goto fail;
619
for(i = 0; i < s->l1_size; i++)
620
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
621
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
622
stl_be_p(data, new_l1_size);
623
stq_be_p(data + 4, new_l1_table_offset);
624
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size),
625
- data, sizeof(data));
626
+ ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,
627
+ sizeof(data), 0);
628
if (ret < 0) {
629
goto fail;
630
}
631
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
632
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
633
ret = bdrv_pwrite_sync(bs->file,
634
s->l1_table_offset + L1E_SIZE * l1_start_index,
635
- buf, bufsize);
636
+ buf, bufsize, 0);
637
if (ret < 0) {
638
return ret;
639
}
640
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
641
(void **)&l2_slice);
642
} else {
643
/* load inactive L2 tables from disk */
644
- ret = bdrv_pread(bs->file, slice_offset, l2_slice, slice_size2);
645
+ ret = bdrv_pread(bs->file, slice_offset, l2_slice,
646
+ slice_size2, 0);
647
}
648
if (ret < 0) {
649
goto fail;
650
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
651
goto fail;
652
}
653
654
- ret = bdrv_pwrite(bs->file, slice_offset,
655
- l2_slice, slice_size2);
656
+ ret = bdrv_pwrite(bs->file, slice_offset, l2_slice,
657
+ slice_size2, 0);
658
if (ret < 0) {
659
goto fail;
660
}
661
@@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
662
663
l1_table = new_l1_table;
664
665
- ret = bdrv_pread(bs->file, s->snapshots[i].l1_table_offset,
666
- l1_table, l1_size2);
667
+ ret = bdrv_pread(bs->file, s->snapshots[i].l1_table_offset, l1_table,
668
+ l1_size2, 0);
669
if (ret < 0) {
670
goto fail;
671
}
672
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
673
index XXXXXXX..XXXXXXX 100644
674
--- a/block/qcow2-refcount.c
675
+++ b/block/qcow2-refcount.c
676
@@ -XXX,XX +XXX,XX @@ int qcow2_refcount_init(BlockDriverState *bs)
677
}
678
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
679
ret = bdrv_pread(bs->file, s->refcount_table_offset,
680
- s->refcount_table, refcount_table_size2);
681
+ s->refcount_table, refcount_table_size2, 0);
682
if (ret < 0) {
683
goto fail;
684
}
685
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
686
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
687
ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset +
688
refcount_table_index * REFTABLE_ENTRY_SIZE,
689
- &data64, sizeof(data64));
690
+ &data64, sizeof(data64), 0);
691
if (ret < 0) {
692
goto fail;
693
}
694
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
695
696
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
697
ret = bdrv_pwrite_sync(bs->file, table_offset, new_table,
698
- table_size * REFTABLE_ENTRY_SIZE);
699
+ table_size * REFTABLE_ENTRY_SIZE, 0);
700
if (ret < 0) {
701
goto fail;
702
}
703
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
704
data.d32 = cpu_to_be32(table_clusters);
705
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
706
ret = bdrv_pwrite_sync(bs->file,
707
- offsetof(QCowHeader, refcount_table_offset),
708
- &data, sizeof(data));
709
+ offsetof(QCowHeader, refcount_table_offset), &data,
710
+ sizeof(data), 0);
711
if (ret < 0) {
712
goto fail;
713
}
714
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
715
}
716
l1_allocated = true;
717
718
- ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2);
719
+ ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2, 0);
720
if (ret < 0) {
721
goto fail;
722
}
723
@@ -XXX,XX +XXX,XX @@ fail:
724
cpu_to_be64s(&l1_table[i]);
725
}
726
727
- ret = bdrv_pwrite_sync(bs->file, l1_table_offset,
728
- l1_table, l1_size2);
729
+ ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2,
730
+ 0);
731
732
for (i = 0; i < l1_size; i++) {
733
be64_to_cpus(&l1_table[i]);
734
@@ -XXX,XX +XXX,XX @@ static int fix_l2_entry_by_zero(BlockDriverState *bs, BdrvCheckResult *res,
735
}
736
737
ret = bdrv_pwrite_sync(bs->file, l2e_offset, &l2_table[idx],
738
- l2_entry_size(s));
739
+ l2_entry_size(s), 0);
740
if (ret < 0) {
741
fprintf(stderr, "ERROR: Failed to overwrite L2 "
742
"table entry: %s\n", strerror(-ret));
743
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
744
bool metadata_overlap;
745
746
/* Read L2 table from disk */
747
- ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size_bytes);
748
+ ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size_bytes, 0);
749
if (ret < 0) {
750
fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n");
751
res->check_errors++;
752
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
753
}
754
755
/* Read L1 table entries from disk */
756
- ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size_bytes);
757
+ ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size_bytes, 0);
758
if (ret < 0) {
759
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
760
res->check_errors++;
761
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
762
}
763
764
ret = bdrv_pread(bs->file, l2_offset, l2_table,
765
- s->l2_size * l2_entry_size(s));
766
+ s->l2_size * l2_entry_size(s), 0);
767
if (ret < 0) {
768
fprintf(stderr, "ERROR: Could not read L2 table: %s\n",
769
strerror(-ret));
770
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
771
goto fail;
772
}
773
774
- ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
775
- s->cluster_size);
776
+ ret = bdrv_pwrite(bs->file, l2_offset, l2_table, s->cluster_size,
777
+ 0);
778
if (ret < 0) {
779
fprintf(stderr, "ERROR: Could not write L2 table: %s\n",
780
strerror(-ret));
781
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcounts_write_refblocks(
782
refblock_index * s->cluster_size);
783
784
ret = bdrv_pwrite(bs->file, refblock_offset, on_disk_refblock,
785
- s->cluster_size);
786
+ s->cluster_size, 0);
787
if (ret < 0) {
788
error_setg_errno(errp, -ret, "ERROR writing refblock");
789
return ret;
790
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcount_structure(BlockDriverState *bs,
791
792
assert(reftable_length < INT_MAX);
793
ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable,
794
- reftable_length);
795
+ reftable_length, 0);
796
if (ret < 0) {
797
error_setg_errno(errp, -ret, "ERROR writing reftable");
798
goto fail;
799
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcount_structure(BlockDriverState *bs,
800
ret = bdrv_pwrite_sync(bs->file,
801
offsetof(QCowHeader, refcount_table_offset),
802
&reftable_offset_and_clusters,
803
- sizeof(reftable_offset_and_clusters));
804
+ sizeof(reftable_offset_and_clusters), 0);
805
if (ret < 0) {
806
error_setg_errno(errp, -ret, "ERROR setting reftable");
807
goto fail;
808
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
809
return -ENOMEM;
810
}
811
812
- ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2);
813
+ ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2, 0);
814
if (ret < 0) {
815
g_free(l1);
816
return ret;
817
@@ -XXX,XX +XXX,XX @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
818
return ret;
819
}
820
821
- ret = bdrv_pwrite(bs->file, offset, refblock, s->cluster_size);
822
+ ret = bdrv_pwrite(bs->file, offset, refblock, s->cluster_size, 0);
823
if (ret < 0) {
824
error_setg_errno(errp, -ret, "Failed to write refblock");
825
return ret;
826
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
827
}
828
829
ret = bdrv_pwrite(bs->file, new_reftable_offset, new_reftable,
830
- new_reftable_size * REFTABLE_ENTRY_SIZE);
831
+ new_reftable_size * REFTABLE_ENTRY_SIZE, 0);
832
833
for (i = 0; i < new_reftable_size; i++) {
834
be64_to_cpus(&new_reftable[i]);
835
@@ -XXX,XX +XXX,XX @@ int qcow2_shrink_reftable(BlockDriverState *bs)
836
}
837
838
ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp,
839
- s->refcount_table_size * REFTABLE_ENTRY_SIZE);
840
+ s->refcount_table_size * REFTABLE_ENTRY_SIZE, 0);
841
/*
842
* If the write in the reftable failed the image may contain a partially
843
* overwritten reftable. In this case it would be better to clear the
844
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
845
index XXXXXXX..XXXXXXX 100644
846
--- a/block/qcow2-snapshot.c
847
+++ b/block/qcow2-snapshot.c
848
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
849
850
/* Read statically sized part of the snapshot header */
851
offset = ROUND_UP(offset, 8);
852
- ret = bdrv_pread(bs->file, offset, &h, sizeof(h));
853
+ ret = bdrv_pread(bs->file, offset, &h, sizeof(h), 0);
854
if (ret < 0) {
855
error_setg_errno(errp, -ret, "Failed to read snapshot table");
856
goto fail;
857
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
858
859
/* Read known extra data */
860
ret = bdrv_pread(bs->file, offset, &extra,
861
- MIN(sizeof(extra), sn->extra_data_size));
862
+ MIN(sizeof(extra), sn->extra_data_size), 0);
863
if (ret < 0) {
864
error_setg_errno(errp, -ret, "Failed to read snapshot table");
865
goto fail;
866
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
867
unknown_extra_data_size = sn->extra_data_size - sizeof(extra);
868
sn->unknown_extra_data = g_malloc(unknown_extra_data_size);
869
ret = bdrv_pread(bs->file, offset, sn->unknown_extra_data,
870
- unknown_extra_data_size);
871
+ unknown_extra_data_size, 0);
872
if (ret < 0) {
873
error_setg_errno(errp, -ret,
874
"Failed to read snapshot table");
875
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
876
877
/* Read snapshot ID */
878
sn->id_str = g_malloc(id_str_size + 1);
879
- ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size);
880
+ ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size, 0);
881
if (ret < 0) {
882
error_setg_errno(errp, -ret, "Failed to read snapshot table");
883
goto fail;
884
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
885
886
/* Read snapshot name */
887
sn->name = g_malloc(name_size + 1);
888
- ret = bdrv_pread(bs->file, offset, sn->name, name_size);
889
+ ret = bdrv_pread(bs->file, offset, sn->name, name_size, 0);
890
if (ret < 0) {
891
error_setg_errno(errp, -ret, "Failed to read snapshot table");
892
goto fail;
893
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
894
h.name_size = cpu_to_be16(name_size);
895
offset = ROUND_UP(offset, 8);
896
897
- ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h));
898
+ ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h), 0);
899
if (ret < 0) {
900
goto fail;
901
}
902
offset += sizeof(h);
903
904
- ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra));
905
+ ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra), 0);
906
if (ret < 0) {
907
goto fail;
908
}
909
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
910
assert(sn->unknown_extra_data);
911
912
ret = bdrv_pwrite(bs->file, offset, sn->unknown_extra_data,
913
- unknown_extra_data_size);
914
+ unknown_extra_data_size, 0);
915
if (ret < 0) {
916
goto fail;
917
}
918
offset += unknown_extra_data_size;
919
}
920
921
- ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size);
922
+ ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size, 0);
923
if (ret < 0) {
924
goto fail;
925
}
926
offset += id_str_size;
927
928
- ret = bdrv_pwrite(bs->file, offset, sn->name, name_size);
929
+ ret = bdrv_pwrite(bs->file, offset, sn->name, name_size, 0);
930
if (ret < 0) {
931
goto fail;
932
}
933
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
934
header_data.snapshots_offset = cpu_to_be64(snapshots_offset);
935
936
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
937
- &header_data, sizeof(header_data));
938
+ &header_data, sizeof(header_data), 0);
939
if (ret < 0) {
940
goto fail;
941
}
942
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
943
944
/* qcow2_do_open() discards this information in check mode */
945
ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
946
- &snapshot_table_pointer, sizeof(snapshot_table_pointer));
947
+ &snapshot_table_pointer, sizeof(snapshot_table_pointer),
948
+ 0);
949
if (ret < 0) {
950
result->check_errors++;
951
fprintf(stderr, "ERROR failed to read the snapshot table pointer from "
952
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
953
snapshot_table_pointer.nb_snapshots = cpu_to_be32(s->nb_snapshots);
954
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
955
&snapshot_table_pointer.nb_snapshots,
956
- sizeof(snapshot_table_pointer.nb_snapshots));
957
+ sizeof(snapshot_table_pointer.nb_snapshots), 0);
958
if (ret < 0) {
959
result->check_errors++;
960
fprintf(stderr, "ERROR failed to update the snapshot count in the "
961
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
962
}
963
964
ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
965
- s->l1_size * L1E_SIZE);
966
+ s->l1_size * L1E_SIZE, 0);
967
if (ret < 0) {
968
goto fail;
969
}
970
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
971
goto fail;
972
}
973
974
- ret = bdrv_pread(bs->file, sn->l1_table_offset,
975
- sn_l1_table, sn_l1_bytes);
976
+ ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_table, sn_l1_bytes,
977
+ 0);
978
if (ret < 0) {
979
goto fail;
980
}
981
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
982
}
983
984
ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
985
- cur_l1_bytes);
986
+ cur_l1_bytes, 0);
987
if (ret < 0) {
988
goto fail;
989
}
990
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
991
return -ENOMEM;
992
}
993
994
- ret = bdrv_pread(bs->file, sn->l1_table_offset,
995
- new_l1_table, new_l1_bytes);
996
+ ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table,
997
+ new_l1_bytes, 0);
998
if (ret < 0) {
999
error_setg(errp, "Failed to read l1 table for snapshot");
1000
qemu_vfree(new_l1_table);
1001
diff --git a/block/qcow2.c b/block/qcow2.c
1002
index XXXXXXX..XXXXXXX 100644
1003
--- a/block/qcow2.c
1004
+++ b/block/qcow2.c
1005
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
1006
return -1;
1007
}
1008
1009
- ret = bdrv_pread(bs->file,
1010
- s->crypto_header.offset + offset, buf, buflen);
1011
+ ret = bdrv_pread(bs->file, s->crypto_header.offset + offset, buf, buflen,
1012
+ 0);
1013
if (ret < 0) {
1014
error_setg_errno(errp, -ret, "Could not read encryption header");
1015
return -1;
1016
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
1017
return -1;
1018
}
1019
1020
- ret = bdrv_pwrite(bs->file,
1021
- s->crypto_header.offset + offset, buf, buflen);
1022
+ ret = bdrv_pwrite(bs->file, s->crypto_header.offset + offset, buf, buflen,
1023
+ 0);
1024
if (ret < 0) {
1025
error_setg_errno(errp, -ret, "Could not read encryption header");
1026
return -1;
1027
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1028
printf("attempting to read extended header in offset %lu\n", offset);
1029
#endif
1030
1031
- ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext));
1032
+ ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext), 0);
1033
if (ret < 0) {
1034
error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "
1035
"pread fail from offset %" PRIu64, offset);
1036
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1037
sizeof(bs->backing_format));
1038
return 2;
1039
}
1040
- ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len);
1041
+ ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len, 0);
1042
if (ret < 0) {
1043
error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "
1044
"Could not read format name");
1045
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1046
case QCOW2_EXT_MAGIC_FEATURE_TABLE:
1047
if (p_feature_table != NULL) {
1048
void *feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));
1049
- ret = bdrv_pread(bs->file, offset , feature_table, ext.len);
1050
+ ret = bdrv_pread(bs->file, offset, feature_table, ext.len, 0);
1051
if (ret < 0) {
1052
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
1053
"Could not read table");
1054
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1055
return -EINVAL;
1056
}
1057
1058
- ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len);
1059
+ ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len, 0);
1060
if (ret < 0) {
1061
error_setg_errno(errp, -ret,
1062
"Unable to read CRYPTO header extension");
1063
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1064
break;
1065
}
1066
1067
- ret = bdrv_pread(bs->file, offset, &bitmaps_ext, ext.len);
1068
+ ret = bdrv_pread(bs->file, offset, &bitmaps_ext, ext.len, 0);
1069
if (ret < 0) {
1070
error_setg_errno(errp, -ret, "bitmaps_ext: "
1071
"Could not read ext header");
1072
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1073
case QCOW2_EXT_MAGIC_DATA_FILE:
1074
{
1075
s->image_data_file = g_malloc0(ext.len + 1);
1076
- ret = bdrv_pread(bs->file, offset, s->image_data_file, ext.len);
1077
+ ret = bdrv_pread(bs->file, offset, s->image_data_file, ext.len, 0);
1078
if (ret < 0) {
1079
error_setg_errno(errp, -ret,
1080
"ERROR: Could not read data file name");
1081
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1082
uext->len = ext.len;
1083
QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);
1084
1085
- ret = bdrv_pread(bs->file, offset , uext->data, uext->len);
1086
+ ret = bdrv_pread(bs->file, offset, uext->data, uext->len, 0);
1087
if (ret < 0) {
1088
error_setg_errno(errp, -ret, "ERROR: unknown extension: "
1089
"Could not read data");
1090
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
1091
1092
val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY);
1093
ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features),
1094
- &val, sizeof(val));
1095
+ &val, sizeof(val), 0);
1096
if (ret < 0) {
1097
return ret;
1098
}
1099
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1100
uint64_t l1_vm_state_index;
1101
bool update_header = false;
1102
1103
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
1104
+ ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
1105
if (ret < 0) {
1106
error_setg_errno(errp, -ret, "Could not read qcow2 header");
1107
goto fail;
1108
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1109
s->unknown_header_fields_size = header.header_length - sizeof(header);
1110
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
1111
ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,
1112
- s->unknown_header_fields_size);
1113
+ s->unknown_header_fields_size, 0);
1114
if (ret < 0) {
1115
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
1116
"fields");
1117
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1118
goto fail;
1119
}
1120
ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
1121
- s->l1_size * L1E_SIZE);
1122
+ s->l1_size * L1E_SIZE, 0);
1123
if (ret < 0) {
1124
error_setg_errno(errp, -ret, "Could not read L1 table");
1125
goto fail;
1126
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1127
goto fail;
1128
}
1129
ret = bdrv_pread(bs->file, header.backing_file_offset,
1130
- bs->auto_backing_file, len);
1131
+ bs->auto_backing_file, len, 0);
1132
if (ret < 0) {
1133
error_setg_errno(errp, -ret, "Could not read backing file name");
1134
goto fail;
1135
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
1136
}
1137
1138
/* Write the new header */
1139
- ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size);
1140
+ ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size, 0);
1141
if (ret < 0) {
1142
goto fail;
1143
}
1144
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
1145
1146
/* write updated header.size */
1147
offset = cpu_to_be64(offset);
1148
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
1149
- &offset, sizeof(offset));
1150
+ ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), &offset,
1151
+ sizeof(offset), 0);
1152
if (ret < 0) {
1153
error_setg_errno(errp, -ret, "Failed to update the image size");
1154
goto fail;
1155
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
1156
l1_ofs_rt_ofs_cls.reftable_offset = cpu_to_be64(s->cluster_size);
1157
l1_ofs_rt_ofs_cls.reftable_clusters = cpu_to_be32(1);
1158
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_table_offset),
1159
- &l1_ofs_rt_ofs_cls, sizeof(l1_ofs_rt_ofs_cls));
1160
+ &l1_ofs_rt_ofs_cls, sizeof(l1_ofs_rt_ofs_cls), 0);
1161
if (ret < 0) {
1162
goto fail_broken_refcounts;
1163
}
1164
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
1165
1166
/* Enter the first refblock into the reftable */
1167
rt_entry = cpu_to_be64(2 * s->cluster_size);
1168
- ret = bdrv_pwrite_sync(bs->file, s->cluster_size,
1169
- &rt_entry, sizeof(rt_entry));
1170
+ ret = bdrv_pwrite_sync(bs->file, s->cluster_size, &rt_entry,
1171
+ sizeof(rt_entry), 0);
1172
if (ret < 0) {
1173
goto fail_broken_refcounts;
1174
}
1175
diff --git a/block/qed.c b/block/qed.c
358
diff --git a/block/qed.c b/block/qed.c
1176
index XXXXXXX..XXXXXXX 100644
359
index XXXXXXX..XXXXXXX 100644
1177
--- a/block/qed.c
360
--- a/block/qed.c
1178
+++ b/block/qed.c
361
+++ b/block/qed.c
1179
@@ -XXX,XX +XXX,XX @@ int qed_write_header_sync(BDRVQEDState *s)
362
@@ -XXX,XX +XXX,XX @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
1180
int ret;
363
static void qed_aio_complete_bh(void *opaque)
1181
364
{
1182
qed_header_cpu_to_le(&s->header, &le);
365
QEDAIOCB *acb = opaque;
1183
- ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le));
366
+ BDRVQEDState *s = acb_to_s(acb);
1184
+ ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le), 0);
367
BlockCompletionFunc *cb = acb->common.cb;
1185
if (ret != sizeof(le)) {
368
void *user_opaque = acb->common.opaque;
1186
return ret;
369
int ret = acb->bh_ret;
1187
}
370
@@ -XXX,XX +XXX,XX @@ static void qed_aio_complete_bh(void *opaque)
1188
@@ -XXX,XX +XXX,XX @@ static int qed_read_string(BdrvChild *file, uint64_t offset, size_t n,
371
qemu_aio_unref(acb);
1189
if (n >= buflen) {
372
1190
return -EINVAL;
373
/* Invoke callback */
1191
}
374
+ qed_acquire(s);
1192
- ret = bdrv_pread(file, offset, buf, n);
375
cb(user_opaque, ret);
1193
+ ret = bdrv_pread(file, offset, buf, n, 0);
376
+ qed_release(s);
1194
if (ret < 0) {
377
}
1195
return ret;
378
1196
}
379
static void qed_aio_complete(QEDAIOCB *acb, int ret)
1197
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
380
diff --git a/block/rbd.c b/block/rbd.c
1198
int64_t file_size;
381
index XXXXXXX..XXXXXXX 100644
1199
int ret;
382
--- a/block/rbd.c
1200
383
+++ b/block/rbd.c
1201
- ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header));
384
@@ -XXX,XX +XXX,XX @@ shutdown:
1202
+ ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header), 0);
385
static void qemu_rbd_complete_aio(RADOSCB *rcb)
1203
if (ret < 0) {
386
{
1204
error_setg(errp, "Failed to read QED header");
387
RBDAIOCB *acb = rcb->acb;
1205
return ret;
388
+ AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
1206
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
389
int64_t r;
1207
}
390
1208
391
r = rcb->ret;
1209
/* Write new header */
392
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
1210
- ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len);
393
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
1211
+ ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len, 0);
394
}
1212
g_free(buffer);
395
qemu_vfree(acb->bounce);
1213
if (ret == 0) {
396
+
1214
memcpy(&s->header, &new_header, sizeof(new_header));
397
+ aio_context_acquire(ctx);
1215
diff --git a/block/vdi.c b/block/vdi.c
398
acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
1216
index XXXXXXX..XXXXXXX 100644
399
+ aio_context_release(ctx);
1217
--- a/block/vdi.c
400
1218
+++ b/block/vdi.c
401
qemu_aio_unref(acb);
1219
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
402
}
1220
403
diff --git a/dma-helpers.c b/dma-helpers.c
1221
logout("\n");
404
index XXXXXXX..XXXXXXX 100644
1222
405
--- a/dma-helpers.c
1223
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
406
+++ b/dma-helpers.c
1224
+ ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
407
@@ -XXX,XX +XXX,XX @@ static void dma_blk_cb(void *opaque, int ret)
1225
if (ret < 0) {
408
QEMU_ALIGN_DOWN(dbs->iov.size, dbs->align));
1226
goto fail;
409
}
1227
}
410
1228
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
411
+ aio_context_acquire(dbs->ctx);
1229
}
412
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
1230
413
dma_blk_cb, dbs, dbs->io_func_opaque);
1231
ret = bdrv_pread(bs->file, header.offset_bmap, s->bmap,
414
+ aio_context_release(dbs->ctx);
1232
- bmap_size * SECTOR_SIZE);
415
assert(dbs->acb);
1233
+ bmap_size * SECTOR_SIZE, 0);
416
}
1234
if (ret < 0) {
417
1235
goto fail_free_bmap;
418
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
1236
}
419
index XXXXXXX..XXXXXXX 100644
1237
@@ -XXX,XX +XXX,XX @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
420
--- a/hw/block/virtio-blk.c
1238
* so this full-cluster write does not overlap a partial write
421
+++ b/hw/block/virtio-blk.c
1239
* of the same cluster, issued from the "else" branch.
422
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
1240
*/
423
1241
- ret = bdrv_pwrite(bs->file, data_offset, block, s->block_size);
424
s->rq = NULL;
1242
+ ret = bdrv_pwrite(bs->file, data_offset, block, s->block_size, 0);
425
1243
qemu_co_rwlock_unlock(&s->bmap_lock);
426
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
1244
} else {
427
while (req) {
1245
nonallocating_write:
428
VirtIOBlockReq *next = req->next;
1246
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
429
if (virtio_blk_handle_request(req, &mrb)) {
1247
assert(VDI_IS_ALLOCATED(bmap_first));
430
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_dma_restart_bh(void *opaque)
1248
*header = s->header;
431
if (mrb.num_reqs) {
1249
vdi_header_to_le(header);
432
virtio_blk_submit_multireq(s->blk, &mrb);
1250
- ret = bdrv_pwrite(bs->file, 0, header, sizeof(*header));
433
}
1251
+ ret = bdrv_pwrite(bs->file, 0, header, sizeof(*header), 0);
434
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
1252
g_free(header);
435
}
1253
436
1254
if (ret < 0) {
437
static void virtio_blk_dma_restart_cb(void *opaque, int running,
1255
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
438
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
1256
logout("will write %u block map sectors starting from entry %u\n",
439
index XXXXXXX..XXXXXXX 100644
1257
n_sectors, bmap_first);
440
--- a/hw/scsi/scsi-bus.c
1258
ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE, base,
441
+++ b/hw/scsi/scsi-bus.c
1259
- n_sectors * SECTOR_SIZE);
442
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_restart_bh(void *opaque)
1260
+ n_sectors * SECTOR_SIZE, 0);
443
qemu_bh_delete(s->bh);
1261
}
444
s->bh = NULL;
1262
445
1263
return ret < 0 ? ret : 0;
446
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
1264
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
447
QTAILQ_FOREACH_SAFE(req, &s->requests, next, next) {
1265
index XXXXXXX..XXXXXXX 100644
448
scsi_req_ref(req);
1266
--- a/block/vhdx-log.c
449
if (req->retry) {
1267
+++ b/block/vhdx-log.c
450
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_restart_bh(void *opaque)
1268
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_peek_hdr(BlockDriverState *bs, VHDXLogEntries *log,
1269
1270
offset = log->offset + read;
1271
1272
- ret = bdrv_pread(bs->file, offset, hdr, sizeof(VHDXLogEntryHeader));
1273
+ ret = bdrv_pread(bs->file, offset, hdr, sizeof(VHDXLogEntryHeader), 0);
1274
if (ret < 0) {
1275
goto exit;
1276
}
1277
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log,
1278
}
451
}
1279
offset = log->offset + read;
452
scsi_req_unref(req);
1280
453
}
1281
- ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE);
454
+ aio_context_release(blk_get_aio_context(s->conf.blk));
1282
+ ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE, 0);
455
}
1283
if (ret < 0) {
456
1284
goto exit;
457
void scsi_req_retry(SCSIRequest *req)
458
diff --git a/util/async.c b/util/async.c
459
index XXXXXXX..XXXXXXX 100644
460
--- a/util/async.c
461
+++ b/util/async.c
462
@@ -XXX,XX +XXX,XX @@ int aio_bh_poll(AioContext *ctx)
463
ret = 1;
464
}
465
bh->idle = 0;
466
- aio_context_acquire(ctx);
467
aio_bh_call(bh);
468
- aio_context_release(ctx);
1285
}
469
}
1286
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log,
470
if (bh->deleted) {
1287
/* full */
471
deleted = true;
1288
break;
472
@@ -XXX,XX +XXX,XX @@ static void co_schedule_bh_cb(void *opaque)
473
Coroutine *co = QSLIST_FIRST(&straight);
474
QSLIST_REMOVE_HEAD(&straight, co_scheduled_next);
475
trace_aio_co_schedule_bh_cb(ctx, co);
476
+ aio_context_acquire(ctx);
477
qemu_coroutine_enter(co);
478
+ aio_context_release(ctx);
479
}
480
}
481
482
diff --git a/util/thread-pool.c b/util/thread-pool.c
483
index XXXXXXX..XXXXXXX 100644
484
--- a/util/thread-pool.c
485
+++ b/util/thread-pool.c
486
@@ -XXX,XX +XXX,XX @@ static void thread_pool_completion_bh(void *opaque)
487
ThreadPool *pool = opaque;
488
ThreadPoolElement *elem, *next;
489
490
+ aio_context_acquire(pool->ctx);
491
restart:
492
QLIST_FOREACH_SAFE(elem, &pool->head, all, next) {
493
if (elem->state != THREAD_DONE) {
494
@@ -XXX,XX +XXX,XX @@ restart:
495
qemu_aio_unref(elem);
1289
}
496
}
1290
- ret = bdrv_pwrite(bs->file, offset, buffer_tmp,
497
}
1291
- VHDX_LOG_SECTOR_SIZE);
498
+ aio_context_release(pool->ctx);
1292
+ ret = bdrv_pwrite(bs->file, offset, buffer_tmp, VHDX_LOG_SECTOR_SIZE,
499
}
1293
+ 0);
500
1294
if (ret < 0) {
501
static void thread_pool_cancel(BlockAIOCB *acb)
1295
goto exit;
1296
}
1297
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush_desc(BlockDriverState *bs, VHDXLogDescriptor *desc,
1298
/* count is only > 1 if we are writing zeroes */
1299
for (i = 0; i < count; i++) {
1300
ret = bdrv_pwrite_sync(bs->file, file_offset, buffer,
1301
- VHDX_LOG_SECTOR_SIZE);
1302
+ VHDX_LOG_SECTOR_SIZE, 0);
1303
if (ret < 0) {
1304
goto exit;
1305
}
1306
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
1307
if (i == 0 && leading_length) {
1308
/* partial sector at the front of the buffer */
1309
ret = bdrv_pread(bs->file, file_offset, merged_sector,
1310
- VHDX_LOG_SECTOR_SIZE);
1311
+ VHDX_LOG_SECTOR_SIZE, 0);
1312
if (ret < 0) {
1313
goto exit;
1314
}
1315
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
1316
sector_write = merged_sector;
1317
} else if (i == sectors - 1 && trailing_length) {
1318
/* partial sector at the end of the buffer */
1319
- ret = bdrv_pread(bs->file,
1320
- file_offset,
1321
- merged_sector + trailing_length,
1322
- VHDX_LOG_SECTOR_SIZE - trailing_length);
1323
+ ret = bdrv_pread(bs->file, file_offset,
1324
+ merged_sector + trailing_length,
1325
+ VHDX_LOG_SECTOR_SIZE - trailing_length, 0);
1326
if (ret < 0) {
1327
goto exit;
1328
}
1329
diff --git a/block/vhdx.c b/block/vhdx.c
1330
index XXXXXXX..XXXXXXX 100644
1331
--- a/block/vhdx.c
1332
+++ b/block/vhdx.c
1333
@@ -XXX,XX +XXX,XX @@ static int vhdx_write_header(BdrvChild *file, VHDXHeader *hdr,
1334
buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
1335
if (read) {
1336
/* if true, we can't assume the extra reserved bytes are 0 */
1337
- ret = bdrv_pread(file, offset, buffer, VHDX_HEADER_SIZE);
1338
+ ret = bdrv_pread(file, offset, buffer, VHDX_HEADER_SIZE, 0);
1339
if (ret < 0) {
1340
goto exit;
1341
}
1342
@@ -XXX,XX +XXX,XX @@ static int vhdx_write_header(BdrvChild *file, VHDXHeader *hdr,
1343
vhdx_header_le_export(hdr, header_le);
1344
vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
1345
offsetof(VHDXHeader, checksum));
1346
- ret = bdrv_pwrite_sync(file, offset, header_le, sizeof(VHDXHeader));
1347
+ ret = bdrv_pwrite_sync(file, offset, header_le, sizeof(VHDXHeader), 0);
1348
1349
exit:
1350
qemu_vfree(buffer);
1351
@@ -XXX,XX +XXX,XX @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
1352
/* We have to read the whole VHDX_HEADER_SIZE instead of
1353
* sizeof(VHDXHeader), because the checksum is over the whole
1354
* region */
1355
- ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, buffer,
1356
- VHDX_HEADER_SIZE);
1357
+ ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, buffer, VHDX_HEADER_SIZE,
1358
+ 0);
1359
if (ret < 0) {
1360
goto fail;
1361
}
1362
@@ -XXX,XX +XXX,XX @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
1363
}
1364
}
1365
1366
- ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, buffer,
1367
- VHDX_HEADER_SIZE);
1368
+ ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, buffer, VHDX_HEADER_SIZE,
1369
+ 0);
1370
if (ret < 0) {
1371
goto fail;
1372
}
1373
@@ -XXX,XX +XXX,XX @@ static int vhdx_open_region_tables(BlockDriverState *bs, BDRVVHDXState *s)
1374
buffer = qemu_blockalign(bs, VHDX_HEADER_BLOCK_SIZE);
1375
1376
ret = bdrv_pread(bs->file, VHDX_REGION_TABLE_OFFSET, buffer,
1377
- VHDX_HEADER_BLOCK_SIZE);
1378
+ VHDX_HEADER_BLOCK_SIZE, 0);
1379
if (ret < 0) {
1380
goto fail;
1381
}
1382
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1383
buffer = qemu_blockalign(bs, VHDX_METADATA_TABLE_MAX_SIZE);
1384
1385
ret = bdrv_pread(bs->file, s->metadata_rt.file_offset, buffer,
1386
- VHDX_METADATA_TABLE_MAX_SIZE);
1387
+ VHDX_METADATA_TABLE_MAX_SIZE, 0);
1388
if (ret < 0) {
1389
goto exit;
1390
}
1391
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1392
s->metadata_entries.file_parameters_entry.offset
1393
+ s->metadata_rt.file_offset,
1394
&s->params,
1395
- sizeof(s->params));
1396
+ sizeof(s->params),
1397
+ 0);
1398
1399
if (ret < 0) {
1400
goto exit;
1401
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1402
s->metadata_entries.virtual_disk_size_entry.offset
1403
+ s->metadata_rt.file_offset,
1404
&s->virtual_disk_size,
1405
- sizeof(uint64_t));
1406
+ sizeof(uint64_t),
1407
+ 0);
1408
if (ret < 0) {
1409
goto exit;
1410
}
1411
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1412
s->metadata_entries.logical_sector_size_entry.offset
1413
+ s->metadata_rt.file_offset,
1414
&s->logical_sector_size,
1415
- sizeof(uint32_t));
1416
+ sizeof(uint32_t),
1417
+ 0);
1418
if (ret < 0) {
1419
goto exit;
1420
}
1421
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1422
s->metadata_entries.phys_sector_size_entry.offset
1423
+ s->metadata_rt.file_offset,
1424
&s->physical_sector_size,
1425
- sizeof(uint32_t));
1426
+ sizeof(uint32_t),
1427
+ 0);
1428
if (ret < 0) {
1429
goto exit;
1430
}
1431
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
1432
QLIST_INIT(&s->regions);
1433
1434
/* validate the file signature */
1435
- ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t));
1436
+ ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t), 0);
1437
if (ret < 0) {
1438
goto fail;
1439
}
1440
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
1441
goto fail;
1442
}
1443
1444
- ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length);
1445
+ ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length, 0);
1446
if (ret < 0) {
1447
goto fail;
1448
}
1449
diff --git a/block/vmdk.c b/block/vmdk.c
1450
index XXXXXXX..XXXXXXX 100644
1451
--- a/block/vmdk.c
1452
+++ b/block/vmdk.c
1453
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
1454
int ret;
1455
1456
desc = g_malloc0(DESC_SIZE);
1457
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
1458
+ ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1459
if (ret < 0) {
1460
goto out;
1461
}
1462
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
1463
1464
desc = g_malloc0(DESC_SIZE);
1465
tmp_desc = g_malloc0(DESC_SIZE);
1466
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
1467
+ ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1468
if (ret < 0) {
1469
goto out;
1470
}
1471
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
1472
pstrcat(desc, DESC_SIZE, tmp_desc);
1473
}
1474
1475
- ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE);
1476
+ ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1477
1478
out:
1479
g_free(desc);
1480
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
1481
int ret;
1482
1483
desc = g_malloc0(DESC_SIZE + 1);
1484
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE);
1485
+ ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1486
if (ret < 0) {
1487
goto out;
1488
}
1489
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
1490
return -ENOMEM;
1491
}
1492
1493
- ret = bdrv_pread(extent->file,
1494
- extent->l1_table_offset,
1495
- extent->l1_table,
1496
- l1_size);
1497
+ ret = bdrv_pread(extent->file, extent->l1_table_offset, extent->l1_table,
1498
+ l1_size, 0);
1499
if (ret < 0) {
1500
bdrv_refresh_filename(extent->file->bs);
1501
error_setg_errno(errp, -ret,
1502
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
1503
ret = -ENOMEM;
1504
goto fail_l1;
1505
}
1506
- ret = bdrv_pread(extent->file,
1507
- extent->l1_backup_table_offset,
1508
- extent->l1_backup_table,
1509
- l1_size);
1510
+ ret = bdrv_pread(extent->file, extent->l1_backup_table_offset,
1511
+ extent->l1_backup_table, l1_size, 0);
1512
if (ret < 0) {
1513
bdrv_refresh_filename(extent->file->bs);
1514
error_setg_errno(errp, -ret,
1515
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
1516
VMDK3Header header;
1517
VmdkExtent *extent = NULL;
1518
1519
- ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
1520
+ ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header), 0);
1521
if (ret < 0) {
1522
bdrv_refresh_filename(file->bs);
1523
error_setg_errno(errp, -ret,
1524
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_se_sparse(BlockDriverState *bs,
1525
1526
assert(sizeof(const_header) == SECTOR_SIZE);
1527
1528
- ret = bdrv_pread(file, 0, &const_header, sizeof(const_header));
1529
+ ret = bdrv_pread(file, 0, &const_header, sizeof(const_header), 0);
1530
if (ret < 0) {
1531
bdrv_refresh_filename(file->bs);
1532
error_setg_errno(errp, -ret,
1533
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_se_sparse(BlockDriverState *bs,
1534
1535
assert(sizeof(volatile_header) == SECTOR_SIZE);
1536
1537
- ret = bdrv_pread(file,
1538
- const_header.volatile_header_offset * SECTOR_SIZE,
1539
- &volatile_header, sizeof(volatile_header));
1540
+ ret = bdrv_pread(file, const_header.volatile_header_offset * SECTOR_SIZE,
1541
+ &volatile_header, sizeof(volatile_header), 0);
1542
if (ret < 0) {
1543
bdrv_refresh_filename(file->bs);
1544
error_setg_errno(errp, -ret,
1545
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
1546
size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */
1547
buf = g_malloc(size + 1);
1548
1549
- ret = bdrv_pread(file, desc_offset, buf, size);
1550
+ ret = bdrv_pread(file, desc_offset, buf, size, 0);
1551
if (ret < 0) {
1552
error_setg_errno(errp, -ret, "Could not read from file");
1553
g_free(buf);
1554
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
1555
int64_t l1_backup_offset = 0;
1556
bool compressed;
1557
1558
- ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header));
1559
+ ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header), 0);
1560
if (ret < 0) {
1561
bdrv_refresh_filename(file->bs);
1562
error_setg_errno(errp, -ret,
1563
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
1564
} QEMU_PACKED eos_marker;
1565
} QEMU_PACKED footer;
1566
1567
- ret = bdrv_pread(file,
1568
- bs->file->bs->total_sectors * 512 - 1536,
1569
- &footer, sizeof(footer));
1570
+ ret = bdrv_pread(file, bs->file->bs->total_sectors * 512 - 1536,
1571
+ &footer, sizeof(footer), 0);
1572
if (ret < 0) {
1573
error_setg_errno(errp, -ret, "Failed to read footer");
1574
return ret;
1575
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1576
/* qcow2 emits this on bs->file instead of bs->backing */
1577
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
1578
ret = bdrv_pread(bs->backing, offset, whole_grain,
1579
- skip_start_bytes);
1580
+ skip_start_bytes, 0);
1581
if (ret < 0) {
1582
ret = VMDK_ERROR;
1583
goto exit;
1584
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1585
}
1586
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
1587
ret = bdrv_pwrite(extent->file, cluster_offset, whole_grain,
1588
- skip_start_bytes);
1589
+ skip_start_bytes, 0);
1590
if (ret < 0) {
1591
ret = VMDK_ERROR;
1592
goto exit;
1593
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1594
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
1595
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
1596
whole_grain + skip_end_bytes,
1597
- cluster_bytes - skip_end_bytes);
1598
+ cluster_bytes - skip_end_bytes, 0);
1599
if (ret < 0) {
1600
ret = VMDK_ERROR;
1601
goto exit;
1602
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1603
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
1604
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
1605
whole_grain + skip_end_bytes,
1606
- cluster_bytes - skip_end_bytes);
1607
+ cluster_bytes - skip_end_bytes, 0);
1608
if (ret < 0) {
1609
ret = VMDK_ERROR;
1610
goto exit;
1611
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
1612
if (bdrv_pwrite(extent->file,
1613
((int64_t)m_data->l2_offset * 512)
1614
+ (m_data->l2_index * sizeof(offset)),
1615
- &offset, sizeof(offset)) < 0) {
1616
+ &offset, sizeof(offset), 0) < 0) {
1617
return VMDK_ERROR;
1618
}
1619
/* update backup L2 table */
1620
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
1621
if (bdrv_pwrite(extent->file,
1622
((int64_t)m_data->l2_offset * 512)
1623
+ (m_data->l2_index * sizeof(offset)),
1624
- &offset, sizeof(offset)) < 0) {
1625
+ &offset, sizeof(offset), 0) < 0) {
1626
return VMDK_ERROR;
1627
}
1628
}
1629
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
1630
if (bdrv_pread(extent->file,
1631
(int64_t)l2_offset * 512,
1632
l2_table,
1633
- l2_size_bytes
1634
+ l2_size_bytes,
1635
+ 0
1636
) != l2_size_bytes) {
1637
return VMDK_ERROR;
1638
}
1639
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1640
cluster_buf = g_malloc(buf_bytes);
1641
uncomp_buf = g_malloc(cluster_bytes);
1642
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
1643
- ret = bdrv_pread(extent->file,
1644
- cluster_offset,
1645
- cluster_buf, buf_bytes);
1646
+ ret = bdrv_pread(extent->file, cluster_offset, cluster_buf, buf_bytes, 0);
1647
if (ret < 0) {
1648
goto out;
1649
}
1650
diff --git a/block/vpc.c b/block/vpc.c
1651
index XXXXXXX..XXXXXXX 100644
1652
--- a/block/vpc.c
1653
+++ b/block/vpc.c
1654
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1655
goto fail;
1656
}
1657
1658
- ret = bdrv_pread(bs->file, 0, &s->footer, sizeof(s->footer));
1659
+ ret = bdrv_pread(bs->file, 0, &s->footer, sizeof(s->footer), 0);
1660
if (ret < 0) {
1661
error_setg(errp, "Unable to read VHD header");
1662
goto fail;
1663
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1664
}
1665
1666
/* If a fixed disk, the footer is found only at the end of the file */
1667
- ret = bdrv_pread(bs->file, offset - sizeof(*footer),
1668
- footer, sizeof(*footer));
1669
+ ret = bdrv_pread(bs->file, offset - sizeof(*footer), footer,
1670
+ sizeof(*footer), 0);
1671
if (ret < 0) {
1672
goto fail;
1673
}
1674
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1675
1676
if (disk_type == VHD_DYNAMIC) {
1677
ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset),
1678
- &dyndisk_header, sizeof(dyndisk_header));
1679
+ &dyndisk_header, sizeof(dyndisk_header), 0);
1680
if (ret < 0) {
1681
error_setg(errp, "Error reading dynamic VHD header");
1682
goto fail;
1683
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1684
s->bat_offset = be64_to_cpu(dyndisk_header.table_offset);
1685
1686
ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
1687
- pagetable_size);
1688
+ pagetable_size, 0);
1689
if (ret < 0) {
1690
error_setg(errp, "Error reading pagetable");
1691
goto fail;
1692
@@ -XXX,XX +XXX,XX @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
1693
1694
s->last_bitmap_offset = bitmap_offset;
1695
memset(bitmap, 0xff, s->bitmap_size);
1696
- r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size);
1697
+ r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size,
1698
+ 0);
1699
if (r < 0) {
1700
*err = r;
1701
return -2;
1702
@@ -XXX,XX +XXX,XX @@ static int rewrite_footer(BlockDriverState *bs)
1703
BDRVVPCState *s = bs->opaque;
1704
int64_t offset = s->free_data_block_offset;
1705
1706
- ret = bdrv_pwrite_sync(bs->file, offset, &s->footer, sizeof(s->footer));
1707
+ ret = bdrv_pwrite_sync(bs->file, offset, &s->footer, sizeof(s->footer), 0);
1708
if (ret < 0)
1709
return ret;
1710
1711
@@ -XXX,XX +XXX,XX @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset)
1712
/* Initialize the block's bitmap */
1713
memset(bitmap, 0xff, s->bitmap_size);
1714
ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
1715
- s->bitmap_size);
1716
+ s->bitmap_size, 0);
1717
if (ret < 0) {
1718
return ret;
1719
}
1720
@@ -XXX,XX +XXX,XX @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset)
1721
/* Write BAT entry to disk */
1722
bat_offset = s->bat_offset + (4 * index);
1723
bat_value = cpu_to_be32(s->pagetable[index]);
1724
- ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4);
1725
+ ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4, 0);
1726
if (ret < 0)
1727
goto fail;
1728
1729
diff --git a/block/vvfat.c b/block/vvfat.c
1730
index XXXXXXX..XXXXXXX 100644
1731
--- a/block/vvfat.c
1732
+++ b/block/vvfat.c
1733
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1734
" allocated\n", sector_num,
1735
n >> BDRV_SECTOR_BITS));
1736
if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE,
1737
- buf + i * 0x200, n) < 0) {
1738
+ buf + i * 0x200, n, 0) < 0) {
1739
return -1;
1740
}
1741
i += (n >> BDRV_SECTOR_BITS) - 1;
1742
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1743
return -1;
1744
}
1745
res = bdrv_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
1746
- s->cluster_buffer, BDRV_SECTOR_SIZE);
1747
+ s->cluster_buffer, BDRV_SECTOR_SIZE,
1748
+ 0);
1749
if (res < 0) {
1750
return -2;
1751
}
1752
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
1753
*/
1754
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
1755
ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE, buf,
1756
- nb_sectors * BDRV_SECTOR_SIZE);
1757
+ nb_sectors * BDRV_SECTOR_SIZE, 0);
1758
if (ret < 0) {
1759
fprintf(stderr, "Error writing to qcow backend\n");
1760
return ret;
1761
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
1762
index XXXXXXX..XXXXXXX 100644
1763
--- a/tests/unit/test-block-iothread.c
1764
+++ b/tests/unit/test-block-iothread.c
1765
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pread(BdrvChild *c)
1766
int ret;
1767
1768
/* Success */
1769
- ret = bdrv_pread(c, 0, buf, sizeof(buf));
1770
+ ret = bdrv_pread(c, 0, buf, sizeof(buf), 0);
1771
g_assert_cmpint(ret, ==, 512);
1772
1773
/* Early error: Negative offset */
1774
- ret = bdrv_pread(c, -2, buf, sizeof(buf));
1775
+ ret = bdrv_pread(c, -2, buf, sizeof(buf), 0);
1776
g_assert_cmpint(ret, ==, -EIO);
1777
}
1778
1779
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pwrite(BdrvChild *c)
1780
int ret;
1781
1782
/* Success */
1783
- ret = bdrv_pwrite(c, 0, buf, sizeof(buf));
1784
+ ret = bdrv_pwrite(c, 0, buf, sizeof(buf), 0);
1785
g_assert_cmpint(ret, ==, 512);
1786
1787
/* Early error: Negative offset */
1788
- ret = bdrv_pwrite(c, -2, buf, sizeof(buf));
1789
+ ret = bdrv_pwrite(c, -2, buf, sizeof(buf), 0);
1790
g_assert_cmpint(ret, ==, -EIO);
1791
}
1792
1793
--
502
--
1794
2.35.3
503
2.9.3
504
505
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Swap 'buf' and 'bytes' around for consistency with
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
4
blk_co_{pread,pwrite}(), and in preparation to implement these functions
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
5
using generated_co_wrapper.
5
Reviewed-by: Fam Zheng <famz@redhat.com>
6
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7
Message-id: 20170213135235.12274-16-pbonzini@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
10
block/archipelago.c | 3 ---
11
block/block-backend.c | 7 -------
12
block/curl.c | 2 +-
13
block/io.c | 6 +-----
14
block/iscsi.c | 3 ---
15
block/linux-aio.c | 5 +----
16
block/mirror.c | 12 +++++++++---
17
block/null.c | 8 --------
18
block/qed-cluster.c | 2 ++
19
block/qed-table.c | 12 ++++++++++--
20
block/qed.c | 4 ++--
21
block/rbd.c | 4 ----
22
block/win32-aio.c | 3 ---
23
hw/block/virtio-blk.c | 12 +++++++++++-
24
hw/scsi/scsi-disk.c | 15 +++++++++++++++
25
hw/scsi/scsi-generic.c | 20 +++++++++++++++++---
26
util/thread-pool.c | 4 +++-
27
17 files changed, 72 insertions(+), 50 deletions(-)
6
28
7
Callers were updated using this Coccinelle script:
29
diff --git a/block/archipelago.c b/block/archipelago.c
8
30
index XXXXXXX..XXXXXXX 100644
9
@@ expression blk, offset, buf, bytes, flags; @@
31
--- a/block/archipelago.c
10
- blk_pread(blk, offset, buf, bytes, flags)
32
+++ b/block/archipelago.c
11
+ blk_pread(blk, offset, bytes, buf, flags)
33
@@ -XXX,XX +XXX,XX @@ static void qemu_archipelago_complete_aio(void *opaque)
12
34
{
13
@@ expression blk, offset, buf, bytes, flags; @@
35
AIORequestData *reqdata = (AIORequestData *) opaque;
14
- blk_pwrite(blk, offset, buf, bytes, flags)
36
ArchipelagoAIOCB *aio_cb = (ArchipelagoAIOCB *) reqdata->aio_cb;
15
+ blk_pwrite(blk, offset, bytes, buf, flags)
37
- AioContext *ctx = bdrv_get_aio_context(aio_cb->common.bs);
16
38
17
It had no effect on hw/block/nand.c, presumably due to the #if, so that
39
- aio_context_acquire(ctx);
18
file was updated manually.
40
aio_cb->common.cb(aio_cb->common.opaque, aio_cb->ret);
19
41
- aio_context_release(ctx);
20
Overly-long lines were then fixed by hand.
42
aio_cb->status = 0;
21
43
22
Signed-off-by: Alberto Faria <afaria@redhat.com>
44
qemu_aio_unref(aio_cb);
23
Reviewed-by: Eric Blake <eblake@redhat.com>
24
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
25
Message-Id: <20220705161527.1054072-4-afaria@redhat.com>
26
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
27
---
28
include/sysemu/block-backend-io.h | 4 +--
29
block.c | 2 +-
30
block/block-backend.c | 4 +--
31
block/commit.c | 4 +--
32
block/crypto.c | 2 +-
33
block/export/fuse.c | 4 +--
34
block/parallels.c | 2 +-
35
block/qcow.c | 8 +++---
36
block/qcow2.c | 4 +--
37
block/qed.c | 8 +++---
38
block/vdi.c | 4 +--
39
block/vhdx.c | 20 ++++++-------
40
block/vmdk.c | 10 +++----
41
block/vpc.c | 12 ++++----
42
hw/arm/allwinner-h3.c | 2 +-
43
hw/arm/aspeed.c | 2 +-
44
hw/block/block.c | 2 +-
45
hw/block/fdc.c | 20 ++++++-------
46
hw/block/hd-geometry.c | 2 +-
47
hw/block/m25p80.c | 2 +-
48
hw/block/nand.c | 47 ++++++++++++++++---------------
49
hw/block/onenand.c | 32 ++++++++++-----------
50
hw/block/pflash_cfi01.c | 4 +--
51
hw/block/pflash_cfi02.c | 4 +--
52
hw/ide/atapi.c | 4 +--
53
hw/misc/mac_via.c | 4 +--
54
hw/misc/sifive_u_otp.c | 14 ++++-----
55
hw/nvram/eeprom_at24c.c | 4 +--
56
hw/nvram/spapr_nvram.c | 6 ++--
57
hw/nvram/xlnx-bbram.c | 4 +--
58
hw/nvram/xlnx-efuse.c | 4 +--
59
hw/ppc/pnv_pnor.c | 6 ++--
60
hw/sd/sd.c | 4 +--
61
migration/block.c | 6 ++--
62
nbd/server.c | 8 +++---
63
qemu-img.c | 18 ++++++------
64
qemu-io-cmds.c | 4 +--
65
tests/unit/test-block-iothread.c | 8 +++---
66
38 files changed, 150 insertions(+), 149 deletions(-)
67
68
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/include/sysemu/block-backend-io.h
71
+++ b/include/sysemu/block-backend-io.h
72
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
73
* the "I/O or GS" API.
74
*/
75
76
-int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes,
77
+int blk_pread(BlockBackend *blk, int64_t offset, int bytes, void *buf,
78
BdrvRequestFlags flags);
79
-int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int bytes,
80
+int blk_pwrite(BlockBackend *blk, int64_t offset, int bytes, const void *buf,
81
BdrvRequestFlags flags);
82
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
83
int64_t bytes, QEMUIOVector *qiov,
84
diff --git a/block.c b/block.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/block.c
87
+++ b/block.c
88
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
89
return ret;
90
}
91
92
- ret = blk_pread(file, 0, buf, sizeof(buf), 0);
93
+ ret = blk_pread(file, 0, sizeof(buf), buf, 0);
94
if (ret < 0) {
95
error_setg_errno(errp, -ret, "Could not read image for determining its "
96
"format");
97
diff --git a/block/block-backend.c b/block/block-backend.c
45
diff --git a/block/block-backend.c b/block/block-backend.c
98
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
99
--- a/block/block-backend.c
47
--- a/block/block-backend.c
100
+++ b/block/block-backend.c
48
+++ b/block/block-backend.c
101
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
49
@@ -XXX,XX +XXX,XX @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags)
102
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
50
static void error_callback_bh(void *opaque)
103
}
51
{
104
52
struct BlockBackendAIOCB *acb = opaque;
105
-int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes,
53
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
106
+int blk_pread(BlockBackend *blk, int64_t offset, int bytes, void *buf,
54
107
BdrvRequestFlags flags)
55
bdrv_dec_in_flight(acb->common.bs);
108
{
56
- aio_context_acquire(ctx);
57
acb->common.cb(acb->common.opaque, acb->ret);
58
- aio_context_release(ctx);
59
qemu_aio_unref(acb);
60
}
61
62
@@ -XXX,XX +XXX,XX @@ static void blk_aio_complete(BlkAioEmAIOCB *acb)
63
static void blk_aio_complete_bh(void *opaque)
64
{
65
BlkAioEmAIOCB *acb = opaque;
66
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
67
-
68
assert(acb->has_returned);
69
- aio_context_acquire(ctx);
70
blk_aio_complete(acb);
71
- aio_context_release(ctx);
72
}
73
74
static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, int bytes,
75
diff --git a/block/curl.c b/block/curl.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/block/curl.c
78
+++ b/block/curl.c
79
@@ -XXX,XX +XXX,XX @@ static void curl_readv_bh_cb(void *p)
80
curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running);
81
82
out:
83
+ aio_context_release(ctx);
84
if (ret != -EINPROGRESS) {
85
acb->common.cb(acb->common.opaque, ret);
86
qemu_aio_unref(acb);
87
}
88
- aio_context_release(ctx);
89
}
90
91
static BlockAIOCB *curl_aio_readv(BlockDriverState *bs,
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 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
97
CoroutineIOCompletion *co = opaque;
98
99
co->ret = ret;
100
- qemu_coroutine_enter(co->coroutine);
101
+ aio_co_wake(co->coroutine);
102
}
103
104
static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
105
@@ -XXX,XX +XXX,XX @@ static void bdrv_co_complete(BlockAIOCBCoroutine *acb)
106
static void bdrv_co_em_bh(void *opaque)
107
{
108
BlockAIOCBCoroutine *acb = opaque;
109
- BlockDriverState *bs = acb->common.bs;
110
- AioContext *ctx = bdrv_get_aio_context(bs);
111
112
assert(!acb->need_bh);
113
- aio_context_acquire(ctx);
114
bdrv_co_complete(acb);
115
- aio_context_release(ctx);
116
}
117
118
static void bdrv_co_maybe_schedule_bh(BlockAIOCBCoroutine *acb)
119
diff --git a/block/iscsi.c b/block/iscsi.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/block/iscsi.c
122
+++ b/block/iscsi.c
123
@@ -XXX,XX +XXX,XX @@ static void
124
iscsi_bh_cb(void *p)
125
{
126
IscsiAIOCB *acb = p;
127
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
128
129
qemu_bh_delete(acb->bh);
130
131
g_free(acb->buf);
132
acb->buf = NULL;
133
134
- aio_context_acquire(ctx);
135
acb->common.cb(acb->common.opaque, acb->status);
136
- aio_context_release(ctx);
137
138
if (acb->task != NULL) {
139
scsi_free_scsi_task(acb->task);
140
diff --git a/block/linux-aio.c b/block/linux-aio.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/block/linux-aio.c
143
+++ b/block/linux-aio.c
144
@@ -XXX,XX +XXX,XX @@ static inline ssize_t io_event_ret(struct io_event *ev)
145
*/
146
static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
147
{
148
- LinuxAioState *s = laiocb->ctx;
109
int ret;
149
int ret;
110
@@ -XXX,XX +XXX,XX @@ int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes,
150
111
return ret;
151
ret = laiocb->ret;
112
}
152
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
113
153
}
114
-int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int bytes,
154
115
+int blk_pwrite(BlockBackend *blk, int64_t offset, int bytes, const void *buf,
155
laiocb->ret = ret;
116
BdrvRequestFlags flags)
156
- aio_context_acquire(s->aio_context);
117
{
157
if (laiocb->co) {
118
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
158
/* If the coroutine is already entered it must be in ioq_submit() and
119
diff --git a/block/commit.c b/block/commit.c
159
* will notice laio->ret has been filled in when it eventually runs
120
index XXXXXXX..XXXXXXX 100644
160
@@ -XXX,XX +XXX,XX @@ static void qemu_laio_process_completion(struct qemu_laiocb *laiocb)
121
--- a/block/commit.c
161
* that!
122
+++ b/block/commit.c
162
*/
123
@@ -XXX,XX +XXX,XX @@ int bdrv_commit(BlockDriverState *bs)
163
if (!qemu_coroutine_entered(laiocb->co)) {
124
goto ro_cleanup;
164
- qemu_coroutine_enter(laiocb->co);
165
+ aio_co_wake(laiocb->co);
125
}
166
}
126
if (ret) {
167
} else {
127
- ret = blk_pread(src, offset, buf, n, 0);
168
laiocb->common.cb(laiocb->common.opaque, ret);
128
+ ret = blk_pread(src, offset, n, buf, 0);
169
qemu_aio_unref(laiocb);
129
if (ret < 0) {
170
}
130
goto ro_cleanup;
171
- aio_context_release(s->aio_context);
131
}
172
}
132
173
133
- ret = blk_pwrite(backing, offset, buf, n, 0);
174
/**
134
+ ret = blk_pwrite(backing, offset, n, buf, 0);
175
diff --git a/block/mirror.c b/block/mirror.c
135
if (ret < 0) {
176
index XXXXXXX..XXXXXXX 100644
136
goto ro_cleanup;
177
--- a/block/mirror.c
137
}
178
+++ b/block/mirror.c
138
diff --git a/block/crypto.c b/block/crypto.c
179
@@ -XXX,XX +XXX,XX @@ static void mirror_write_complete(void *opaque, int ret)
139
index XXXXXXX..XXXXXXX 100644
180
{
140
--- a/block/crypto.c
181
MirrorOp *op = opaque;
141
+++ b/block/crypto.c
182
MirrorBlockJob *s = op->s;
142
@@ -XXX,XX +XXX,XX @@ static int block_crypto_create_write_func(QCryptoBlock *block,
183
+
143
struct BlockCryptoCreateData *data = opaque;
184
+ aio_context_acquire(blk_get_aio_context(s->common.blk));
144
ssize_t ret;
145
146
- ret = blk_pwrite(data->blk, offset, buf, buflen, 0);
147
+ ret = blk_pwrite(data->blk, offset, buflen, buf, 0);
148
if (ret < 0) {
185
if (ret < 0) {
149
error_setg_errno(errp, -ret, "Could not write encryption header");
186
BlockErrorAction action;
150
return ret;
187
151
diff --git a/block/export/fuse.c b/block/export/fuse.c
188
@@ -XXX,XX +XXX,XX @@ static void mirror_write_complete(void *opaque, int ret)
152
index XXXXXXX..XXXXXXX 100644
189
}
153
--- a/block/export/fuse.c
190
}
154
+++ b/block/export/fuse.c
191
mirror_iteration_done(op, ret);
155
@@ -XXX,XX +XXX,XX @@ static void fuse_read(fuse_req_t req, fuse_ino_t inode,
192
+ aio_context_release(blk_get_aio_context(s->common.blk));
193
}
194
195
static void mirror_read_complete(void *opaque, int ret)
196
{
197
MirrorOp *op = opaque;
198
MirrorBlockJob *s = op->s;
199
+
200
+ aio_context_acquire(blk_get_aio_context(s->common.blk));
201
if (ret < 0) {
202
BlockErrorAction action;
203
204
@@ -XXX,XX +XXX,XX @@ static void mirror_read_complete(void *opaque, int ret)
205
}
206
207
mirror_iteration_done(op, ret);
208
- return;
209
+ } else {
210
+ blk_aio_pwritev(s->target, op->sector_num * BDRV_SECTOR_SIZE, &op->qiov,
211
+ 0, mirror_write_complete, op);
212
}
213
- blk_aio_pwritev(s->target, op->sector_num * BDRV_SECTOR_SIZE, &op->qiov,
214
- 0, mirror_write_complete, op);
215
+ aio_context_release(blk_get_aio_context(s->common.blk));
216
}
217
218
static inline void mirror_clip_sectors(MirrorBlockJob *s,
219
diff --git a/block/null.c b/block/null.c
220
index XXXXXXX..XXXXXXX 100644
221
--- a/block/null.c
222
+++ b/block/null.c
223
@@ -XXX,XX +XXX,XX @@ static const AIOCBInfo null_aiocb_info = {
224
static void null_bh_cb(void *opaque)
225
{
226
NullAIOCB *acb = opaque;
227
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
228
-
229
- aio_context_acquire(ctx);
230
acb->common.cb(acb->common.opaque, 0);
231
- aio_context_release(ctx);
232
qemu_aio_unref(acb);
233
}
234
235
static void null_timer_cb(void *opaque)
236
{
237
NullAIOCB *acb = opaque;
238
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
239
-
240
- aio_context_acquire(ctx);
241
acb->common.cb(acb->common.opaque, 0);
242
- aio_context_release(ctx);
243
timer_deinit(&acb->timer);
244
qemu_aio_unref(acb);
245
}
246
diff --git a/block/qed-cluster.c b/block/qed-cluster.c
247
index XXXXXXX..XXXXXXX 100644
248
--- a/block/qed-cluster.c
249
+++ b/block/qed-cluster.c
250
@@ -XXX,XX +XXX,XX @@ static void qed_find_cluster_cb(void *opaque, int ret)
251
unsigned int index;
252
unsigned int n;
253
254
+ qed_acquire(s);
255
if (ret) {
256
goto out;
257
}
258
@@ -XXX,XX +XXX,XX @@ static void qed_find_cluster_cb(void *opaque, int ret)
259
260
out:
261
find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
262
+ qed_release(s);
263
g_free(find_cluster_cb);
264
}
265
266
diff --git a/block/qed-table.c b/block/qed-table.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/block/qed-table.c
269
+++ b/block/qed-table.c
270
@@ -XXX,XX +XXX,XX @@ static void qed_read_table_cb(void *opaque, int ret)
271
{
272
QEDReadTableCB *read_table_cb = opaque;
273
QEDTable *table = read_table_cb->table;
274
+ BDRVQEDState *s = read_table_cb->s;
275
int noffsets = read_table_cb->qiov.size / sizeof(uint64_t);
276
int i;
277
278
@@ -XXX,XX +XXX,XX @@ static void qed_read_table_cb(void *opaque, int ret)
279
}
280
281
/* Byteswap offsets */
282
+ qed_acquire(s);
283
for (i = 0; i < noffsets; i++) {
284
table->offsets[i] = le64_to_cpu(table->offsets[i]);
285
}
286
+ qed_release(s);
287
288
out:
289
/* Completion */
290
- trace_qed_read_table_cb(read_table_cb->s, read_table_cb->table, ret);
291
+ trace_qed_read_table_cb(s, read_table_cb->table, ret);
292
gencb_complete(&read_table_cb->gencb, ret);
293
}
294
295
@@ -XXX,XX +XXX,XX @@ typedef struct {
296
static void qed_write_table_cb(void *opaque, int ret)
297
{
298
QEDWriteTableCB *write_table_cb = opaque;
299
+ BDRVQEDState *s = write_table_cb->s;
300
301
- trace_qed_write_table_cb(write_table_cb->s,
302
+ trace_qed_write_table_cb(s,
303
write_table_cb->orig_table,
304
write_table_cb->flush,
305
ret);
306
@@ -XXX,XX +XXX,XX @@ static void qed_write_table_cb(void *opaque, int ret)
307
if (write_table_cb->flush) {
308
/* We still need to flush first */
309
write_table_cb->flush = false;
310
+ qed_acquire(s);
311
bdrv_aio_flush(write_table_cb->s->bs, qed_write_table_cb,
312
write_table_cb);
313
+ qed_release(s);
156
return;
314
return;
157
}
315
}
158
316
159
- ret = blk_pread(exp->common.blk, offset, buf, size, 0);
317
@@ -XXX,XX +XXX,XX @@ static void qed_read_l2_table_cb(void *opaque, int ret)
160
+ ret = blk_pread(exp->common.blk, offset, size, buf, 0);
318
CachedL2Table *l2_table = request->l2_table;
161
if (ret >= 0) {
319
uint64_t l2_offset = read_l2_table_cb->l2_offset;
162
fuse_reply_buf(req, buf, size);
320
163
} else {
321
+ qed_acquire(s);
164
@@ -XXX,XX +XXX,XX @@ static void fuse_write(fuse_req_t req, fuse_ino_t inode, const char *buf,
322
if (ret) {
165
}
323
/* can't trust loaded L2 table anymore */
166
}
324
qed_unref_l2_cache_entry(l2_table);
167
325
@@ -XXX,XX +XXX,XX @@ static void qed_read_l2_table_cb(void *opaque, int ret)
168
- ret = blk_pwrite(exp->common.blk, offset, buf, size, 0);
326
request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
169
+ ret = blk_pwrite(exp->common.blk, offset, size, buf, 0);
327
assert(request->l2_table != NULL);
170
if (ret >= 0) {
328
}
171
fuse_reply_write(req, size);
329
+ qed_release(s);
172
} else {
330
173
diff --git a/block/parallels.c b/block/parallels.c
331
gencb_complete(&read_l2_table_cb->gencb, ret);
174
index XXXXXXX..XXXXXXX 100644
332
}
175
--- a/block/parallels.c
176
+++ b/block/parallels.c
177
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_create(BlockdevCreateOptions* opts,
178
memset(tmp, 0, sizeof(tmp));
179
memcpy(tmp, &header, sizeof(header));
180
181
- ret = blk_pwrite(blk, 0, tmp, BDRV_SECTOR_SIZE, 0);
182
+ ret = blk_pwrite(blk, 0, BDRV_SECTOR_SIZE, tmp, 0);
183
if (ret < 0) {
184
goto exit;
185
}
186
diff --git a/block/qcow.c b/block/qcow.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/block/qcow.c
189
+++ b/block/qcow.c
190
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
191
}
192
193
/* write all the data */
194
- ret = blk_pwrite(qcow_blk, 0, &header, sizeof(header), 0);
195
+ ret = blk_pwrite(qcow_blk, 0, sizeof(header), &header, 0);
196
if (ret < 0) {
197
goto exit;
198
}
199
200
if (qcow_opts->has_backing_file) {
201
- ret = blk_pwrite(qcow_blk, sizeof(header),
202
- qcow_opts->backing_file, backing_filename_len, 0);
203
+ ret = blk_pwrite(qcow_blk, sizeof(header), backing_filename_len,
204
+ qcow_opts->backing_file, 0);
205
if (ret < 0) {
206
goto exit;
207
}
208
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
209
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
210
i++) {
211
ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
212
- tmp, BDRV_SECTOR_SIZE, 0);
213
+ BDRV_SECTOR_SIZE, tmp, 0);
214
if (ret < 0) {
215
g_free(tmp);
216
goto exit;
217
diff --git a/block/qcow2.c b/block/qcow2.c
218
index XXXXXXX..XXXXXXX 100644
219
--- a/block/qcow2.c
220
+++ b/block/qcow2.c
221
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
222
cpu_to_be64(QCOW2_INCOMPAT_EXTL2);
223
}
224
225
- ret = blk_pwrite(blk, 0, header, cluster_size, 0);
226
+ ret = blk_pwrite(blk, 0, cluster_size, header, 0);
227
g_free(header);
228
if (ret < 0) {
229
error_setg_errno(errp, -ret, "Could not write qcow2 header");
230
@@ -XXX,XX +XXX,XX @@ qcow2_co_create(BlockdevCreateOptions *create_options, Error **errp)
231
/* Write a refcount table with one refcount block */
232
refcount_table = g_malloc0(2 * cluster_size);
233
refcount_table[0] = cpu_to_be64(2 * cluster_size);
234
- ret = blk_pwrite(blk, cluster_size, refcount_table, 2 * cluster_size, 0);
235
+ ret = blk_pwrite(blk, cluster_size, 2 * cluster_size, refcount_table, 0);
236
g_free(refcount_table);
237
238
if (ret < 0) {
239
diff --git a/block/qed.c b/block/qed.c
333
diff --git a/block/qed.c b/block/qed.c
240
index XXXXXXX..XXXXXXX 100644
334
index XXXXXXX..XXXXXXX 100644
241
--- a/block/qed.c
335
--- a/block/qed.c
242
+++ b/block/qed.c
336
+++ b/block/qed.c
243
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_co_create(BlockdevCreateOptions *opts,
337
@@ -XXX,XX +XXX,XX @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
244
}
338
}
245
339
246
qed_header_cpu_to_le(&header, &le_header);
340
if (cb->co) {
247
- ret = blk_pwrite(blk, 0, &le_header, sizeof(le_header), 0);
341
- qemu_coroutine_enter(cb->co);
248
+ ret = blk_pwrite(blk, 0, sizeof(le_header), &le_header, 0);
342
+ aio_co_wake(cb->co);
343
}
344
}
345
346
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qed_co_pwrite_zeroes_cb(void *opaque, int ret)
347
cb->done = true;
348
cb->ret = ret;
349
if (cb->co) {
350
- qemu_coroutine_enter(cb->co);
351
+ aio_co_wake(cb->co);
352
}
353
}
354
355
diff --git a/block/rbd.c b/block/rbd.c
356
index XXXXXXX..XXXXXXX 100644
357
--- a/block/rbd.c
358
+++ b/block/rbd.c
359
@@ -XXX,XX +XXX,XX @@ shutdown:
360
static void qemu_rbd_complete_aio(RADOSCB *rcb)
361
{
362
RBDAIOCB *acb = rcb->acb;
363
- AioContext *ctx = bdrv_get_aio_context(acb->common.bs);
364
int64_t r;
365
366
r = rcb->ret;
367
@@ -XXX,XX +XXX,XX @@ static void qemu_rbd_complete_aio(RADOSCB *rcb)
368
qemu_iovec_from_buf(acb->qiov, 0, acb->bounce, acb->qiov->size);
369
}
370
qemu_vfree(acb->bounce);
371
-
372
- aio_context_acquire(ctx);
373
acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
374
- aio_context_release(ctx);
375
376
qemu_aio_unref(acb);
377
}
378
diff --git a/block/win32-aio.c b/block/win32-aio.c
379
index XXXXXXX..XXXXXXX 100644
380
--- a/block/win32-aio.c
381
+++ b/block/win32-aio.c
382
@@ -XXX,XX +XXX,XX @@ static void win32_aio_process_completion(QEMUWin32AIOState *s,
383
qemu_vfree(waiocb->buf);
384
}
385
386
-
387
- aio_context_acquire(s->aio_ctx);
388
waiocb->common.cb(waiocb->common.opaque, ret);
389
- aio_context_release(s->aio_ctx);
390
qemu_aio_unref(waiocb);
391
}
392
393
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
394
index XXXXXXX..XXXXXXX 100644
395
--- a/hw/block/virtio-blk.c
396
+++ b/hw/block/virtio-blk.c
397
@@ -XXX,XX +XXX,XX @@ static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
398
static void virtio_blk_rw_complete(void *opaque, int ret)
399
{
400
VirtIOBlockReq *next = opaque;
401
+ VirtIOBlock *s = next->dev;
402
403
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
404
while (next) {
405
VirtIOBlockReq *req = next;
406
next = req->mr_next;
407
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_rw_complete(void *opaque, int ret)
408
block_acct_done(blk_get_stats(req->dev->blk), &req->acct);
409
virtio_blk_free_request(req);
410
}
411
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
412
}
413
414
static void virtio_blk_flush_complete(void *opaque, int ret)
415
{
416
VirtIOBlockReq *req = opaque;
417
+ VirtIOBlock *s = req->dev;
418
419
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
420
if (ret) {
421
if (virtio_blk_handle_rw_error(req, -ret, 0)) {
422
- return;
423
+ goto out;
424
}
425
}
426
427
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
428
block_acct_done(blk_get_stats(req->dev->blk), &req->acct);
429
virtio_blk_free_request(req);
430
+
431
+out:
432
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
433
}
434
435
#ifdef __linux__
436
@@ -XXX,XX +XXX,XX @@ static void virtio_blk_ioctl_complete(void *opaque, int status)
437
virtio_stl_p(vdev, &scsi->data_len, hdr->dxfer_len);
438
439
out:
440
+ aio_context_acquire(blk_get_aio_context(s->conf.conf.blk));
441
virtio_blk_req_complete(req, status);
442
virtio_blk_free_request(req);
443
+ aio_context_release(blk_get_aio_context(s->conf.conf.blk));
444
g_free(ioctl_req);
445
}
446
447
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
448
index XXXXXXX..XXXXXXX 100644
449
--- a/hw/scsi/scsi-disk.c
450
+++ b/hw/scsi/scsi-disk.c
451
@@ -XXX,XX +XXX,XX @@ static void scsi_aio_complete(void *opaque, int ret)
452
453
assert(r->req.aiocb != NULL);
454
r->req.aiocb = NULL;
455
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
456
if (scsi_disk_req_check_error(r, ret, true)) {
457
goto done;
458
}
459
@@ -XXX,XX +XXX,XX @@ static void scsi_aio_complete(void *opaque, int ret)
460
scsi_req_complete(&r->req, GOOD);
461
462
done:
463
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
464
scsi_req_unref(&r->req);
465
}
466
467
@@ -XXX,XX +XXX,XX @@ static void scsi_dma_complete(void *opaque, int ret)
468
assert(r->req.aiocb != NULL);
469
r->req.aiocb = NULL;
470
471
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
249
if (ret < 0) {
472
if (ret < 0) {
250
goto out;
473
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
251
}
474
} else {
252
- ret = blk_pwrite(blk, sizeof(le_header), qed_opts->backing_file,
475
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
253
- header.backing_filename_size, 0);
476
}
254
+ ret = blk_pwrite(blk, sizeof(le_header), header.backing_filename_size,
477
scsi_dma_complete_noio(r, ret);
255
+ qed_opts->backing_file, 0);
478
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
479
}
480
481
static void scsi_read_complete(void * opaque, int ret)
482
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
483
484
assert(r->req.aiocb != NULL);
485
r->req.aiocb = NULL;
486
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
487
if (scsi_disk_req_check_error(r, ret, true)) {
488
goto done;
489
}
490
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
491
492
done:
493
scsi_req_unref(&r->req);
494
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
495
}
496
497
/* Actually issue a read to the block device. */
498
@@ -XXX,XX +XXX,XX @@ static void scsi_do_read_cb(void *opaque, int ret)
499
assert (r->req.aiocb != NULL);
500
r->req.aiocb = NULL;
501
502
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
256
if (ret < 0) {
503
if (ret < 0) {
257
goto out;
504
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
258
}
505
} else {
259
506
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
260
l1_table = g_malloc0(l1_size);
507
}
261
- ret = blk_pwrite(blk, header.l1_table_offset, l1_table, l1_size, 0);
508
scsi_do_read(opaque, ret);
262
+ ret = blk_pwrite(blk, header.l1_table_offset, l1_size, l1_table, 0);
509
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
510
}
511
512
/* Read more data from scsi device into buffer. */
513
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
514
assert (r->req.aiocb != NULL);
515
r->req.aiocb = NULL;
516
517
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
263
if (ret < 0) {
518
if (ret < 0) {
264
goto out;
519
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
265
}
266
diff --git a/block/vdi.c b/block/vdi.c
267
index XXXXXXX..XXXXXXX 100644
268
--- a/block/vdi.c
269
+++ b/block/vdi.c
270
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
271
vdi_header_print(&header);
272
}
273
vdi_header_to_le(&header);
274
- ret = blk_pwrite(blk, offset, &header, sizeof(header), 0);
275
+ ret = blk_pwrite(blk, offset, sizeof(header), &header, 0);
276
if (ret < 0) {
277
error_setg(errp, "Error writing header");
278
goto exit;
279
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
280
bmap[i] = VDI_UNALLOCATED;
281
}
282
}
283
- ret = blk_pwrite(blk, offset, bmap, bmap_size, 0);
284
+ ret = blk_pwrite(blk, offset, bmap_size, bmap, 0);
285
if (ret < 0) {
286
error_setg(errp, "Error writing bmap");
287
goto exit;
288
diff --git a/block/vhdx.c b/block/vhdx.c
289
index XXXXXXX..XXXXXXX 100644
290
--- a/block/vhdx.c
291
+++ b/block/vhdx.c
292
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_new_metadata(BlockBackend *blk,
293
VHDX_META_FLAGS_IS_VIRTUAL_DISK;
294
vhdx_metadata_entry_le_export(&md_table_entry[4]);
295
296
- ret = blk_pwrite(blk, metadata_offset, buffer, VHDX_HEADER_BLOCK_SIZE, 0);
297
+ ret = blk_pwrite(blk, metadata_offset, VHDX_HEADER_BLOCK_SIZE, buffer, 0);
298
if (ret < 0) {
299
goto exit;
300
}
301
302
- ret = blk_pwrite(blk, metadata_offset + (64 * KiB), entry_buffer,
303
- VHDX_METADATA_ENTRY_BUFFER_SIZE, 0);
304
+ ret = blk_pwrite(blk, metadata_offset + (64 * KiB),
305
+ VHDX_METADATA_ENTRY_BUFFER_SIZE, entry_buffer, 0);
306
if (ret < 0) {
307
goto exit;
308
}
309
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
310
s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
311
sector_num += s->sectors_per_block;
312
}
313
- ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
314
+ ret = blk_pwrite(blk, file_offset, length, s->bat, 0);
315
if (ret < 0) {
316
error_setg_errno(errp, -ret, "Failed to write the BAT");
317
goto exit;
318
@@ -XXX,XX +XXX,XX @@ static int vhdx_create_new_region_table(BlockBackend *blk,
319
}
320
321
/* Now write out the region headers to disk */
322
- ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, buffer,
323
- VHDX_HEADER_BLOCK_SIZE, 0);
324
+ ret = blk_pwrite(blk, VHDX_REGION_TABLE_OFFSET, VHDX_HEADER_BLOCK_SIZE,
325
+ buffer, 0);
326
if (ret < 0) {
327
error_setg_errno(errp, -ret, "Failed to write first region table");
328
goto exit;
329
}
330
331
- ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, buffer,
332
- VHDX_HEADER_BLOCK_SIZE, 0);
333
+ ret = blk_pwrite(blk, VHDX_REGION_TABLE2_OFFSET, VHDX_HEADER_BLOCK_SIZE,
334
+ buffer, 0);
335
if (ret < 0) {
336
error_setg_errno(errp, -ret, "Failed to write second region table");
337
goto exit;
338
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
339
creator = g_utf8_to_utf16("QEMU v" QEMU_VERSION, -1, NULL,
340
&creator_items, NULL);
341
signature = cpu_to_le64(VHDX_FILE_SIGNATURE);
342
- ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, &signature, sizeof(signature),
343
+ ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET, sizeof(signature), &signature,
344
0);
345
if (ret < 0) {
346
error_setg_errno(errp, -ret, "Failed to write file signature");
347
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
348
}
349
if (creator) {
350
ret = blk_pwrite(blk, VHDX_FILE_ID_OFFSET + sizeof(signature),
351
- creator, creator_items * sizeof(gunichar2), 0);
352
+ creator_items * sizeof(gunichar2), creator, 0);
353
if (ret < 0) {
354
error_setg_errno(errp, -ret, "Failed to write creator field");
355
goto delete_and_exit;
356
diff --git a/block/vmdk.c b/block/vmdk.c
357
index XXXXXXX..XXXXXXX 100644
358
--- a/block/vmdk.c
359
+++ b/block/vmdk.c
360
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
361
header.check_bytes[3] = 0xa;
362
363
/* write all the data */
364
- ret = blk_pwrite(blk, 0, &magic, sizeof(magic), 0);
365
+ ret = blk_pwrite(blk, 0, sizeof(magic), &magic, 0);
366
if (ret < 0) {
367
error_setg(errp, QERR_IO_ERROR);
368
goto exit;
369
}
370
- ret = blk_pwrite(blk, sizeof(magic), &header, sizeof(header), 0);
371
+ ret = blk_pwrite(blk, sizeof(magic), sizeof(header), &header, 0);
372
if (ret < 0) {
373
error_setg(errp, QERR_IO_ERROR);
374
goto exit;
375
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
376
gd_buf[i] = cpu_to_le32(tmp);
377
}
378
ret = blk_pwrite(blk, le64_to_cpu(header.rgd_offset) * BDRV_SECTOR_SIZE,
379
- gd_buf, gd_buf_size, 0);
380
+ gd_buf_size, gd_buf, 0);
381
if (ret < 0) {
382
error_setg(errp, QERR_IO_ERROR);
383
goto exit;
384
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_extent(BlockBackend *blk,
385
gd_buf[i] = cpu_to_le32(tmp);
386
}
387
ret = blk_pwrite(blk, le64_to_cpu(header.gd_offset) * BDRV_SECTOR_SIZE,
388
- gd_buf, gd_buf_size, 0);
389
+ gd_buf_size, gd_buf, 0);
390
if (ret < 0) {
391
error_setg(errp, QERR_IO_ERROR);
392
}
393
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn vmdk_co_do_create(int64_t size,
394
desc_offset = 0x200;
395
}
396
397
- ret = blk_pwrite(blk, desc_offset, desc, desc_len, 0);
398
+ ret = blk_pwrite(blk, desc_offset, desc_len, desc, 0);
399
if (ret < 0) {
400
error_setg_errno(errp, -ret, "Could not write description");
401
goto exit;
402
diff --git a/block/vpc.c b/block/vpc.c
403
index XXXXXXX..XXXXXXX 100644
404
--- a/block/vpc.c
405
+++ b/block/vpc.c
406
@@ -XXX,XX +XXX,XX @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer,
407
block_size = 0x200000;
408
num_bat_entries = DIV_ROUND_UP(total_sectors, block_size / 512);
409
410
- ret = blk_pwrite(blk, offset, footer, sizeof(*footer), 0);
411
+ ret = blk_pwrite(blk, offset, sizeof(*footer), footer, 0);
412
if (ret < 0) {
413
goto fail;
414
}
415
416
offset = 1536 + ((num_bat_entries * 4 + 511) & ~511);
417
- ret = blk_pwrite(blk, offset, footer, sizeof(*footer), 0);
418
+ ret = blk_pwrite(blk, offset, sizeof(*footer), footer, 0);
419
if (ret < 0) {
420
goto fail;
421
}
422
@@ -XXX,XX +XXX,XX @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer,
423
424
memset(bat_sector, 0xFF, 512);
425
for (i = 0; i < DIV_ROUND_UP(num_bat_entries * 4, 512); i++) {
426
- ret = blk_pwrite(blk, offset, bat_sector, 512, 0);
427
+ ret = blk_pwrite(blk, offset, 512, bat_sector, 0);
428
if (ret < 0) {
429
goto fail;
430
}
431
@@ -XXX,XX +XXX,XX @@ static int create_dynamic_disk(BlockBackend *blk, VHDFooter *footer,
432
/* Write the header */
433
offset = 512;
434
435
- ret = blk_pwrite(blk, offset, &dyndisk_header, sizeof(dyndisk_header), 0);
436
+ ret = blk_pwrite(blk, offset, sizeof(dyndisk_header), &dyndisk_header, 0);
437
if (ret < 0) {
438
goto fail;
439
}
440
@@ -XXX,XX +XXX,XX @@ static int create_fixed_disk(BlockBackend *blk, VHDFooter *footer,
441
return ret;
442
}
443
444
- ret = blk_pwrite(blk, total_size - sizeof(*footer),
445
- footer, sizeof(*footer), 0);
446
+ ret = blk_pwrite(blk, total_size - sizeof(*footer), sizeof(*footer),
447
+ footer, 0);
448
if (ret < 0) {
449
error_setg_errno(errp, -ret, "Unable to write VHD header");
450
return ret;
451
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
452
index XXXXXXX..XXXXXXX 100644
453
--- a/hw/arm/allwinner-h3.c
454
+++ b/hw/arm/allwinner-h3.c
455
@@ -XXX,XX +XXX,XX @@ void allwinner_h3_bootrom_setup(AwH3State *s, BlockBackend *blk)
456
const int64_t rom_size = 32 * KiB;
457
g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
458
459
- if (blk_pread(blk, 8 * KiB, buffer, rom_size, 0) < 0) {
460
+ if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
461
error_setg(&error_fatal, "%s: failed to read BlockBackend data",
462
__func__);
463
return;
464
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
465
index XXXXXXX..XXXXXXX 100644
466
--- a/hw/arm/aspeed.c
467
+++ b/hw/arm/aspeed.c
468
@@ -XXX,XX +XXX,XX @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size,
469
}
470
471
storage = g_malloc0(rom_size);
472
- if (blk_pread(blk, 0, storage, rom_size, 0) < 0) {
473
+ if (blk_pread(blk, 0, rom_size, storage, 0) < 0) {
474
error_setg(errp, "failed to read the initial flash content");
475
return;
476
}
477
diff --git a/hw/block/block.c b/hw/block/block.c
478
index XXXXXXX..XXXXXXX 100644
479
--- a/hw/block/block.c
480
+++ b/hw/block/block.c
481
@@ -XXX,XX +XXX,XX @@ bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size,
482
* block device and read only on demand.
483
*/
484
assert(size <= BDRV_REQUEST_MAX_BYTES);
485
- ret = blk_pread(blk, 0, buf, size, 0);
486
+ ret = blk_pread(blk, 0, size, buf, 0);
487
if (ret < 0) {
488
error_setg_errno(errp, -ret, "can't read block backend");
489
return false;
490
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
491
index XXXXXXX..XXXXXXX 100644
492
--- a/hw/block/fdc.c
493
+++ b/hw/block/fdc.c
494
@@ -XXX,XX +XXX,XX @@ int fdctrl_transfer_handler(void *opaque, int nchan, int dma_pos, int dma_len)
495
if (fdctrl->data_dir != FD_DIR_WRITE ||
496
len < FD_SECTOR_LEN || rel_pos != 0) {
497
/* READ & SCAN commands and realign to a sector for WRITE */
498
- if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
499
- BDRV_SECTOR_SIZE, 0) < 0) {
500
+ if (blk_pread(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE,
501
+ fdctrl->fifo, 0) < 0) {
502
FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
503
fd_sector(cur_drv));
504
/* Sure, image size is too small... */
505
@@ -XXX,XX +XXX,XX @@ int fdctrl_transfer_handler(void *opaque, int nchan, int dma_pos, int dma_len)
506
507
k->read_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos,
508
fdctrl->data_pos, len);
509
- if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv),
510
- fdctrl->fifo, BDRV_SECTOR_SIZE, 0) < 0) {
511
+ if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE,
512
+ fdctrl->fifo, 0) < 0) {
513
FLOPPY_DPRINTF("error writing sector %d\n",
514
fd_sector(cur_drv));
515
fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
516
@@ -XXX,XX +XXX,XX @@ static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
517
fd_sector(cur_drv));
518
return 0;
519
}
520
- if (blk_pread(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
521
- BDRV_SECTOR_SIZE, 0)
522
+ if (blk_pread(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE,
523
+ fdctrl->fifo, 0)
524
< 0) {
525
FLOPPY_DPRINTF("error getting sector %d\n",
526
fd_sector(cur_drv));
527
@@ -XXX,XX +XXX,XX @@ static void fdctrl_format_sector(FDCtrl *fdctrl)
528
}
529
memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
530
if (cur_drv->blk == NULL ||
531
- blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
532
- BDRV_SECTOR_SIZE, 0) < 0) {
533
+ blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE,
534
+ fdctrl->fifo, 0) < 0) {
535
FLOPPY_DPRINTF("error formatting sector %d\n", fd_sector(cur_drv));
536
fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
537
} else {
520
} else {
538
@@ -XXX,XX +XXX,XX @@ static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
521
block_acct_done(blk_get_stats(s->qdev.conf.blk), &r->acct);
539
if (pos == FD_SECTOR_LEN - 1 ||
522
}
540
fdctrl->data_pos == fdctrl->data_len) {
523
scsi_write_complete_noio(r, ret);
541
cur_drv = get_cur_drv(fdctrl);
524
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
542
- if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), fdctrl->fifo,
525
}
543
- BDRV_SECTOR_SIZE, 0) < 0) {
526
544
+ if (blk_pwrite(cur_drv->blk, fd_offset(cur_drv), BDRV_SECTOR_SIZE,
527
static void scsi_write_data(SCSIRequest *req)
545
+ fdctrl->fifo, 0) < 0) {
528
@@ -XXX,XX +XXX,XX @@ static void scsi_unmap_complete(void *opaque, int ret)
546
FLOPPY_DPRINTF("error writing sector %d\n",
529
{
547
fd_sector(cur_drv));
530
UnmapCBData *data = opaque;
548
break;
531
SCSIDiskReq *r = data->r;
549
diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c
532
+ SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
550
index XXXXXXX..XXXXXXX 100644
533
551
--- a/hw/block/hd-geometry.c
534
assert(r->req.aiocb != NULL);
552
+++ b/hw/block/hd-geometry.c
535
r->req.aiocb = NULL;
553
@@ -XXX,XX +XXX,XX @@ static int guess_disk_lchs(BlockBackend *blk,
536
554
537
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
555
blk_get_geometry(blk, &nb_sectors);
538
scsi_unmap_complete_noio(data, ret);
556
539
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
557
- if (blk_pread(blk, 0, buf, BDRV_SECTOR_SIZE, 0) < 0) {
540
}
558
+ if (blk_pread(blk, 0, BDRV_SECTOR_SIZE, buf, 0) < 0) {
541
559
return -1;
542
static void scsi_disk_emulate_unmap(SCSIDiskReq *r, uint8_t *inbuf)
560
}
543
@@ -XXX,XX +XXX,XX @@ static void scsi_write_same_complete(void *opaque, int ret)
561
/* test msdos magic */
544
562
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
545
assert(r->req.aiocb != NULL);
563
index XXXXXXX..XXXXXXX 100644
546
r->req.aiocb = NULL;
564
--- a/hw/block/m25p80.c
547
+ aio_context_acquire(blk_get_aio_context(s->qdev.conf.blk));
565
+++ b/hw/block/m25p80.c
548
if (scsi_disk_req_check_error(r, ret, true)) {
566
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSIPeripheral *ss, Error **errp)
549
goto done;
567
trace_m25p80_binding(s);
550
}
568
s->storage = blk_blockalign(s->blk, s->size);
551
@@ -XXX,XX +XXX,XX @@ done:
569
552
scsi_req_unref(&r->req);
570
- if (blk_pread(s->blk, 0, s->storage, s->size, 0) < 0) {
553
qemu_vfree(data->iov.iov_base);
571
+ if (blk_pread(s->blk, 0, s->size, s->storage, 0) < 0) {
554
g_free(data);
572
error_setg(errp, "failed to read the initial flash content");
555
+ aio_context_release(blk_get_aio_context(s->qdev.conf.blk));
573
return;
556
}
574
}
557
575
diff --git a/hw/block/nand.c b/hw/block/nand.c
558
static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
576
index XXXXXXX..XXXXXXX 100644
559
diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c
577
--- a/hw/block/nand.c
560
index XXXXXXX..XXXXXXX 100644
578
+++ b/hw/block/nand.c
561
--- a/hw/scsi/scsi-generic.c
579
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_write_, NAND_PAGE_SIZE)(NANDFlashState *s)
562
+++ b/hw/scsi/scsi-generic.c
580
sector = SECTOR(s->addr);
563
@@ -XXX,XX +XXX,XX @@ done:
581
off = (s->addr & PAGE_MASK) + s->offset;
564
static void scsi_command_complete(void *opaque, int ret)
582
soff = SECTOR_OFFSET(s->addr);
565
{
583
- if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
566
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
584
- PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
567
+ SCSIDevice *s = r->req.dev;
585
+ if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS,
568
586
+ PAGE_SECTORS << BDRV_SECTOR_BITS, iobuf, 0) < 0) {
569
assert(r->req.aiocb != NULL);
587
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
570
r->req.aiocb = NULL;
588
return;
571
+
589
}
572
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
590
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_write_, NAND_PAGE_SIZE)(NANDFlashState *s)
573
scsi_command_complete_noio(r, ret);
591
MIN(OOB_SIZE, off + s->iolen - NAND_PAGE_SIZE));
574
+ aio_context_release(blk_get_aio_context(s->conf.blk));
592
}
575
}
593
576
594
- if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
577
static int execute_command(BlockBackend *blk,
595
- PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
578
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
596
+ if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS,
579
assert(r->req.aiocb != NULL);
597
+ PAGE_SECTORS << BDRV_SECTOR_BITS, iobuf, 0) < 0) {
580
r->req.aiocb = NULL;
598
printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
581
599
}
582
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
600
} else {
583
+
601
off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset;
584
if (ret || r->req.io_canceled) {
602
sector = off >> 9;
585
scsi_command_complete_noio(r, ret);
603
soff = off & 0x1ff;
586
- return;
604
- if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
587
+ goto done;
605
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
588
}
606
+ if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS,
589
607
+ (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, iobuf, 0) < 0) {
590
len = r->io_header.dxfer_len - r->io_header.resid;
608
printf("%s: read error in sector %" PRIu64 "\n", __func__, sector);
591
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
609
return;
592
r->len = -1;
610
}
593
if (len == 0) {
611
594
scsi_command_complete_noio(r, 0);
612
mem_and(iobuf + soff, s->io, s->iolen);
595
- return;
613
596
+ goto done;
614
- if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf,
597
}
615
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
598
616
+ if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS,
599
/* Snoop READ CAPACITY output to set the blocksize. */
617
+ (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, iobuf, 0) < 0) {
600
@@ -XXX,XX +XXX,XX @@ static void scsi_read_complete(void * opaque, int ret)
618
printf("%s: write error in sector %" PRIu64 "\n", __func__, sector);
601
}
619
}
602
scsi_req_data(&r->req, len);
620
}
603
scsi_req_unref(&r->req);
621
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
604
+
622
i = SECTOR(addr);
605
+done:
623
page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift)));
606
+ aio_context_release(blk_get_aio_context(s->conf.blk));
624
for (; i < page; i ++)
607
}
625
- if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, iobuf,
608
626
- BDRV_SECTOR_SIZE, 0) < 0) {
609
/* Read more data from scsi device into buffer. */
627
+ if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS,
610
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
628
+ BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
611
assert(r->req.aiocb != NULL);
629
printf("%s: write error in sector %" PRIu64 "\n", __func__, i);
612
r->req.aiocb = NULL;
630
}
613
631
} else {
614
+ aio_context_acquire(blk_get_aio_context(s->conf.blk));
632
addr = PAGE_START(addr);
615
+
633
page = addr >> 9;
616
if (ret || r->req.io_canceled) {
634
- if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
617
scsi_command_complete_noio(r, ret);
635
- BDRV_SECTOR_SIZE, 0) < 0) {
618
- return;
636
+ if (blk_pread(s->blk, page << BDRV_SECTOR_BITS,
619
+ goto done;
637
+ BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
620
}
638
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
621
639
}
622
if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 &&
640
memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1);
623
@@ -XXX,XX +XXX,XX @@ static void scsi_write_complete(void * opaque, int ret)
641
- if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
624
}
642
- BDRV_SECTOR_SIZE, 0) < 0) {
625
643
+ if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS,
626
scsi_command_complete_noio(r, ret);
644
+ BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
627
+
645
printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
628
+done:
646
}
629
+ aio_context_release(blk_get_aio_context(s->conf.blk));
647
630
}
648
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s)
631
649
i = (addr & ~0x1ff) + 0x200;
632
/* Write data to a scsi device. Returns nonzero on failure.
650
for (addr += ((NAND_PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200;
633
diff --git a/util/thread-pool.c b/util/thread-pool.c
651
i < addr; i += 0x200) {
634
index XXXXXXX..XXXXXXX 100644
652
- if (blk_pwrite(s->blk, i, iobuf, BDRV_SECTOR_SIZE, 0) < 0) {
635
--- a/util/thread-pool.c
653
+ if (blk_pwrite(s->blk, i, BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
636
+++ b/util/thread-pool.c
654
printf("%s: write error in sector %" PRIu64 "\n",
637
@@ -XXX,XX +XXX,XX @@ restart:
655
__func__, i >> 9);
638
*/
656
}
639
qemu_bh_schedule(pool->completion_bh);
657
}
640
658
641
+ aio_context_release(pool->ctx);
659
page = i >> 9;
642
elem->common.cb(elem->common.opaque, elem->ret);
660
- if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf,
643
+ aio_context_acquire(pool->ctx);
661
- BDRV_SECTOR_SIZE, 0) < 0) {
644
qemu_aio_unref(elem);
662
+ if (blk_pread(s->blk, page << BDRV_SECTOR_BITS,
645
goto restart;
663
+ BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
664
printf("%s: read error in sector %" PRIu64 "\n", __func__, page);
665
}
666
memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1);
667
- if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf,
668
- BDRV_SECTOR_SIZE, 0) < 0) {
669
+ if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS,
670
+ BDRV_SECTOR_SIZE, iobuf, 0) < 0) {
671
printf("%s: write error in sector %" PRIu64 "\n", __func__, page);
672
}
673
}
674
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
675
676
if (s->blk) {
677
if (s->mem_oob) {
678
- if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io,
679
- PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) {
680
+ if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS,
681
+ PAGE_SECTORS << BDRV_SECTOR_BITS, s->io, 0) < 0) {
682
printf("%s: read error in sector %" PRIu64 "\n",
683
__func__, SECTOR(addr));
684
}
685
@@ -XXX,XX +XXX,XX @@ static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s,
686
OOB_SIZE);
687
s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset;
688
} else {
646
} else {
689
- if (blk_pread(s->blk, PAGE_START(addr), s->io,
647
@@ -XXX,XX +XXX,XX @@ static void thread_pool_co_cb(void *opaque, int ret)
690
- (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) {
648
ThreadPoolCo *co = opaque;
691
+ if (blk_pread(s->blk, PAGE_START(addr),
649
692
+ (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, s->io, 0)
650
co->ret = ret;
693
+ < 0) {
651
- qemu_coroutine_enter(co->co);
694
printf("%s: read error in sector %" PRIu64 "\n",
652
+ aio_co_wake(co->co);
695
__func__, PAGE_START(addr) >> 9);
653
}
696
}
654
697
diff --git a/hw/block/onenand.c b/hw/block/onenand.c
655
int coroutine_fn thread_pool_submit_co(ThreadPool *pool, ThreadPoolFunc *func,
698
index XXXXXXX..XXXXXXX 100644
699
--- a/hw/block/onenand.c
700
+++ b/hw/block/onenand.c
701
@@ -XXX,XX +XXX,XX @@ static void onenand_reset(OneNANDState *s, int cold)
702
/* Lock the whole flash */
703
memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
704
705
- if (s->blk_cur && blk_pread(s->blk_cur, 0, s->boot[0],
706
- 8 << BDRV_SECTOR_BITS, 0) < 0) {
707
+ if (s->blk_cur && blk_pread(s->blk_cur, 0, 8 << BDRV_SECTOR_BITS,
708
+ s->boot[0], 0) < 0) {
709
hw_error("%s: Loading the BootRAM failed.\n", __func__);
710
}
711
}
712
@@ -XXX,XX +XXX,XX @@ static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
713
assert(UINT32_MAX >> BDRV_SECTOR_BITS > sec);
714
assert(UINT32_MAX >> BDRV_SECTOR_BITS > secn);
715
if (s->blk_cur) {
716
- return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS, dest,
717
- secn << BDRV_SECTOR_BITS, 0) < 0;
718
+ return blk_pread(s->blk_cur, sec << BDRV_SECTOR_BITS,
719
+ secn << BDRV_SECTOR_BITS, dest, 0) < 0;
720
} else if (sec + secn > s->secs_cur) {
721
return 1;
722
}
723
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
724
uint8_t *dp = 0;
725
if (s->blk_cur) {
726
dp = g_malloc(size);
727
- if (!dp || blk_pread(s->blk_cur, offset, dp, size, 0) < 0) {
728
+ if (!dp || blk_pread(s->blk_cur, offset, size, dp, 0) < 0) {
729
result = 1;
730
}
731
} else {
732
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
733
dp[i] &= sp[i];
734
}
735
if (s->blk_cur) {
736
- result = blk_pwrite(s->blk_cur, offset, dp, size, 0) < 0;
737
+ result = blk_pwrite(s->blk_cur, offset, size, dp, 0) < 0;
738
}
739
}
740
if (dp && s->blk_cur) {
741
@@ -XXX,XX +XXX,XX @@ static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
742
743
if (s->blk_cur) {
744
uint32_t offset = (s->secs_cur + (sec >> 5)) << BDRV_SECTOR_BITS;
745
- if (blk_pread(s->blk_cur, offset, buf, BDRV_SECTOR_SIZE, 0) < 0) {
746
+ if (blk_pread(s->blk_cur, offset, BDRV_SECTOR_SIZE, buf, 0) < 0) {
747
return 1;
748
}
749
memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
750
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
751
if (s->blk_cur) {
752
dp = g_malloc(512);
753
if (!dp
754
- || blk_pread(s->blk_cur, offset, dp, BDRV_SECTOR_SIZE, 0) < 0) {
755
+ || blk_pread(s->blk_cur, offset, BDRV_SECTOR_SIZE, dp, 0) < 0) {
756
result = 1;
757
} else {
758
dpp = dp + ((sec & 31) << 4);
759
@@ -XXX,XX +XXX,XX @@ static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
760
dpp[i] &= sp[i];
761
}
762
if (s->blk_cur) {
763
- result = blk_pwrite(s->blk_cur, offset, dp,
764
- BDRV_SECTOR_SIZE, 0) < 0;
765
+ result = blk_pwrite(s->blk_cur, offset, BDRV_SECTOR_SIZE, dp,
766
+ 0) < 0;
767
}
768
}
769
g_free(dp);
770
@@ -XXX,XX +XXX,XX @@ static inline int onenand_erase(OneNANDState *s, int sec, int num)
771
for (; num > 0; num--, sec++) {
772
if (s->blk_cur) {
773
int erasesec = s->secs_cur + (sec >> 5);
774
- if (blk_pwrite(s->blk_cur, sec << BDRV_SECTOR_BITS, blankbuf,
775
- BDRV_SECTOR_SIZE, 0) < 0) {
776
+ if (blk_pwrite(s->blk_cur, sec << BDRV_SECTOR_BITS,
777
+ BDRV_SECTOR_SIZE, blankbuf, 0) < 0) {
778
goto fail;
779
}
780
- if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
781
- BDRV_SECTOR_SIZE, 0) < 0) {
782
+ if (blk_pread(s->blk_cur, erasesec << BDRV_SECTOR_BITS,
783
+ BDRV_SECTOR_SIZE, tmpbuf, 0) < 0) {
784
goto fail;
785
}
786
memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
787
- if (blk_pwrite(s->blk_cur, erasesec << BDRV_SECTOR_BITS, tmpbuf,
788
- BDRV_SECTOR_SIZE, 0) < 0) {
789
+ if (blk_pwrite(s->blk_cur, erasesec << BDRV_SECTOR_BITS,
790
+ BDRV_SECTOR_SIZE, tmpbuf, 0) < 0) {
791
goto fail;
792
}
793
} else {
794
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
795
index XXXXXXX..XXXXXXX 100644
796
--- a/hw/block/pflash_cfi01.c
797
+++ b/hw/block/pflash_cfi01.c
798
@@ -XXX,XX +XXX,XX @@ static void pflash_update(PFlashCFI01 *pfl, int offset,
799
/* widen to sector boundaries */
800
offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
801
offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
802
- ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset,
803
- offset_end - offset, 0);
804
+ ret = blk_pwrite(pfl->blk, offset, offset_end - offset,
805
+ pfl->storage + offset, 0);
806
if (ret < 0) {
807
/* TODO set error bit in status */
808
error_report("Could not update PFLASH: %s", strerror(-ret));
809
diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c
810
index XXXXXXX..XXXXXXX 100644
811
--- a/hw/block/pflash_cfi02.c
812
+++ b/hw/block/pflash_cfi02.c
813
@@ -XXX,XX +XXX,XX @@ static void pflash_update(PFlashCFI02 *pfl, int offset, int size)
814
/* widen to sector boundaries */
815
offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
816
offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
817
- ret = blk_pwrite(pfl->blk, offset, pfl->storage + offset,
818
- offset_end - offset, 0);
819
+ ret = blk_pwrite(pfl->blk, offset, offset_end - offset,
820
+ pfl->storage + offset, 0);
821
if (ret < 0) {
822
/* TODO set error bit in status */
823
error_report("Could not update PFLASH: %s", strerror(-ret));
824
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
825
index XXXXXXX..XXXXXXX 100644
826
--- a/hw/ide/atapi.c
827
+++ b/hw/ide/atapi.c
828
@@ -XXX,XX +XXX,XX @@ cd_read_sector_sync(IDEState *s)
829
switch (s->cd_sector_size) {
830
case 2048:
831
ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
832
- s->io_buffer, ATAPI_SECTOR_SIZE, 0);
833
+ ATAPI_SECTOR_SIZE, s->io_buffer, 0);
834
break;
835
case 2352:
836
ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
837
- s->io_buffer + 16, ATAPI_SECTOR_SIZE, 0);
838
+ ATAPI_SECTOR_SIZE, s->io_buffer + 16, 0);
839
if (ret >= 0) {
840
cd_data_to_raw(s->io_buffer, s->lba);
841
}
842
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
843
index XXXXXXX..XXXXXXX 100644
844
--- a/hw/misc/mac_via.c
845
+++ b/hw/misc/mac_via.c
846
@@ -XXX,XX +XXX,XX @@ static void via1_one_second(void *opaque)
847
static void pram_update(MOS6522Q800VIA1State *v1s)
848
{
849
if (v1s->blk) {
850
- if (blk_pwrite(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM), 0) < 0) {
851
+ if (blk_pwrite(v1s->blk, 0, sizeof(v1s->PRAM), v1s->PRAM, 0) < 0) {
852
qemu_log("pram_update: cannot write to file\n");
853
}
854
}
855
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
856
return;
857
}
858
859
- ret = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM), 0);
860
+ ret = blk_pread(v1s->blk, 0, sizeof(v1s->PRAM), v1s->PRAM, 0);
861
if (ret < 0) {
862
error_setg(errp, "can't read PRAM contents");
863
return;
864
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
865
index XXXXXXX..XXXXXXX 100644
866
--- a/hw/misc/sifive_u_otp.c
867
+++ b/hw/misc/sifive_u_otp.c
868
@@ -XXX,XX +XXX,XX @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
869
if (s->blk) {
870
int32_t buf;
871
872
- if (blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
873
- SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
874
+ if (blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD,
875
+ SIFIVE_U_OTP_FUSE_WORD, &buf, 0) < 0) {
876
error_report("read error index<%d>", s->pa);
877
return 0xff;
878
}
879
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
880
/* write to backend */
881
if (s->blk) {
882
if (blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD,
883
- &s->fuse[s->pa], SIFIVE_U_OTP_FUSE_WORD,
884
- 0) < 0) {
885
+ SIFIVE_U_OTP_FUSE_WORD, &s->fuse[s->pa], 0)
886
+ < 0) {
887
error_report("write error index<%d>", s->pa);
888
}
889
}
890
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
891
return;
892
}
893
894
- if (blk_pread(s->blk, 0, s->fuse, filesize, 0) < 0) {
895
+ if (blk_pread(s->blk, 0, filesize, s->fuse, 0) < 0) {
896
error_setg(errp, "failed to read the initial flash content");
897
return;
898
}
899
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
900
901
serial_data = s->serial;
902
if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
903
- &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
904
+ SIFIVE_U_OTP_FUSE_WORD, &serial_data, 0) < 0) {
905
error_setg(errp, "failed to write index<%d>", index);
906
return;
907
}
908
909
serial_data = ~(s->serial);
910
if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
911
- &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
912
+ SIFIVE_U_OTP_FUSE_WORD, &serial_data, 0) < 0) {
913
error_setg(errp, "failed to write index<%d>", index + 1);
914
return;
915
}
916
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
917
index XXXXXXX..XXXXXXX 100644
918
--- a/hw/nvram/eeprom_at24c.c
919
+++ b/hw/nvram/eeprom_at24c.c
920
@@ -XXX,XX +XXX,XX @@ int at24c_eeprom_event(I2CSlave *s, enum i2c_event event)
921
case I2C_START_RECV:
922
DPRINTK("clear\n");
923
if (ee->blk && ee->changed) {
924
- int ret = blk_pwrite(ee->blk, 0, ee->mem, ee->rsize, 0);
925
+ int ret = blk_pwrite(ee->blk, 0, ee->rsize, ee->mem, 0);
926
if (ret < 0) {
927
ERR(TYPE_AT24C_EE
928
" : failed to write backing file\n");
929
@@ -XXX,XX +XXX,XX @@ void at24c_eeprom_reset(DeviceState *state)
930
memset(ee->mem, 0, ee->rsize);
931
932
if (ee->blk) {
933
- int ret = blk_pread(ee->blk, 0, ee->mem, ee->rsize, 0);
934
+ int ret = blk_pread(ee->blk, 0, ee->rsize, ee->mem, 0);
935
936
if (ret < 0) {
937
ERR(TYPE_AT24C_EE
938
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
939
index XXXXXXX..XXXXXXX 100644
940
--- a/hw/nvram/spapr_nvram.c
941
+++ b/hw/nvram/spapr_nvram.c
942
@@ -XXX,XX +XXX,XX @@ static void rtas_nvram_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
943
944
ret = 0;
945
if (nvram->blk) {
946
- ret = blk_pwrite(nvram->blk, offset, membuf, len, 0);
947
+ ret = blk_pwrite(nvram->blk, offset, len, membuf, 0);
948
}
949
950
assert(nvram->buf);
951
@@ -XXX,XX +XXX,XX @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
952
}
953
954
if (nvram->blk) {
955
- ret = blk_pread(nvram->blk, 0, nvram->buf, nvram->size, 0);
956
+ ret = blk_pread(nvram->blk, 0, nvram->size, nvram->buf, 0);
957
958
if (ret < 0) {
959
error_setg(errp, "can't read spapr-nvram contents");
960
@@ -XXX,XX +XXX,XX @@ static void postload_update_cb(void *opaque, bool running, RunState state)
961
qemu_del_vm_change_state_handler(nvram->vmstate);
962
nvram->vmstate = NULL;
963
964
- blk_pwrite(nvram->blk, 0, nvram->buf, nvram->size, 0);
965
+ blk_pwrite(nvram->blk, 0, nvram->size, nvram->buf, 0);
966
}
967
968
static int spapr_nvram_post_load(void *opaque, int version_id)
969
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
970
index XXXXXXX..XXXXXXX 100644
971
--- a/hw/nvram/xlnx-bbram.c
972
+++ b/hw/nvram/xlnx-bbram.c
973
@@ -XXX,XX +XXX,XX @@ static void bbram_bdrv_read(XlnxBBRam *s, Error **errp)
974
blk_name(s->blk));
975
}
976
977
- if (blk_pread(s->blk, 0, ram, nr, 0) < 0) {
978
+ if (blk_pread(s->blk, 0, nr, ram, 0) < 0) {
979
error_setg(errp,
980
"%s: Failed to read %u bytes from BBRAM backstore.",
981
blk_name(s->blk), nr);
982
@@ -XXX,XX +XXX,XX @@ static void bbram_bdrv_sync(XlnxBBRam *s, uint64_t hwaddr)
983
}
984
985
offset = hwaddr - A_BBRAM_0;
986
- rc = blk_pwrite(s->blk, offset, &le32, 4, 0);
987
+ rc = blk_pwrite(s->blk, offset, 4, &le32, 0);
988
if (rc < 0) {
989
bbram_bdrv_error(s, rc, g_strdup_printf("write to offset %u", offset));
990
}
991
diff --git a/hw/nvram/xlnx-efuse.c b/hw/nvram/xlnx-efuse.c
992
index XXXXXXX..XXXXXXX 100644
993
--- a/hw/nvram/xlnx-efuse.c
994
+++ b/hw/nvram/xlnx-efuse.c
995
@@ -XXX,XX +XXX,XX @@ static int efuse_bdrv_read(XlnxEFuse *s, Error **errp)
996
blk_name(s->blk));
997
}
998
999
- if (blk_pread(s->blk, 0, ram, nr, 0) < 0) {
1000
+ if (blk_pread(s->blk, 0, nr, ram, 0) < 0) {
1001
error_setg(errp, "%s: Failed to read %u bytes from eFUSE backstore.",
1002
blk_name(s->blk), nr);
1003
return -1;
1004
@@ -XXX,XX +XXX,XX @@ static void efuse_bdrv_sync(XlnxEFuse *s, unsigned int bit)
1005
le32 = cpu_to_le32(xlnx_efuse_get_row(s, bit));
1006
1007
row_offset = (bit / 32) * 4;
1008
- if (blk_pwrite(s->blk, row_offset, &le32, 4, 0) < 0) {
1009
+ if (blk_pwrite(s->blk, row_offset, 4, &le32, 0) < 0) {
1010
error_report("%s: Failed to write offset %u of eFUSE backstore.",
1011
blk_name(s->blk), row_offset);
1012
}
1013
diff --git a/hw/ppc/pnv_pnor.c b/hw/ppc/pnv_pnor.c
1014
index XXXXXXX..XXXXXXX 100644
1015
--- a/hw/ppc/pnv_pnor.c
1016
+++ b/hw/ppc/pnv_pnor.c
1017
@@ -XXX,XX +XXX,XX @@ static void pnv_pnor_update(PnvPnor *s, int offset, int size)
1018
offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE);
1019
offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE);
1020
1021
- ret = blk_pwrite(s->blk, offset, s->storage + offset,
1022
- offset_end - offset, 0);
1023
+ ret = blk_pwrite(s->blk, offset, offset_end - offset, s->storage + offset,
1024
+ 0);
1025
if (ret < 0) {
1026
error_report("Could not update PNOR offset=0x%" PRIx32" : %s", offset,
1027
strerror(-ret));
1028
@@ -XXX,XX +XXX,XX @@ static void pnv_pnor_realize(DeviceState *dev, Error **errp)
1029
1030
s->storage = blk_blockalign(s->blk, s->size);
1031
1032
- if (blk_pread(s->blk, 0, s->storage, s->size, 0) < 0) {
1033
+ if (blk_pread(s->blk, 0, s->size, s->storage, 0) < 0) {
1034
error_setg(errp, "failed to read the initial flash content");
1035
return;
1036
}
1037
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
1038
index XXXXXXX..XXXXXXX 100644
1039
--- a/hw/sd/sd.c
1040
+++ b/hw/sd/sd.c
1041
@@ -XXX,XX +XXX,XX @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert)
1042
static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
1043
{
1044
trace_sdcard_read_block(addr, len);
1045
- if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len, 0) < 0) {
1046
+ if (!sd->blk || blk_pread(sd->blk, addr, len, sd->data, 0) < 0) {
1047
fprintf(stderr, "sd_blk_read: read error on host side\n");
1048
}
1049
}
1050
@@ -XXX,XX +XXX,XX @@ static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len)
1051
static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
1052
{
1053
trace_sdcard_write_block(addr, len);
1054
- if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) {
1055
+ if (!sd->blk || blk_pwrite(sd->blk, addr, len, sd->data, 0) < 0) {
1056
fprintf(stderr, "sd_blk_write: write error on host side\n");
1057
}
1058
}
1059
diff --git a/migration/block.c b/migration/block.c
1060
index XXXXXXX..XXXXXXX 100644
1061
--- a/migration/block.c
1062
+++ b/migration/block.c
1063
@@ -XXX,XX +XXX,XX @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
1064
blk_mig_unlock();
1065
} else {
1066
ret = blk_pread(bmds->blk, sector * BDRV_SECTOR_SIZE,
1067
- blk->buf, nr_sectors * BDRV_SECTOR_SIZE, 0);
1068
+ nr_sectors * BDRV_SECTOR_SIZE, blk->buf, 0);
1069
if (ret < 0) {
1070
goto error;
1071
}
1072
@@ -XXX,XX +XXX,XX @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
1073
cluster_size,
1074
BDRV_REQ_MAY_UNMAP);
1075
} else {
1076
- ret = blk_pwrite(blk, cur_addr, cur_buf,
1077
- cluster_size, 0);
1078
+ ret = blk_pwrite(blk, cur_addr, cluster_size, cur_buf,
1079
+ 0);
1080
}
1081
if (ret < 0) {
1082
break;
1083
diff --git a/nbd/server.c b/nbd/server.c
1084
index XXXXXXX..XXXXXXX 100644
1085
--- a/nbd/server.c
1086
+++ b/nbd/server.c
1087
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
1088
stl_be_p(&chunk.length, pnum);
1089
ret = nbd_co_send_iov(client, iov, 1, errp);
1090
} else {
1091
- ret = blk_pread(exp->common.blk, offset + progress,
1092
- data + progress, pnum, 0);
1093
+ ret = blk_pread(exp->common.blk, offset + progress, pnum,
1094
+ data + progress, 0);
1095
if (ret < 0) {
1096
error_setg_errno(errp, -ret, "reading from file failed");
1097
break;
1098
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_do_cmd_read(NBDClient *client, NBDRequest *request,
1099
data, request->len, errp);
1100
}
1101
1102
- ret = blk_pread(exp->common.blk, request->from, data, request->len, 0);
1103
+ ret = blk_pread(exp->common.blk, request->from, request->len, data, 0);
1104
if (ret < 0) {
1105
return nbd_send_generic_reply(client, request->handle, ret,
1106
"reading from file failed", errp);
1107
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
1108
if (request->flags & NBD_CMD_FLAG_FUA) {
1109
flags |= BDRV_REQ_FUA;
1110
}
1111
- ret = blk_pwrite(exp->common.blk, request->from, data, request->len,
1112
+ ret = blk_pwrite(exp->common.blk, request->from, request->len, data,
1113
flags);
1114
return nbd_send_generic_reply(client, request->handle, ret,
1115
"writing to file failed", errp);
1116
diff --git a/qemu-img.c b/qemu-img.c
1117
index XXXXXXX..XXXXXXX 100644
1118
--- a/qemu-img.c
1119
+++ b/qemu-img.c
1120
@@ -XXX,XX +XXX,XX @@ static int check_empty_sectors(BlockBackend *blk, int64_t offset,
1121
int ret = 0;
1122
int64_t idx;
1123
1124
- ret = blk_pread(blk, offset, buffer, bytes, 0);
1125
+ ret = blk_pread(blk, offset, bytes, buffer, 0);
1126
if (ret < 0) {
1127
error_report("Error while reading offset %" PRId64 " of %s: %s",
1128
offset, filename, strerror(-ret));
1129
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
1130
int64_t pnum;
1131
1132
chunk = MIN(chunk, IO_BUF_SIZE);
1133
- ret = blk_pread(blk1, offset, buf1, chunk, 0);
1134
+ ret = blk_pread(blk1, offset, chunk, buf1, 0);
1135
if (ret < 0) {
1136
error_report("Error while reading offset %" PRId64
1137
" of %s: %s",
1138
@@ -XXX,XX +XXX,XX @@ static int img_compare(int argc, char **argv)
1139
ret = 4;
1140
goto out;
1141
}
1142
- ret = blk_pread(blk2, offset, buf2, chunk, 0);
1143
+ ret = blk_pread(blk2, offset, chunk, buf2, 0);
1144
if (ret < 0) {
1145
error_report("Error while reading offset %" PRId64
1146
" of %s: %s",
1147
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
1148
n = old_backing_size - offset;
1149
}
1150
1151
- ret = blk_pread(blk_old_backing, offset, buf_old, n, 0);
1152
+ ret = blk_pread(blk_old_backing, offset, n, buf_old, 0);
1153
if (ret < 0) {
1154
error_report("error while reading from old backing file");
1155
goto out;
1156
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
1157
n = new_backing_size - offset;
1158
}
1159
1160
- ret = blk_pread(blk_new_backing, offset, buf_new, n, 0);
1161
+ ret = blk_pread(blk_new_backing, offset, n, buf_new, 0);
1162
if (ret < 0) {
1163
error_report("error while reading from new backing file");
1164
goto out;
1165
@@ -XXX,XX +XXX,XX @@ static int img_rebase(int argc, char **argv)
1166
if (buf_old_is_zero) {
1167
ret = blk_pwrite_zeroes(blk, offset + written, pnum, 0);
1168
} else {
1169
- ret = blk_pwrite(blk, offset + written,
1170
- buf_old + written, pnum, 0);
1171
+ ret = blk_pwrite(blk, offset + written, pnum,
1172
+ buf_old + written, 0);
1173
}
1174
if (ret < 0) {
1175
error_report("Error while writing to COW image: %s",
1176
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
1177
for (out_pos = 0; in_pos < size; block_count++) {
1178
int bytes = (in_pos + in.bsz > size) ? size - in_pos : in.bsz;
1179
1180
- ret = blk_pread(blk1, in_pos, in.buf, bytes, 0);
1181
+ ret = blk_pread(blk1, in_pos, bytes, in.buf, 0);
1182
if (ret < 0) {
1183
error_report("error while reading from input image file: %s",
1184
strerror(-ret));
1185
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
1186
}
1187
in_pos += bytes;
1188
1189
- ret = blk_pwrite(blk2, out_pos, in.buf, bytes, 0);
1190
+ ret = blk_pwrite(blk2, out_pos, bytes, in.buf, 0);
1191
if (ret < 0) {
1192
error_report("error while writing to output image file: %s",
1193
strerror(-ret));
1194
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
1195
index XXXXXXX..XXXXXXX 100644
1196
--- a/qemu-io-cmds.c
1197
+++ b/qemu-io-cmds.c
1198
@@ -XXX,XX +XXX,XX @@ static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
1199
return -ERANGE;
1200
}
1201
1202
- ret = blk_pread(blk, offset, (uint8_t *)buf, bytes, 0);
1203
+ ret = blk_pread(blk, offset, bytes, (uint8_t *)buf, 0);
1204
if (ret < 0) {
1205
return ret;
1206
}
1207
@@ -XXX,XX +XXX,XX @@ static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
1208
return -ERANGE;
1209
}
1210
1211
- ret = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
1212
+ ret = blk_pwrite(blk, offset, bytes, (uint8_t *)buf, flags);
1213
if (ret < 0) {
1214
return ret;
1215
}
1216
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
1217
index XXXXXXX..XXXXXXX 100644
1218
--- a/tests/unit/test-block-iothread.c
1219
+++ b/tests/unit/test-block-iothread.c
1220
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pread(BlockBackend *blk)
1221
int ret;
1222
1223
/* Success */
1224
- ret = blk_pread(blk, 0, buf, sizeof(buf), 0);
1225
+ ret = blk_pread(blk, 0, sizeof(buf), buf, 0);
1226
g_assert_cmpint(ret, ==, 0);
1227
1228
/* Early error: Negative offset */
1229
- ret = blk_pread(blk, -2, buf, sizeof(buf), 0);
1230
+ ret = blk_pread(blk, -2, sizeof(buf), buf, 0);
1231
g_assert_cmpint(ret, ==, -EIO);
1232
}
1233
1234
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwrite(BlockBackend *blk)
1235
int ret;
1236
1237
/* Success */
1238
- ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
1239
+ ret = blk_pwrite(blk, 0, sizeof(buf), buf, 0);
1240
g_assert_cmpint(ret, ==, 0);
1241
1242
/* Early error: Negative offset */
1243
- ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
1244
+ ret = blk_pwrite(blk, -2, sizeof(buf), buf, 0);
1245
g_assert_cmpint(ret, ==, -EIO);
1246
}
1247
1248
--
656
--
1249
2.35.3
657
2.9.3
658
659
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Also convert blk_truncate() into a generated_co_wrapper.
3
This patch prepares for the removal of unnecessary lockcnt inc/dec pairs.
4
Extract the dispatching loop for file descriptor handlers into a new
5
function aio_dispatch_handlers, and then inline aio_dispatch into
6
aio_poll.
4
7
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
8
aio_dispatch can now become void.
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20220705161527.1054072-17-afaria@redhat.com>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
14
Message-id: 20170213135235.12274-17-pbonzini@redhat.com
15
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
16
---
11
include/sysemu/block-backend-io.h | 8 ++++++--
17
include/block/aio.h | 6 +-----
12
block/block-backend.c | 7 ++++---
18
util/aio-posix.c | 44 ++++++++++++++------------------------------
13
tests/unit/test-block-iothread.c | 14 ++++++++++++++
19
util/aio-win32.c | 13 ++++---------
14
3 files changed, 24 insertions(+), 5 deletions(-)
20
util/async.c | 2 +-
21
4 files changed, 20 insertions(+), 45 deletions(-)
15
22
16
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
23
diff --git a/include/block/aio.h b/include/block/aio.h
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/block-backend-io.h
25
--- a/include/block/aio.h
19
+++ b/include/sysemu/block-backend-io.h
26
+++ b/include/block/aio.h
20
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
27
@@ -XXX,XX +XXX,XX @@ bool aio_pending(AioContext *ctx);
21
BdrvRequestFlags flags);
28
/* Dispatch any pending callbacks from the GSource attached to the AioContext.
22
int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
29
*
23
int64_t bytes, BdrvRequestFlags flags);
30
* This is used internally in the implementation of the GSource.
24
-int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
31
- *
25
- PreallocMode prealloc, BdrvRequestFlags flags, Error **errp);
32
- * @dispatch_fds: true to process fds, false to skip them
26
+int generated_co_wrapper blk_truncate(BlockBackend *blk, int64_t offset,
33
- * (can be used as an optimization by callers that know there
27
+ bool exact, PreallocMode prealloc,
34
- * are no fds ready)
28
+ BdrvRequestFlags flags, Error **errp);
35
*/
29
+int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
36
-bool aio_dispatch(AioContext *ctx, bool dispatch_fds);
30
+ PreallocMode prealloc, BdrvRequestFlags flags,
37
+void aio_dispatch(AioContext *ctx);
31
+ Error **errp);
38
32
39
/* Progress in completing AIO work to occur. This can issue new pending
33
#endif /* BLOCK_BACKEND_IO_H */
40
* aio as a result of executing I/O completion or bh callbacks.
34
diff --git a/block/block-backend.c b/block/block-backend.c
41
diff --git a/util/aio-posix.c b/util/aio-posix.c
35
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
36
--- a/block/block-backend.c
43
--- a/util/aio-posix.c
37
+++ b/block/block-backend.c
44
+++ b/util/aio-posix.c
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
45
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
39
BDRV_REQ_WRITE_COMPRESSED);
46
AioHandler *node, *tmp;
47
bool progress = false;
48
49
- /*
50
- * We have to walk very carefully in case aio_set_fd_handler is
51
- * called while we're walking.
52
- */
53
- qemu_lockcnt_inc(&ctx->list_lock);
54
-
55
QLIST_FOREACH_SAFE_RCU(node, &ctx->aio_handlers, node, tmp) {
56
int revents;
57
58
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
59
}
60
}
61
62
- qemu_lockcnt_dec(&ctx->list_lock);
63
return progress;
40
}
64
}
41
65
42
-int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
66
-/*
43
- PreallocMode prealloc, BdrvRequestFlags flags, Error **errp)
67
- * Note that dispatch_fds == false has the side-effect of post-poning the
44
+int coroutine_fn blk_co_truncate(BlockBackend *blk, int64_t offset, bool exact,
68
- * freeing of deleted handlers.
45
+ PreallocMode prealloc, BdrvRequestFlags flags,
69
- */
46
+ Error **errp)
70
-bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
71
+void aio_dispatch(AioContext *ctx)
47
{
72
{
48
IO_OR_GS_CODE();
73
- bool progress;
49
if (!blk_is_available(blk)) {
74
+ aio_bh_poll(ctx);
50
@@ -XXX,XX +XXX,XX @@ int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
75
51
return -ENOMEDIUM;
76
- /*
77
- * If there are callbacks left that have been queued, we need to call them.
78
- * Do not call select in this case, because it is possible that the caller
79
- * does not need a complete flush (as is the case for aio_poll loops).
80
- */
81
- progress = aio_bh_poll(ctx);
82
+ qemu_lockcnt_inc(&ctx->list_lock);
83
+ aio_dispatch_handlers(ctx);
84
+ qemu_lockcnt_dec(&ctx->list_lock);
85
86
- if (dispatch_fds) {
87
- progress |= aio_dispatch_handlers(ctx);
88
- }
89
-
90
- /* Run our timers */
91
- progress |= timerlistgroup_run_timers(&ctx->tlg);
92
-
93
- return progress;
94
+ timerlistgroup_run_timers(&ctx->tlg);
95
}
96
97
/* These thread-local variables are used only in a small part of aio_poll
98
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
99
npfd = 0;
100
qemu_lockcnt_dec(&ctx->list_lock);
101
102
- /* Run dispatch even if there were no readable fds to run timers */
103
- if (aio_dispatch(ctx, ret > 0)) {
104
- progress = true;
105
+ progress |= aio_bh_poll(ctx);
106
+
107
+ if (ret > 0) {
108
+ qemu_lockcnt_inc(&ctx->list_lock);
109
+ progress |= aio_dispatch_handlers(ctx);
110
+ qemu_lockcnt_dec(&ctx->list_lock);
52
}
111
}
53
112
54
- return bdrv_truncate(blk->root, offset, exact, prealloc, flags, errp);
113
+ progress |= timerlistgroup_run_timers(&ctx->tlg);
55
+ return bdrv_co_truncate(blk->root, offset, exact, prealloc, flags, errp);
114
+
115
return progress;
56
}
116
}
57
117
58
int blk_save_vmstate(BlockBackend *blk, const uint8_t *buf,
118
diff --git a/util/aio-win32.c b/util/aio-win32.c
59
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
60
index XXXXXXX..XXXXXXX 100644
119
index XXXXXXX..XXXXXXX 100644
61
--- a/tests/unit/test-block-iothread.c
120
--- a/util/aio-win32.c
62
+++ b/tests/unit/test-block-iothread.c
121
+++ b/util/aio-win32.c
63
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_truncate(BdrvChild *c)
122
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
64
c->bs->open_flags |= BDRV_O_RDWR;
123
return progress;
65
}
124
}
66
125
67
+static void test_sync_op_blk_truncate(BlockBackend *blk)
126
-bool aio_dispatch(AioContext *ctx, bool dispatch_fds)
68
+{
127
+void aio_dispatch(AioContext *ctx)
69
+ int ret;
70
+
71
+ /* Normal success path */
72
+ ret = blk_truncate(blk, 65536, false, PREALLOC_MODE_OFF, 0, NULL);
73
+ g_assert_cmpint(ret, ==, 0);
74
+
75
+ /* Early error: Negative offset */
76
+ ret = blk_truncate(blk, -2, false, PREALLOC_MODE_OFF, 0, NULL);
77
+ g_assert_cmpint(ret, ==, -EINVAL);
78
+}
79
+
80
static void test_sync_op_block_status(BdrvChild *c)
81
{
128
{
82
int ret;
129
- bool progress;
83
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
130
-
84
}, {
131
- progress = aio_bh_poll(ctx);
85
.name = "/sync-op/truncate",
132
- if (dispatch_fds) {
86
.fn = test_sync_op_truncate,
133
- progress |= aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE);
87
+ .blkfn = test_sync_op_blk_truncate,
134
- }
88
}, {
135
- progress |= timerlistgroup_run_timers(&ctx->tlg);
89
.name = "/sync-op/block_status",
136
- return progress;
90
.fn = test_sync_op_block_status,
137
+ aio_bh_poll(ctx);
138
+ aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE);
139
+ timerlistgroup_run_timers(&ctx->tlg);
140
}
141
142
bool aio_poll(AioContext *ctx, bool blocking)
143
diff --git a/util/async.c b/util/async.c
144
index XXXXXXX..XXXXXXX 100644
145
--- a/util/async.c
146
+++ b/util/async.c
147
@@ -XXX,XX +XXX,XX @@ aio_ctx_dispatch(GSource *source,
148
AioContext *ctx = (AioContext *) source;
149
150
assert(callback == NULL);
151
- aio_dispatch(ctx, true);
152
+ aio_dispatch(ctx);
153
return true;
154
}
155
91
--
156
--
92
2.35.3
157
2.9.3
158
159
diff view generated by jsdifflib
1
Currently, the exit notifier for unlinking the PID file is registered
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
unconditionally. Limit it to only when we actually do create a PID
3
file.
4
2
5
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
3
Pull the increment/decrement pair out of aio_bh_poll and into the
6
Message-Id: <20220609122701.17172-3-hreitz@redhat.com>
4
callers.
7
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
5
6
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
8
Reviewed-by: Fam Zheng <famz@redhat.com>
9
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
10
Message-id: 20170213135235.12274-18-pbonzini@redhat.com
11
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
12
---
9
softmmu/vl.c | 18 +++++++++---------
13
util/aio-posix.c | 8 +++-----
10
1 file changed, 9 insertions(+), 9 deletions(-)
14
util/aio-win32.c | 8 ++++----
15
util/async.c | 12 ++++++------
16
3 files changed, 13 insertions(+), 15 deletions(-)
11
17
12
diff --git a/softmmu/vl.c b/softmmu/vl.c
18
diff --git a/util/aio-posix.c b/util/aio-posix.c
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/softmmu/vl.c
20
--- a/util/aio-posix.c
15
+++ b/softmmu/vl.c
21
+++ b/util/aio-posix.c
16
@@ -XXX,XX +XXX,XX @@ static Notifier qemu_unlink_pidfile_notifier;
22
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx)
17
23
18
static void qemu_unlink_pidfile(Notifier *n, void *data)
24
void aio_dispatch(AioContext *ctx)
19
{
25
{
20
- if (pid_file) {
26
+ qemu_lockcnt_inc(&ctx->list_lock);
21
- unlink(pid_file);
27
aio_bh_poll(ctx);
22
- }
28
-
23
+ unlink(pid_file);
29
- qemu_lockcnt_inc(&ctx->list_lock);
30
aio_dispatch_handlers(ctx);
31
qemu_lockcnt_dec(&ctx->list_lock);
32
33
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
34
}
35
36
npfd = 0;
37
- qemu_lockcnt_dec(&ctx->list_lock);
38
39
progress |= aio_bh_poll(ctx);
40
41
if (ret > 0) {
42
- qemu_lockcnt_inc(&ctx->list_lock);
43
progress |= aio_dispatch_handlers(ctx);
44
- qemu_lockcnt_dec(&ctx->list_lock);
45
}
46
47
+ qemu_lockcnt_dec(&ctx->list_lock);
48
+
49
progress |= timerlistgroup_run_timers(&ctx->tlg);
50
51
return progress;
52
diff --git a/util/aio-win32.c b/util/aio-win32.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/util/aio-win32.c
55
+++ b/util/aio-win32.c
56
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
57
bool progress = false;
58
AioHandler *tmp;
59
60
- qemu_lockcnt_inc(&ctx->list_lock);
61
-
62
/*
63
* We have to walk very carefully in case aio_set_fd_handler is
64
* called while we're walking.
65
@@ -XXX,XX +XXX,XX @@ static bool aio_dispatch_handlers(AioContext *ctx, HANDLE event)
66
}
67
}
68
69
- qemu_lockcnt_dec(&ctx->list_lock);
70
return progress;
24
}
71
}
25
72
26
static const QEMUOption *lookup_opt(int argc, char **argv,
73
void aio_dispatch(AioContext *ctx)
27
@@ -XXX,XX +XXX,XX @@ static void qemu_maybe_daemonize(const char *pid_file)
74
{
28
os_daemonize();
75
+ qemu_lockcnt_inc(&ctx->list_lock);
29
rcu_disable_atfork();
76
aio_bh_poll(ctx);
30
77
aio_dispatch_handlers(ctx, INVALID_HANDLE_VALUE);
31
- if (pid_file && !qemu_write_pidfile(pid_file, &err)) {
78
+ qemu_lockcnt_dec(&ctx->list_lock);
32
- error_reportf_err(err, "cannot create PID file: ");
79
timerlistgroup_run_timers(&ctx->tlg);
33
- exit(1);
34
- }
35
+ if (pid_file) {
36
+ if (!qemu_write_pidfile(pid_file, &err)) {
37
+ error_reportf_err(err, "cannot create PID file: ");
38
+ exit(1);
39
+ }
40
41
- qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
42
- qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
43
+ qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
44
+ qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
45
+ }
46
}
80
}
47
81
48
static void qemu_init_displays(void)
82
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
83
}
84
}
85
86
- qemu_lockcnt_dec(&ctx->list_lock);
87
first = true;
88
89
/* ctx->notifier is always registered. */
90
@@ -XXX,XX +XXX,XX @@ bool aio_poll(AioContext *ctx, bool blocking)
91
progress |= aio_dispatch_handlers(ctx, event);
92
} while (count > 0);
93
94
+ qemu_lockcnt_dec(&ctx->list_lock);
95
+
96
progress |= timerlistgroup_run_timers(&ctx->tlg);
97
return progress;
98
}
99
diff --git a/util/async.c b/util/async.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/util/async.c
102
+++ b/util/async.c
103
@@ -XXX,XX +XXX,XX @@ void aio_bh_call(QEMUBH *bh)
104
bh->cb(bh->opaque);
105
}
106
107
-/* Multiple occurrences of aio_bh_poll cannot be called concurrently */
108
+/* Multiple occurrences of aio_bh_poll cannot be called concurrently.
109
+ * The count in ctx->list_lock is incremented before the call, and is
110
+ * not affected by the call.
111
+ */
112
int aio_bh_poll(AioContext *ctx)
113
{
114
QEMUBH *bh, **bhp, *next;
115
int ret;
116
bool deleted = false;
117
118
- qemu_lockcnt_inc(&ctx->list_lock);
119
-
120
ret = 0;
121
for (bh = atomic_rcu_read(&ctx->first_bh); bh; bh = next) {
122
next = atomic_rcu_read(&bh->next);
123
@@ -XXX,XX +XXX,XX @@ int aio_bh_poll(AioContext *ctx)
124
125
/* remove deleted bhs */
126
if (!deleted) {
127
- qemu_lockcnt_dec(&ctx->list_lock);
128
return ret;
129
}
130
131
- if (qemu_lockcnt_dec_and_lock(&ctx->list_lock)) {
132
+ if (qemu_lockcnt_dec_if_lock(&ctx->list_lock)) {
133
bhp = &ctx->first_bh;
134
while (*bhp) {
135
bh = *bhp;
136
@@ -XXX,XX +XXX,XX @@ int aio_bh_poll(AioContext *ctx)
137
bhp = &bh->next;
138
}
139
}
140
- qemu_lockcnt_unlock(&ctx->list_lock);
141
+ qemu_lockcnt_inc_and_unlock(&ctx->list_lock);
142
}
143
return ret;
144
}
49
--
145
--
50
2.35.3
146
2.9.3
51
147
52
148
diff view generated by jsdifflib
1
error_report() only works once monitor_init_globals_core() has been
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
called, which is not the case when parsing the --daemonize option. Use
3
fprintf(stderr, ...) instead.
4
2
5
Fixes: 2525edd85fec53e23fda98974a15e3b3c8957596 ("qsd: Add --daemonize")
3
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
6
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
4
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20220609122852.21140-1-hreitz@redhat.com>
5
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
7
Message-id: 20170213135235.12274-19-pbonzini@redhat.com
8
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
---
9
---
10
storage-daemon/qemu-storage-daemon.c | 6 +++++-
10
include/block/block_int.h | 64 +++++++++++++++++++++++++-----------------
11
1 file changed, 5 insertions(+), 1 deletion(-)
11
include/sysemu/block-backend.h | 14 ++++++---
12
2 files changed, 49 insertions(+), 29 deletions(-)
12
13
13
diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c
14
diff --git a/include/block/block_int.h b/include/block/block_int.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/storage-daemon/qemu-storage-daemon.c
16
--- a/include/block/block_int.h
16
+++ b/storage-daemon/qemu-storage-daemon.c
17
+++ b/include/block/block_int.h
17
@@ -XXX,XX +XXX,XX @@ static void process_options(int argc, char *argv[], bool pre_init_pass)
18
@@ -XXX,XX +XXX,XX @@ struct BdrvChild {
18
}
19
* copied as well.
19
case OPTION_DAEMONIZE:
20
*/
20
if (os_set_daemonize(true) < 0) {
21
struct BlockDriverState {
21
- error_report("--daemonize not supported in this build");
22
- int64_t total_sectors; /* if we are reading a disk image, give its
22
+ /*
23
- size in sectors */
23
+ * --daemonize is parsed before monitor_init_globals_core(), so
24
+ /* Protected by big QEMU lock or read-only after opening. No special
24
+ * error_report() does not work yet
25
+ * locking needed during I/O...
25
+ */
26
+ */
26
+ fprintf(stderr, "--daemonize not supported in this build\n");
27
int open_flags; /* flags used to open the file, re-used for re-open */
27
exit(EXIT_FAILURE);
28
bool read_only; /* if true, the media is read only */
28
}
29
bool encrypted; /* if true, the media is encrypted */
29
break;
30
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
31
bool sg; /* if true, the device is a /dev/sg* */
32
bool probed; /* if true, format was probed rather than specified */
33
34
- int copy_on_read; /* if nonzero, copy read backing sectors into image.
35
- note this is a reference count */
36
-
37
- CoQueue flush_queue; /* Serializing flush queue */
38
- bool active_flush_req; /* Flush request in flight? */
39
- unsigned int write_gen; /* Current data generation */
40
- unsigned int flushed_gen; /* Flushed write generation */
41
-
42
BlockDriver *drv; /* NULL means no media */
43
void *opaque;
44
45
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
46
BdrvChild *backing;
47
BdrvChild *file;
48
49
- /* Callback before write request is processed */
50
- NotifierWithReturnList before_write_notifiers;
51
-
52
- /* number of in-flight requests; overall and serialising */
53
- unsigned int in_flight;
54
- unsigned int serialising_in_flight;
55
-
56
- bool wakeup;
57
-
58
- /* Offset after the highest byte written to */
59
- uint64_t wr_highest_offset;
60
-
61
/* I/O Limits */
62
BlockLimits bl;
63
64
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
65
QTAILQ_ENTRY(BlockDriverState) bs_list;
66
/* element of the list of monitor-owned BDS */
67
QTAILQ_ENTRY(BlockDriverState) monitor_list;
68
- QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
69
int refcnt;
70
71
- QLIST_HEAD(, BdrvTrackedRequest) tracked_requests;
72
-
73
/* operation blockers */
74
QLIST_HEAD(, BdrvOpBlocker) op_blockers[BLOCK_OP_TYPE_MAX];
75
76
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
77
/* The error object in use for blocking operations on backing_hd */
78
Error *backing_blocker;
79
80
+ /* Protected by AioContext lock */
81
+
82
+ /* If true, copy read backing sectors into image. Can be >1 if more
83
+ * than one client has requested copy-on-read.
84
+ */
85
+ int copy_on_read;
86
+
87
+ /* If we are reading a disk image, give its size in sectors.
88
+ * Generally read-only; it is written to by load_vmstate and save_vmstate,
89
+ * but the block layer is quiescent during those.
90
+ */
91
+ int64_t total_sectors;
92
+
93
+ /* Callback before write request is processed */
94
+ NotifierWithReturnList before_write_notifiers;
95
+
96
+ /* number of in-flight requests; overall and serialising */
97
+ unsigned int in_flight;
98
+ unsigned int serialising_in_flight;
99
+
100
+ bool wakeup;
101
+
102
+ /* Offset after the highest byte written to */
103
+ uint64_t wr_highest_offset;
104
+
105
/* threshold limit for writes, in bytes. "High water mark". */
106
uint64_t write_threshold_offset;
107
NotifierWithReturn write_threshold_notifier;
108
@@ -XXX,XX +XXX,XX @@ struct BlockDriverState {
109
/* counter for nested bdrv_io_plug */
110
unsigned io_plugged;
111
112
+ QLIST_HEAD(, BdrvTrackedRequest) tracked_requests;
113
+ CoQueue flush_queue; /* Serializing flush queue */
114
+ bool active_flush_req; /* Flush request in flight? */
115
+ unsigned int write_gen; /* Current data generation */
116
+ unsigned int flushed_gen; /* Flushed write generation */
117
+
118
+ QLIST_HEAD(, BdrvDirtyBitmap) dirty_bitmaps;
119
+
120
+ /* do we need to tell the quest if we have a volatile write cache? */
121
+ int enable_write_cache;
122
+
123
int quiesce_counter;
124
};
125
126
diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h
127
index XXXXXXX..XXXXXXX 100644
128
--- a/include/sysemu/block-backend.h
129
+++ b/include/sysemu/block-backend.h
130
@@ -XXX,XX +XXX,XX @@ typedef struct BlockDevOps {
131
* fields that must be public. This is in particular for QLIST_ENTRY() and
132
* friends so that BlockBackends can be kept in lists outside block-backend.c */
133
typedef struct BlockBackendPublic {
134
- /* I/O throttling.
135
- * throttle_state tells us if this BlockBackend has I/O limits configured.
136
- * io_limits_disabled tells us if they are currently being enforced */
137
+ /* I/O throttling has its own locking, but also some fields are
138
+ * protected by the AioContext lock.
139
+ */
140
+
141
+ /* Protected by AioContext lock. */
142
CoQueue throttled_reqs[2];
143
+
144
+ /* Nonzero if the I/O limits are currently being ignored; generally
145
+ * it is zero. */
146
unsigned int io_limits_disabled;
147
148
/* The following fields are protected by the ThrottleGroup lock.
149
- * See the ThrottleGroup documentation for details. */
150
+ * See the ThrottleGroup documentation for details.
151
+ * throttle_state tells us if I/O limits are configured. */
152
ThrottleState *throttle_state;
153
ThrottleTimers throttle_timers;
154
unsigned pending_reqs[2];
30
--
155
--
31
2.35.3
156
2.9.3
32
157
33
158
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Also convert bdrv_pwrite_sync() to being implemented using
3
This uses the lock-free mutex described in the paper '"Blocking without
4
generated_co_wrapper.
4
Locking", or LFTHREADS: A lock-free thread library' by Gidenstam and
5
5
Papatriantafilou. The same technique is used in OSv, and in fact
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
the code is essentially a conversion to C of OSv's code.
7
Reviewed-by: Eric Blake <eblake@redhat.com>
7
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
[Added missing coroutine_fn in tests/test-aio-multithread.c.
9
Message-Id: <20220609152744.3891847-9-afaria@redhat.com>
9
--Stefan]
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Message-id: 20170213181244.16297-2-pbonzini@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
12
---
15
---
13
include/block/block-io.h | 8 ++++++--
16
include/qemu/coroutine.h | 17 ++++-
14
block/io.c | 9 +++++----
17
tests/test-aio-multithread.c | 86 ++++++++++++++++++++++++
15
2 files changed, 11 insertions(+), 6 deletions(-)
18
util/qemu-coroutine-lock.c | 155 ++++++++++++++++++++++++++++++++++++++++---
16
19
util/trace-events | 1 +
17
diff --git a/include/block/block-io.h b/include/block/block-io.h
20
4 files changed, 246 insertions(+), 13 deletions(-)
21
22
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
18
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
19
--- a/include/block/block-io.h
24
--- a/include/qemu/coroutine.h
20
+++ b/include/block/block-io.h
25
+++ b/include/qemu/coroutine.h
21
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper bdrv_pread(BdrvChild *child, int64_t offset,
26
@@ -XXX,XX +XXX,XX @@ bool qemu_co_queue_empty(CoQueue *queue);
22
int generated_co_wrapper bdrv_pwrite(BdrvChild *child, int64_t offset,
27
/**
23
int64_t bytes, const void *buf,
28
* Provides a mutex that can be used to synchronise coroutines
24
BdrvRequestFlags flags);
29
*/
25
-int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
30
+struct CoWaitRecord;
26
- const void *buf, BdrvRequestFlags flags);
31
typedef struct CoMutex {
27
+int generated_co_wrapper bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
32
- bool locked;
28
+ int64_t bytes, const void *buf,
33
+ /* Count of pending lockers; 0 for a free mutex, 1 for an
29
+ BdrvRequestFlags flags);
34
+ * uncontended mutex.
30
+int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
35
+ */
31
+ int64_t bytes, const void *buf,
36
+ unsigned locked;
32
+ BdrvRequestFlags flags);
37
+
33
/*
38
+ /* A queue of waiters. Elements are added atomically in front of
34
* Efficiently zero a region of the disk image. Note that this is a regular
39
+ * from_push. to_pop is only populated, and popped from, by whoever
35
* I/O request like read or write and should have a reasonable size. This
40
+ * is in charge of the next wakeup. This can be an unlocker or,
36
diff --git a/block/io.c b/block/io.c
41
+ * through the handoff protocol, a locker that is about to go to sleep.
42
+ */
43
+ QSLIST_HEAD(, CoWaitRecord) from_push, to_pop;
44
+
45
+ unsigned handoff, sequence;
46
+
47
Coroutine *holder;
48
- CoQueue queue;
49
} CoMutex;
50
51
/**
52
diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c
37
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
38
--- a/block/io.c
54
--- a/tests/test-aio-multithread.c
39
+++ b/block/io.c
55
+++ b/tests/test-aio-multithread.c
40
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
56
@@ -XXX,XX +XXX,XX @@ static void test_multi_co_schedule_10(void)
41
*
57
test_multi_co_schedule(10);
42
* Returns 0 on success, -errno in error cases.
58
}
59
60
+/* CoMutex thread-safety. */
61
+
62
+static uint32_t atomic_counter;
63
+static uint32_t running;
64
+static uint32_t counter;
65
+static CoMutex comutex;
66
+
67
+static void coroutine_fn test_multi_co_mutex_entry(void *opaque)
68
+{
69
+ while (!atomic_mb_read(&now_stopping)) {
70
+ qemu_co_mutex_lock(&comutex);
71
+ counter++;
72
+ qemu_co_mutex_unlock(&comutex);
73
+
74
+ /* Increase atomic_counter *after* releasing the mutex. Otherwise
75
+ * there is a chance (it happens about 1 in 3 runs) that the iothread
76
+ * exits before the coroutine is woken up, causing a spurious
77
+ * assertion failure.
78
+ */
79
+ atomic_inc(&atomic_counter);
80
+ }
81
+ atomic_dec(&running);
82
+}
83
+
84
+static void test_multi_co_mutex(int threads, int seconds)
85
+{
86
+ int i;
87
+
88
+ qemu_co_mutex_init(&comutex);
89
+ counter = 0;
90
+ atomic_counter = 0;
91
+ now_stopping = false;
92
+
93
+ create_aio_contexts();
94
+ assert(threads <= NUM_CONTEXTS);
95
+ running = threads;
96
+ for (i = 0; i < threads; i++) {
97
+ Coroutine *co1 = qemu_coroutine_create(test_multi_co_mutex_entry, NULL);
98
+ aio_co_schedule(ctx[i], co1);
99
+ }
100
+
101
+ g_usleep(seconds * 1000000);
102
+
103
+ atomic_mb_set(&now_stopping, true);
104
+ while (running > 0) {
105
+ g_usleep(100000);
106
+ }
107
+
108
+ join_aio_contexts();
109
+ g_test_message("%d iterations/second\n", counter / seconds);
110
+ g_assert_cmpint(counter, ==, atomic_counter);
111
+}
112
+
113
+/* Testing with NUM_CONTEXTS threads focuses on the queue. The mutex however
114
+ * is too contended (and the threads spend too much time in aio_poll)
115
+ * to actually stress the handoff protocol.
116
+ */
117
+static void test_multi_co_mutex_1(void)
118
+{
119
+ test_multi_co_mutex(NUM_CONTEXTS, 1);
120
+}
121
+
122
+static void test_multi_co_mutex_10(void)
123
+{
124
+ test_multi_co_mutex(NUM_CONTEXTS, 10);
125
+}
126
+
127
+/* Testing with fewer threads stresses the handoff protocol too. Still, the
128
+ * case where the locker _can_ pick up a handoff is very rare, happening
129
+ * about 10 times in 1 million, so increase the runtime a bit compared to
130
+ * other "quick" testcases that only run for 1 second.
131
+ */
132
+static void test_multi_co_mutex_2_3(void)
133
+{
134
+ test_multi_co_mutex(2, 3);
135
+}
136
+
137
+static void test_multi_co_mutex_2_30(void)
138
+{
139
+ test_multi_co_mutex(2, 30);
140
+}
141
+
142
/* End of tests. */
143
144
int main(int argc, char **argv)
145
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
146
g_test_add_func("/aio/multi/lifecycle", test_lifecycle);
147
if (g_test_quick()) {
148
g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_1);
149
+ g_test_add_func("/aio/multi/mutex/contended", test_multi_co_mutex_1);
150
+ g_test_add_func("/aio/multi/mutex/handoff", test_multi_co_mutex_2_3);
151
} else {
152
g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_10);
153
+ g_test_add_func("/aio/multi/mutex/contended", test_multi_co_mutex_10);
154
+ g_test_add_func("/aio/multi/mutex/handoff", test_multi_co_mutex_2_30);
155
}
156
return g_test_run();
157
}
158
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/util/qemu-coroutine-lock.c
161
+++ b/util/qemu-coroutine-lock.c
162
@@ -XXX,XX +XXX,XX @@
163
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
164
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
165
* THE SOFTWARE.
166
+ *
167
+ * The lock-free mutex implementation is based on OSv
168
+ * (core/lfmutex.cc, include/lockfree/mutex.hh).
169
+ * Copyright (C) 2013 Cloudius Systems, Ltd.
43
*/
170
*/
44
-int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
171
45
- const void *buf, BdrvRequestFlags flags)
172
#include "qemu/osdep.h"
46
+int coroutine_fn bdrv_co_pwrite_sync(BdrvChild *child, int64_t offset,
173
@@ -XXX,XX +XXX,XX @@ bool qemu_co_queue_empty(CoQueue *queue)
47
+ int64_t bytes, const void *buf,
174
return QSIMPLEQ_FIRST(&queue->entries) == NULL;
48
+ BdrvRequestFlags flags)
175
}
176
177
+/* The wait records are handled with a multiple-producer, single-consumer
178
+ * lock-free queue. There cannot be two concurrent pop_waiter() calls
179
+ * because pop_waiter() can only be called while mutex->handoff is zero.
180
+ * This can happen in three cases:
181
+ * - in qemu_co_mutex_unlock, before the hand-off protocol has started.
182
+ * In this case, qemu_co_mutex_lock will see mutex->handoff == 0 and
183
+ * not take part in the handoff.
184
+ * - in qemu_co_mutex_lock, if it steals the hand-off responsibility from
185
+ * qemu_co_mutex_unlock. In this case, qemu_co_mutex_unlock will fail
186
+ * the cmpxchg (it will see either 0 or the next sequence value) and
187
+ * exit. The next hand-off cannot begin until qemu_co_mutex_lock has
188
+ * woken up someone.
189
+ * - in qemu_co_mutex_unlock, if it takes the hand-off token itself.
190
+ * In this case another iteration starts with mutex->handoff == 0;
191
+ * a concurrent qemu_co_mutex_lock will fail the cmpxchg, and
192
+ * qemu_co_mutex_unlock will go back to case (1).
193
+ *
194
+ * The following functions manage this queue.
195
+ */
196
+typedef struct CoWaitRecord {
197
+ Coroutine *co;
198
+ QSLIST_ENTRY(CoWaitRecord) next;
199
+} CoWaitRecord;
200
+
201
+static void push_waiter(CoMutex *mutex, CoWaitRecord *w)
202
+{
203
+ w->co = qemu_coroutine_self();
204
+ QSLIST_INSERT_HEAD_ATOMIC(&mutex->from_push, w, next);
205
+}
206
+
207
+static void move_waiters(CoMutex *mutex)
208
+{
209
+ QSLIST_HEAD(, CoWaitRecord) reversed;
210
+ QSLIST_MOVE_ATOMIC(&reversed, &mutex->from_push);
211
+ while (!QSLIST_EMPTY(&reversed)) {
212
+ CoWaitRecord *w = QSLIST_FIRST(&reversed);
213
+ QSLIST_REMOVE_HEAD(&reversed, next);
214
+ QSLIST_INSERT_HEAD(&mutex->to_pop, w, next);
215
+ }
216
+}
217
+
218
+static CoWaitRecord *pop_waiter(CoMutex *mutex)
219
+{
220
+ CoWaitRecord *w;
221
+
222
+ if (QSLIST_EMPTY(&mutex->to_pop)) {
223
+ move_waiters(mutex);
224
+ if (QSLIST_EMPTY(&mutex->to_pop)) {
225
+ return NULL;
226
+ }
227
+ }
228
+ w = QSLIST_FIRST(&mutex->to_pop);
229
+ QSLIST_REMOVE_HEAD(&mutex->to_pop, next);
230
+ return w;
231
+}
232
+
233
+static bool has_waiters(CoMutex *mutex)
234
+{
235
+ return QSLIST_EMPTY(&mutex->to_pop) || QSLIST_EMPTY(&mutex->from_push);
236
+}
237
+
238
void qemu_co_mutex_init(CoMutex *mutex)
49
{
239
{
50
int ret;
240
memset(mutex, 0, sizeof(*mutex));
51
IO_CODE();
241
- qemu_co_queue_init(&mutex->queue);
52
242
}
53
- ret = bdrv_pwrite(child, offset, bytes, buf, flags);
243
54
+ ret = bdrv_co_pwrite(child, offset, bytes, buf, flags);
244
-void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
55
if (ret < 0) {
245
+static void coroutine_fn qemu_co_mutex_lock_slowpath(CoMutex *mutex)
56
return ret;
246
{
247
Coroutine *self = qemu_coroutine_self();
248
+ CoWaitRecord w;
249
+ unsigned old_handoff;
250
251
trace_qemu_co_mutex_lock_entry(mutex, self);
252
+ w.co = self;
253
+ push_waiter(mutex, &w);
254
255
- while (mutex->locked) {
256
- qemu_co_queue_wait(&mutex->queue);
257
+ /* This is the "Responsibility Hand-Off" protocol; a lock() picks from
258
+ * a concurrent unlock() the responsibility of waking somebody up.
259
+ */
260
+ old_handoff = atomic_mb_read(&mutex->handoff);
261
+ if (old_handoff &&
262
+ has_waiters(mutex) &&
263
+ atomic_cmpxchg(&mutex->handoff, old_handoff, 0) == old_handoff) {
264
+ /* There can be no concurrent pops, because there can be only
265
+ * one active handoff at a time.
266
+ */
267
+ CoWaitRecord *to_wake = pop_waiter(mutex);
268
+ Coroutine *co = to_wake->co;
269
+ if (co == self) {
270
+ /* We got the lock ourselves! */
271
+ assert(to_wake == &w);
272
+ return;
273
+ }
274
+
275
+ aio_co_wake(co);
57
}
276
}
58
277
59
- ret = bdrv_flush(child->bs);
278
- mutex->locked = true;
60
+ ret = bdrv_co_flush(child->bs);
279
- mutex->holder = self;
61
if (ret < 0) {
280
- self->locks_held++;
62
return ret;
281
-
63
}
282
+ qemu_coroutine_yield();
283
trace_qemu_co_mutex_lock_return(mutex, self);
284
}
285
286
+void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
287
+{
288
+ Coroutine *self = qemu_coroutine_self();
289
+
290
+ if (atomic_fetch_inc(&mutex->locked) == 0) {
291
+ /* Uncontended. */
292
+ trace_qemu_co_mutex_lock_uncontended(mutex, self);
293
+ } else {
294
+ qemu_co_mutex_lock_slowpath(mutex);
295
+ }
296
+ mutex->holder = self;
297
+ self->locks_held++;
298
+}
299
+
300
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
301
{
302
Coroutine *self = qemu_coroutine_self();
303
304
trace_qemu_co_mutex_unlock_entry(mutex, self);
305
306
- assert(mutex->locked == true);
307
+ assert(mutex->locked);
308
assert(mutex->holder == self);
309
assert(qemu_in_coroutine());
310
311
- mutex->locked = false;
312
mutex->holder = NULL;
313
self->locks_held--;
314
- qemu_co_queue_next(&mutex->queue);
315
+ if (atomic_fetch_dec(&mutex->locked) == 1) {
316
+ /* No waiting qemu_co_mutex_lock(). Pfew, that was easy! */
317
+ return;
318
+ }
319
+
320
+ for (;;) {
321
+ CoWaitRecord *to_wake = pop_waiter(mutex);
322
+ unsigned our_handoff;
323
+
324
+ if (to_wake) {
325
+ Coroutine *co = to_wake->co;
326
+ aio_co_wake(co);
327
+ break;
328
+ }
329
+
330
+ /* Some concurrent lock() is in progress (we know this because
331
+ * mutex->locked was >1) but it hasn't yet put itself on the wait
332
+ * queue. Pick a sequence number for the handoff protocol (not 0).
333
+ */
334
+ if (++mutex->sequence == 0) {
335
+ mutex->sequence = 1;
336
+ }
337
+
338
+ our_handoff = mutex->sequence;
339
+ atomic_mb_set(&mutex->handoff, our_handoff);
340
+ if (!has_waiters(mutex)) {
341
+ /* The concurrent lock has not added itself yet, so it
342
+ * will be able to pick our handoff.
343
+ */
344
+ break;
345
+ }
346
+
347
+ /* Try to do the handoff protocol ourselves; if somebody else has
348
+ * already taken it, however, we're done and they're responsible.
349
+ */
350
+ if (atomic_cmpxchg(&mutex->handoff, our_handoff, 0) != our_handoff) {
351
+ break;
352
+ }
353
+ }
354
355
trace_qemu_co_mutex_unlock_return(mutex, self);
356
}
357
diff --git a/util/trace-events b/util/trace-events
358
index XXXXXXX..XXXXXXX 100644
359
--- a/util/trace-events
360
+++ b/util/trace-events
361
@@ -XXX,XX +XXX,XX @@ qemu_coroutine_terminate(void *co) "self %p"
362
363
# util/qemu-coroutine-lock.c
364
qemu_co_queue_run_restart(void *co) "co %p"
365
+qemu_co_mutex_lock_uncontended(void *mutex, void *self) "mutex %p self %p"
366
qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
367
qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
368
qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
64
--
369
--
65
2.35.3
370
2.9.3
371
372
diff view generated by jsdifflib
1
After writing the PID file, we register an exit notifier to unlink it
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
when the process terminates. However, if the process has changed its
3
working directory in the meantime (e.g. in os_setup_post() when
4
daemonizing), this will not work when the PID file path was relative.
5
Therefore, pass the absolute path (created with realpath()) to the
6
unlink() call in the exit notifier.
7
2
8
(realpath() needs a path pointing to an existing file, so we cannot use
3
Running a very small critical section on pthread_mutex_t and CoMutex
9
it before qemu_write_pidfile().)
4
shows that pthread_mutex_t is much faster because it doesn't actually
5
go to sleep. What happens is that the critical section is shorter
6
than the latency of entering the kernel and thus FUTEX_WAIT always
7
fails. With CoMutex there is no such latency but you still want to
8
avoid wait and wakeup. So introduce it artificially.
10
9
11
Reproducer:
10
This only works with one waiters; because CoMutex is fair, it will
12
$ cd /tmp
11
always have more waits and wakeups than a pthread_mutex_t.
13
$ qemu-system-x86_64 --daemonize --pidfile qemu.pid
14
$ file qemu.pid
15
qemu.pid: ASCII text
16
$ kill $(cat qemu.pid)
17
$ file qemu.pid
18
qemu.pid: ASCII text
19
12
20
(qemu.pid should be gone after the process has terminated.)
13
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
14
Reviewed-by: Fam Zheng <famz@redhat.com>
15
Message-id: 20170213181244.16297-3-pbonzini@redhat.com
16
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
17
---
18
include/qemu/coroutine.h | 5 +++++
19
util/qemu-coroutine-lock.c | 51 ++++++++++++++++++++++++++++++++++++++++------
20
util/qemu-coroutine.c | 2 +-
21
3 files changed, 51 insertions(+), 7 deletions(-)
21
22
22
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
23
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
23
Message-Id: <20220609122701.17172-4-hreitz@redhat.com>
24
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
25
---
26
softmmu/vl.c | 30 ++++++++++++++++++++++++++----
27
1 file changed, 26 insertions(+), 4 deletions(-)
28
29
diff --git a/softmmu/vl.c b/softmmu/vl.c
30
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
31
--- a/softmmu/vl.c
25
--- a/include/qemu/coroutine.h
32
+++ b/softmmu/vl.c
26
+++ b/include/qemu/coroutine.h
33
@@ -XXX,XX +XXX,XX @@ machine_parse_property_opt(QemuOptsList *opts_list, const char *propname,
27
@@ -XXX,XX +XXX,XX @@ typedef struct CoMutex {
28
*/
29
unsigned locked;
30
31
+ /* Context that is holding the lock. Useful to avoid spinning
32
+ * when two coroutines on the same AioContext try to get the lock. :)
33
+ */
34
+ AioContext *ctx;
35
+
36
/* A queue of waiters. Elements are added atomically in front of
37
* from_push. to_pop is only populated, and popped from, by whoever
38
* is in charge of the next wakeup. This can be an unlocker or,
39
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/util/qemu-coroutine-lock.c
42
+++ b/util/qemu-coroutine-lock.c
43
@@ -XXX,XX +XXX,XX @@
44
#include "qemu-common.h"
45
#include "qemu/coroutine.h"
46
#include "qemu/coroutine_int.h"
47
+#include "qemu/processor.h"
48
#include "qemu/queue.h"
49
#include "block/aio.h"
50
#include "trace.h"
51
@@ -XXX,XX +XXX,XX @@ void qemu_co_mutex_init(CoMutex *mutex)
52
memset(mutex, 0, sizeof(*mutex));
34
}
53
}
35
54
36
static const char *pid_file;
55
-static void coroutine_fn qemu_co_mutex_lock_slowpath(CoMutex *mutex)
37
-static Notifier qemu_unlink_pidfile_notifier;
56
+static void coroutine_fn qemu_co_mutex_wake(CoMutex *mutex, Coroutine *co)
38
+struct UnlinkPidfileNotifier {
57
+{
39
+ Notifier notifier;
58
+ /* Read co before co->ctx; pairs with smp_wmb() in
40
+ char *pid_file_realpath;
59
+ * qemu_coroutine_enter().
41
+};
60
+ */
42
+static struct UnlinkPidfileNotifier qemu_unlink_pidfile_notifier;
61
+ smp_read_barrier_depends();
43
62
+ mutex->ctx = co->ctx;
44
static void qemu_unlink_pidfile(Notifier *n, void *data)
63
+ aio_co_wake(co);
64
+}
65
+
66
+static void coroutine_fn qemu_co_mutex_lock_slowpath(AioContext *ctx,
67
+ CoMutex *mutex)
45
{
68
{
46
- unlink(pid_file);
69
Coroutine *self = qemu_coroutine_self();
47
+ struct UnlinkPidfileNotifier *upn;
70
CoWaitRecord w;
71
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qemu_co_mutex_lock_slowpath(CoMutex *mutex)
72
if (co == self) {
73
/* We got the lock ourselves! */
74
assert(to_wake == &w);
75
+ mutex->ctx = ctx;
76
return;
77
}
78
79
- aio_co_wake(co);
80
+ qemu_co_mutex_wake(mutex, co);
81
}
82
83
qemu_coroutine_yield();
84
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn qemu_co_mutex_lock_slowpath(CoMutex *mutex)
85
86
void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex)
87
{
88
+ AioContext *ctx = qemu_get_current_aio_context();
89
Coroutine *self = qemu_coroutine_self();
90
+ int waiters, i;
91
92
- if (atomic_fetch_inc(&mutex->locked) == 0) {
93
+ /* Running a very small critical section on pthread_mutex_t and CoMutex
94
+ * shows that pthread_mutex_t is much faster because it doesn't actually
95
+ * go to sleep. What happens is that the critical section is shorter
96
+ * than the latency of entering the kernel and thus FUTEX_WAIT always
97
+ * fails. With CoMutex there is no such latency but you still want to
98
+ * avoid wait and wakeup. So introduce it artificially.
99
+ */
100
+ i = 0;
101
+retry_fast_path:
102
+ waiters = atomic_cmpxchg(&mutex->locked, 0, 1);
103
+ if (waiters != 0) {
104
+ while (waiters == 1 && ++i < 1000) {
105
+ if (atomic_read(&mutex->ctx) == ctx) {
106
+ break;
107
+ }
108
+ if (atomic_read(&mutex->locked) == 0) {
109
+ goto retry_fast_path;
110
+ }
111
+ cpu_relax();
112
+ }
113
+ waiters = atomic_fetch_inc(&mutex->locked);
114
+ }
48
+
115
+
49
+ upn = DO_UPCAST(struct UnlinkPidfileNotifier, notifier, n);
116
+ if (waiters == 0) {
50
+ unlink(upn->pid_file_realpath);
117
/* Uncontended. */
51
}
118
trace_qemu_co_mutex_lock_uncontended(mutex, self);
52
119
+ mutex->ctx = ctx;
53
static const QEMUOption *lookup_opt(int argc, char **argv,
120
} else {
54
@@ -XXX,XX +XXX,XX @@ static void qemu_maybe_daemonize(const char *pid_file)
121
- qemu_co_mutex_lock_slowpath(mutex);
55
rcu_disable_atfork();
122
+ qemu_co_mutex_lock_slowpath(ctx, mutex);
56
123
}
57
if (pid_file) {
124
mutex->holder = self;
58
+ char *pid_file_realpath = NULL;
125
self->locks_held++;
59
+
126
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
60
if (!qemu_write_pidfile(pid_file, &err)) {
127
assert(mutex->holder == self);
61
error_reportf_err(err, "cannot create PID file: ");
128
assert(qemu_in_coroutine());
62
exit(1);
129
130
+ mutex->ctx = NULL;
131
mutex->holder = NULL;
132
self->locks_held--;
133
if (atomic_fetch_dec(&mutex->locked) == 1) {
134
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex)
135
unsigned our_handoff;
136
137
if (to_wake) {
138
- Coroutine *co = to_wake->co;
139
- aio_co_wake(co);
140
+ qemu_co_mutex_wake(mutex, to_wake->co);
141
break;
63
}
142
}
64
143
65
- qemu_unlink_pidfile_notifier.notify = qemu_unlink_pidfile;
144
diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c
66
- qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier);
145
index XXXXXXX..XXXXXXX 100644
67
+ pid_file_realpath = g_malloc0(PATH_MAX);
146
--- a/util/qemu-coroutine.c
68
+ if (!realpath(pid_file, pid_file_realpath)) {
147
+++ b/util/qemu-coroutine.c
69
+ error_report("cannot resolve PID file path: %s: %s",
148
@@ -XXX,XX +XXX,XX @@ void qemu_coroutine_enter(Coroutine *co)
70
+ pid_file, strerror(errno));
149
co->ctx = qemu_get_current_aio_context();
71
+ unlink(pid_file);
150
72
+ exit(1);
151
/* Store co->ctx before anything that stores co. Matches
73
+ }
152
- * barrier in aio_co_wake.
74
+
153
+ * barrier in aio_co_wake and qemu_co_mutex_wake.
75
+ qemu_unlink_pidfile_notifier = (struct UnlinkPidfileNotifier) {
154
*/
76
+ .notifier = {
155
smp_wmb();
77
+ .notify = qemu_unlink_pidfile,
78
+ },
79
+ .pid_file_realpath = pid_file_realpath,
80
+ };
81
+ qemu_add_exit_notifier(&qemu_unlink_pidfile_notifier.notifier);
82
}
83
}
84
156
85
--
157
--
86
2.35.3
158
2.9.3
87
159
88
160
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Signed-off-by: Alberto Faria <afaria@redhat.com>
3
Add two implementations of the same benchmark as the previous patch,
4
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
4
but using pthreads. One uses a normal QemuMutex, the other is Linux
5
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
5
only and implements a fair mutex based on MCS locks and futexes.
6
Message-Id: <20220705161527.1054072-14-afaria@redhat.com>
6
This shows that the slower performance of the 5-thread case is due to
7
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
7
the fairness of CoMutex, rather than to coroutines. If fairness does
8
not matter, as is the case with two threads, CoMutex can actually be
9
faster than pthreads.
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12
Reviewed-by: Fam Zheng <famz@redhat.com>
13
Message-id: 20170213181244.16297-4-pbonzini@redhat.com
14
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
8
---
15
---
9
block/coroutines.h | 3 ---
16
tests/test-aio-multithread.c | 164 +++++++++++++++++++++++++++++++++++++++++++
10
include/sysemu/block-backend-io.h | 3 ++-
17
1 file changed, 164 insertions(+)
11
block/block-backend.c | 12 ------------
18
12
3 files changed, 2 insertions(+), 16 deletions(-)
19
diff --git a/tests/test-aio-multithread.c b/tests/test-aio-multithread.c
13
14
diff --git a/block/coroutines.h b/block/coroutines.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/block/coroutines.h
21
--- a/tests/test-aio-multithread.c
17
+++ b/block/coroutines.h
22
+++ b/tests/test-aio-multithread.c
18
@@ -XXX,XX +XXX,XX @@ nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
23
@@ -XXX,XX +XXX,XX @@ static void test_multi_co_mutex_2_30(void)
19
int generated_co_wrapper
24
test_multi_co_mutex(2, 30);
20
blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
21
22
-int generated_co_wrapper
23
-blk_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
24
-
25
int generated_co_wrapper blk_do_flush(BlockBackend *blk);
26
27
#endif /* BLOCK_COROUTINES_H */
28
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/block-backend-io.h
31
+++ b/include/sysemu/block-backend-io.h
32
@@ -XXX,XX +XXX,XX @@ static inline int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset,
33
return blk_co_pwritev(blk, offset, bytes, &qiov, flags);
34
}
25
}
35
26
36
+int generated_co_wrapper blk_pdiscard(BlockBackend *blk, int64_t offset,
27
+/* Same test with fair mutexes, for performance comparison. */
37
+ int64_t bytes);
28
+
38
int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
29
+#ifdef CONFIG_LINUX
39
int64_t bytes);
30
+#include "qemu/futex.h"
40
31
+
41
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
32
+/* The nodes for the mutex reside in this structure (on which we try to avoid
42
const void *buf);
33
+ * false sharing). The head of the mutex is in the "mutex_head" variable.
43
int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
34
+ */
44
int64_t bytes, const void *buf);
35
+static struct {
45
-int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
36
+ int next, locked;
46
int generated_co_wrapper blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
37
+ int padding[14];
47
int64_t bytes,
38
+} nodes[NUM_CONTEXTS] __attribute__((__aligned__(64)));
48
BdrvRequestFlags flags);
39
+
49
diff --git a/block/block-backend.c b/block/block-backend.c
40
+static int mutex_head = -1;
50
index XXXXXXX..XXXXXXX 100644
41
+
51
--- a/block/block-backend.c
42
+static void mcs_mutex_lock(void)
52
+++ b/block/block-backend.c
43
+{
53
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pdiscard(BlockBackend *blk, int64_t offset,
44
+ int prev;
54
return ret;
45
+
46
+ nodes[id].next = -1;
47
+ nodes[id].locked = 1;
48
+ prev = atomic_xchg(&mutex_head, id);
49
+ if (prev != -1) {
50
+ atomic_set(&nodes[prev].next, id);
51
+ qemu_futex_wait(&nodes[id].locked, 1);
52
+ }
53
+}
54
+
55
+static void mcs_mutex_unlock(void)
56
+{
57
+ int next;
58
+ if (nodes[id].next == -1) {
59
+ if (atomic_read(&mutex_head) == id &&
60
+ atomic_cmpxchg(&mutex_head, id, -1) == id) {
61
+ /* Last item in the list, exit. */
62
+ return;
63
+ }
64
+ while (atomic_read(&nodes[id].next) == -1) {
65
+ /* mcs_mutex_lock did the xchg, but has not updated
66
+ * nodes[prev].next yet.
67
+ */
68
+ }
69
+ }
70
+
71
+ /* Wake up the next in line. */
72
+ next = nodes[id].next;
73
+ nodes[next].locked = 0;
74
+ qemu_futex_wake(&nodes[next].locked, 1);
75
+}
76
+
77
+static void test_multi_fair_mutex_entry(void *opaque)
78
+{
79
+ while (!atomic_mb_read(&now_stopping)) {
80
+ mcs_mutex_lock();
81
+ counter++;
82
+ mcs_mutex_unlock();
83
+ atomic_inc(&atomic_counter);
84
+ }
85
+ atomic_dec(&running);
86
+}
87
+
88
+static void test_multi_fair_mutex(int threads, int seconds)
89
+{
90
+ int i;
91
+
92
+ assert(mutex_head == -1);
93
+ counter = 0;
94
+ atomic_counter = 0;
95
+ now_stopping = false;
96
+
97
+ create_aio_contexts();
98
+ assert(threads <= NUM_CONTEXTS);
99
+ running = threads;
100
+ for (i = 0; i < threads; i++) {
101
+ Coroutine *co1 = qemu_coroutine_create(test_multi_fair_mutex_entry, NULL);
102
+ aio_co_schedule(ctx[i], co1);
103
+ }
104
+
105
+ g_usleep(seconds * 1000000);
106
+
107
+ atomic_mb_set(&now_stopping, true);
108
+ while (running > 0) {
109
+ g_usleep(100000);
110
+ }
111
+
112
+ join_aio_contexts();
113
+ g_test_message("%d iterations/second\n", counter / seconds);
114
+ g_assert_cmpint(counter, ==, atomic_counter);
115
+}
116
+
117
+static void test_multi_fair_mutex_1(void)
118
+{
119
+ test_multi_fair_mutex(NUM_CONTEXTS, 1);
120
+}
121
+
122
+static void test_multi_fair_mutex_10(void)
123
+{
124
+ test_multi_fair_mutex(NUM_CONTEXTS, 10);
125
+}
126
+#endif
127
+
128
+/* Same test with pthread mutexes, for performance comparison and
129
+ * portability. */
130
+
131
+static QemuMutex mutex;
132
+
133
+static void test_multi_mutex_entry(void *opaque)
134
+{
135
+ while (!atomic_mb_read(&now_stopping)) {
136
+ qemu_mutex_lock(&mutex);
137
+ counter++;
138
+ qemu_mutex_unlock(&mutex);
139
+ atomic_inc(&atomic_counter);
140
+ }
141
+ atomic_dec(&running);
142
+}
143
+
144
+static void test_multi_mutex(int threads, int seconds)
145
+{
146
+ int i;
147
+
148
+ qemu_mutex_init(&mutex);
149
+ counter = 0;
150
+ atomic_counter = 0;
151
+ now_stopping = false;
152
+
153
+ create_aio_contexts();
154
+ assert(threads <= NUM_CONTEXTS);
155
+ running = threads;
156
+ for (i = 0; i < threads; i++) {
157
+ Coroutine *co1 = qemu_coroutine_create(test_multi_mutex_entry, NULL);
158
+ aio_co_schedule(ctx[i], co1);
159
+ }
160
+
161
+ g_usleep(seconds * 1000000);
162
+
163
+ atomic_mb_set(&now_stopping, true);
164
+ while (running > 0) {
165
+ g_usleep(100000);
166
+ }
167
+
168
+ join_aio_contexts();
169
+ g_test_message("%d iterations/second\n", counter / seconds);
170
+ g_assert_cmpint(counter, ==, atomic_counter);
171
+}
172
+
173
+static void test_multi_mutex_1(void)
174
+{
175
+ test_multi_mutex(NUM_CONTEXTS, 1);
176
+}
177
+
178
+static void test_multi_mutex_10(void)
179
+{
180
+ test_multi_mutex(NUM_CONTEXTS, 10);
181
+}
182
+
183
/* End of tests. */
184
185
int main(int argc, char **argv)
186
@@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv)
187
g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_1);
188
g_test_add_func("/aio/multi/mutex/contended", test_multi_co_mutex_1);
189
g_test_add_func("/aio/multi/mutex/handoff", test_multi_co_mutex_2_3);
190
+#ifdef CONFIG_LINUX
191
+ g_test_add_func("/aio/multi/mutex/mcs", test_multi_fair_mutex_1);
192
+#endif
193
+ g_test_add_func("/aio/multi/mutex/pthread", test_multi_mutex_1);
194
} else {
195
g_test_add_func("/aio/multi/schedule", test_multi_co_schedule_10);
196
g_test_add_func("/aio/multi/mutex/contended", test_multi_co_mutex_10);
197
g_test_add_func("/aio/multi/mutex/handoff", test_multi_co_mutex_2_30);
198
+#ifdef CONFIG_LINUX
199
+ g_test_add_func("/aio/multi/mutex/mcs", test_multi_fair_mutex_10);
200
+#endif
201
+ g_test_add_func("/aio/multi/mutex/pthread", test_multi_mutex_10);
202
}
203
return g_test_run();
55
}
204
}
56
57
-int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes)
58
-{
59
- int ret;
60
- IO_OR_GS_CODE();
61
-
62
- blk_inc_in_flight(blk);
63
- ret = blk_do_pdiscard(blk, offset, bytes);
64
- blk_dec_in_flight(blk);
65
-
66
- return ret;
67
-}
68
-
69
/* To be called between exactly one pair of blk_inc/dec_in_flight() */
70
int coroutine_fn blk_co_do_flush(BlockBackend *blk)
71
{
72
--
205
--
73
2.35.3
206
2.9.3
207
208
diff view generated by jsdifflib
1
From: John Snow <jsnow@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Fixes: 58a6fdcc
3
This will avoid forward references in the next patch. It is also
4
Signed-off-by: John Snow <jsnow@redhat.com>
4
more logical because CoQueue is not anymore the basic primitive.
5
Tested-by: Daniel P. Berrangé <berrange@redhat.com>
5
6
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Message-Id: <20220616142659.3184115-2-jsnow@redhat.com>
7
Reviewed-by: Fam Zheng <famz@redhat.com>
8
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-id: 20170213181244.16297-5-pbonzini@redhat.com
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
---
10
---
11
tests/qemu-iotests/223.out | 4 ++--
11
include/qemu/coroutine.h | 89 ++++++++++++++++++++++++------------------------
12
tests/qemu-iotests/307.out | 4 ++--
12
1 file changed, 44 insertions(+), 45 deletions(-)
13
2 files changed, 4 insertions(+), 4 deletions(-)
14
13
15
diff --git a/tests/qemu-iotests/223.out b/tests/qemu-iotests/223.out
14
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/tests/qemu-iotests/223.out
16
--- a/include/qemu/coroutine.h
18
+++ b/tests/qemu-iotests/223.out
17
+++ b/include/qemu/coroutine.h
19
@@ -XXX,XX +XXX,XX @@ exports available: 3
18
@@ -XXX,XX +XXX,XX @@ bool qemu_in_coroutine(void);
20
export: 'n2'
19
*/
21
description: some text
20
bool qemu_coroutine_entered(Coroutine *co);
22
size: 4194304
21
23
- flags: 0xced ( flush fua trim zeroes df cache fast-zero )
22
-
24
+ flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
23
-/**
25
min block: 1
24
- * CoQueues are a mechanism to queue coroutines in order to continue executing
26
opt block: 4096
25
- * them later. They provide the fundamental primitives on which coroutine locks
27
max block: 33554432
26
- * are built.
28
@@ -XXX,XX +XXX,XX @@ exports available: 3
27
- */
29
export: 'n2'
28
-typedef struct CoQueue {
30
description: some text
29
- QSIMPLEQ_HEAD(, Coroutine) entries;
31
size: 4194304
30
-} CoQueue;
32
- flags: 0xced ( flush fua trim zeroes df cache fast-zero )
31
-
33
+ flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
32
-/**
34
min block: 1
33
- * Initialise a CoQueue. This must be called before any other operation is used
35
opt block: 4096
34
- * on the CoQueue.
36
max block: 33554432
35
- */
37
diff --git a/tests/qemu-iotests/307.out b/tests/qemu-iotests/307.out
36
-void qemu_co_queue_init(CoQueue *queue);
38
index XXXXXXX..XXXXXXX 100644
37
-
39
--- a/tests/qemu-iotests/307.out
38
-/**
40
+++ b/tests/qemu-iotests/307.out
39
- * Adds the current coroutine to the CoQueue and transfers control to the
41
@@ -XXX,XX +XXX,XX @@ exports available: 2
40
- * caller of the coroutine.
42
export: 'export1'
41
- */
43
description: This is the writable second export
42
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
44
size: 67108864
43
-
45
- flags: 0xced ( flush fua trim zeroes df cache fast-zero )
44
-/**
46
+ flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
45
- * Restarts the next coroutine in the CoQueue and removes it from the queue.
47
min block: XXX
46
- *
48
opt block: XXX
47
- * Returns true if a coroutine was restarted, false if the queue is empty.
49
max block: XXX
48
- */
50
@@ -XXX,XX +XXX,XX @@ exports available: 1
49
-bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
51
export: 'export1'
50
-
52
description: This is the writable second export
51
-/**
53
size: 67108864
52
- * Restarts all coroutines in the CoQueue and leaves the queue empty.
54
- flags: 0xced ( flush fua trim zeroes df cache fast-zero )
53
- */
55
+ flags: 0xded ( flush fua trim zeroes df multi cache fast-zero )
54
-void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
56
min block: XXX
55
-
57
opt block: XXX
56
-/**
58
max block: XXX
57
- * Enter the next coroutine in the queue
58
- */
59
-bool qemu_co_enter_next(CoQueue *queue);
60
-
61
-/**
62
- * Checks if the CoQueue is empty.
63
- */
64
-bool qemu_co_queue_empty(CoQueue *queue);
65
-
66
-
67
/**
68
* Provides a mutex that can be used to synchronise coroutines
69
*/
70
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_lock(CoMutex *mutex);
71
*/
72
void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
73
74
+
75
+/**
76
+ * CoQueues are a mechanism to queue coroutines in order to continue executing
77
+ * them later.
78
+ */
79
+typedef struct CoQueue {
80
+ QSIMPLEQ_HEAD(, Coroutine) entries;
81
+} CoQueue;
82
+
83
+/**
84
+ * Initialise a CoQueue. This must be called before any other operation is used
85
+ * on the CoQueue.
86
+ */
87
+void qemu_co_queue_init(CoQueue *queue);
88
+
89
+/**
90
+ * Adds the current coroutine to the CoQueue and transfers control to the
91
+ * caller of the coroutine.
92
+ */
93
+void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
94
+
95
+/**
96
+ * Restarts the next coroutine in the CoQueue and removes it from the queue.
97
+ *
98
+ * Returns true if a coroutine was restarted, false if the queue is empty.
99
+ */
100
+bool coroutine_fn qemu_co_queue_next(CoQueue *queue);
101
+
102
+/**
103
+ * Restarts all coroutines in the CoQueue and leaves the queue empty.
104
+ */
105
+void coroutine_fn qemu_co_queue_restart_all(CoQueue *queue);
106
+
107
+/**
108
+ * Enter the next coroutine in the queue
109
+ */
110
+bool qemu_co_enter_next(CoQueue *queue);
111
+
112
+/**
113
+ * Checks if the CoQueue is empty.
114
+ */
115
+bool qemu_co_queue_empty(CoQueue *queue);
116
+
117
+
118
typedef struct CoRwlock {
119
bool writer;
120
int reader;
59
--
121
--
60
2.35.3
122
2.9.3
61
123
62
124
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Swap 'buf' and 'bytes' around for consistency with
3
All that CoQueue needs in order to become thread-safe is help
4
bdrv_co_{pread,pwrite}(), and in preparation to implement these
4
from an external mutex. Add this to the API.
5
functions using generated_co_wrapper.
5
6
6
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
7
Callers were updated using this Coccinelle script:
7
Reviewed-by: Fam Zheng <famz@redhat.com>
8
8
Message-id: 20170213181244.16297-6-pbonzini@redhat.com
9
@@ expression child, offset, buf, bytes, flags; @@
9
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
10
- bdrv_pread(child, offset, buf, bytes, flags)
11
+ bdrv_pread(child, offset, bytes, buf, flags)
12
13
@@ expression child, offset, buf, bytes, flags; @@
14
- bdrv_pwrite(child, offset, buf, bytes, flags)
15
+ bdrv_pwrite(child, offset, bytes, buf, flags)
16
17
@@ expression child, offset, buf, bytes, flags; @@
18
- bdrv_pwrite_sync(child, offset, buf, bytes, flags)
19
+ bdrv_pwrite_sync(child, offset, bytes, buf, flags)
20
21
Resulting overly-long lines were then fixed by hand.
22
23
Signed-off-by: Alberto Faria <afaria@redhat.com>
24
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
25
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
26
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
27
Message-Id: <20220609152744.3891847-3-afaria@redhat.com>
28
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
29
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
30
---
10
---
31
include/block/block-io.h | 10 +++---
11
include/qemu/coroutine.h | 8 +++++---
32
block/blklogwrites.c | 6 ++--
12
block/backup.c | 2 +-
33
block/bochs.c | 10 +++---
13
block/io.c | 4 ++--
34
block/cloop.c | 10 +++---
14
block/nbd-client.c | 2 +-
35
block/crypto.c | 4 +--
15
block/qcow2-cluster.c | 4 +---
36
block/dmg.c | 26 +++++++--------
16
block/sheepdog.c | 2 +-
37
block/io.c | 12 +++----
17
block/throttle-groups.c | 2 +-
38
block/parallels-ext.c | 6 ++--
18
hw/9pfs/9p.c | 2 +-
39
block/parallels.c | 10 +++---
19
util/qemu-coroutine-lock.c | 24 +++++++++++++++++++++---
40
block/qcow.c | 34 +++++++++----------
20
9 files changed, 34 insertions(+), 16 deletions(-)
41
block/qcow2-bitmap.c | 14 ++++----
21
42
block/qcow2-cache.c | 8 ++---
22
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
43
block/qcow2-cluster.c | 22 ++++++-------
23
index XXXXXXX..XXXXXXX 100644
44
block/qcow2-refcount.c | 56 +++++++++++++++++---------------
24
--- a/include/qemu/coroutine.h
45
block/qcow2-snapshot.c | 48 +++++++++++++--------------
25
+++ b/include/qemu/coroutine.h
46
block/qcow2.c | 47 ++++++++++++++-------------
26
@@ -XXX,XX +XXX,XX @@ void coroutine_fn qemu_co_mutex_unlock(CoMutex *mutex);
47
block/qed.c | 8 ++---
27
48
block/vdi.c | 14 ++++----
28
/**
49
block/vhdx-log.c | 18 +++++-----
29
* CoQueues are a mechanism to queue coroutines in order to continue executing
50
block/vhdx.c | 28 ++++++++--------
30
- * them later.
51
block/vmdk.c | 50 ++++++++++++++--------------
31
+ * them later. They are similar to condition variables, but they need help
52
block/vpc.c | 22 ++++++-------
32
+ * from an external mutex in order to maintain thread-safety.
53
block/vvfat.c | 10 +++---
33
*/
54
tests/unit/test-block-iothread.c | 8 ++---
34
typedef struct CoQueue {
55
24 files changed, 242 insertions(+), 239 deletions(-)
35
QSIMPLEQ_HEAD(, Coroutine) entries;
56
36
@@ -XXX,XX +XXX,XX @@ void qemu_co_queue_init(CoQueue *queue);
57
diff --git a/include/block/block-io.h b/include/block/block-io.h
37
58
index XXXXXXX..XXXXXXX 100644
38
/**
59
--- a/include/block/block-io.h
39
* Adds the current coroutine to the CoQueue and transfers control to the
60
+++ b/include/block/block-io.h
40
- * caller of the coroutine.
61
@@ -XXX,XX +XXX,XX @@
41
+ * caller of the coroutine. The mutex is unlocked during the wait and
62
int bdrv_pwrite_zeroes(BdrvChild *child, int64_t offset,
42
+ * locked again afterwards.
63
int64_t bytes, BdrvRequestFlags flags);
43
*/
64
int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags);
44
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue);
65
-int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes,
45
+void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex);
66
+int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
46
67
BdrvRequestFlags flags);
47
/**
68
-int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
48
* Restarts the next coroutine in the CoQueue and removes it from the queue.
69
- int64_t bytes, BdrvRequestFlags flags);
49
diff --git a/block/backup.c b/block/backup.c
70
-int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
50
index XXXXXXX..XXXXXXX 100644
71
- const void *buf, int64_t bytes, BdrvRequestFlags flags);
51
--- a/block/backup.c
72
+int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
52
+++ b/block/backup.c
73
+ const void *buf, BdrvRequestFlags flags);
53
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn wait_for_overlapping_requests(BackupBlockJob *job,
74
+int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
54
retry = false;
75
+ const void *buf, BdrvRequestFlags flags);
55
QLIST_FOREACH(req, &job->inflight_reqs, list) {
76
/*
56
if (end > req->start && start < req->end) {
77
* Efficiently zero a region of the disk image. Note that this is a regular
57
- qemu_co_queue_wait(&req->wait_queue);
78
* I/O request like read or write and should have a reasonable size. This
58
+ qemu_co_queue_wait(&req->wait_queue, NULL);
79
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
59
retry = true;
80
index XXXXXXX..XXXXXXX 100644
60
break;
81
--- a/block/blklogwrites.c
82
+++ b/block/blklogwrites.c
83
@@ -XXX,XX +XXX,XX @@ static uint64_t blk_log_writes_find_cur_log_sector(BdrvChild *log,
84
struct log_write_entry cur_entry;
85
86
while (cur_idx < nr_entries) {
87
- int read_ret = bdrv_pread(log, cur_sector << sector_bits, &cur_entry,
88
- sizeof(cur_entry), 0);
89
+ int read_ret = bdrv_pread(log, cur_sector << sector_bits,
90
+ sizeof(cur_entry), &cur_entry, 0);
91
if (read_ret < 0) {
92
error_setg_errno(errp, -read_ret,
93
"Failed to read log entry %"PRIu64, cur_idx);
94
@@ -XXX,XX +XXX,XX @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
95
log_sb.nr_entries = cpu_to_le64(0);
96
log_sb.sectorsize = cpu_to_le32(BDRV_SECTOR_SIZE);
97
} else {
98
- ret = bdrv_pread(s->log_file, 0, &log_sb, sizeof(log_sb), 0);
99
+ ret = bdrv_pread(s->log_file, 0, sizeof(log_sb), &log_sb, 0);
100
if (ret < 0) {
101
error_setg_errno(errp, -ret, "Could not read log superblock");
102
goto fail_log;
103
diff --git a/block/bochs.c b/block/bochs.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/block/bochs.c
106
+++ b/block/bochs.c
107
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
108
return -EINVAL;
109
}
110
111
- ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs), 0);
112
+ ret = bdrv_pread(bs->file, 0, sizeof(bochs), &bochs, 0);
113
if (ret < 0) {
114
return ret;
115
}
116
@@ -XXX,XX +XXX,XX @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
117
return -ENOMEM;
118
}
119
120
- ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_bitmap,
121
- s->catalog_size * 4, 0);
122
+ ret = bdrv_pread(bs->file, le32_to_cpu(bochs.header), s->catalog_size * 4,
123
+ s->catalog_bitmap, 0);
124
if (ret < 0) {
125
goto fail;
126
}
127
@@ -XXX,XX +XXX,XX @@ static int64_t seek_to_sector(BlockDriverState *bs, int64_t sector_num)
128
(s->extent_blocks + s->bitmap_blocks));
129
130
/* read in bitmap for current extent */
131
- ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8),
132
- &bitmap_entry, 1, 0);
133
+ ret = bdrv_pread(bs->file, bitmap_offset + (extent_offset / 8), 1,
134
+ &bitmap_entry, 0);
135
if (ret < 0) {
136
return ret;
137
}
138
diff --git a/block/cloop.c b/block/cloop.c
139
index XXXXXXX..XXXXXXX 100644
140
--- a/block/cloop.c
141
+++ b/block/cloop.c
142
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
143
}
144
145
/* read header */
146
- ret = bdrv_pread(bs->file, 128, &s->block_size, 4, 0);
147
+ ret = bdrv_pread(bs->file, 128, 4, &s->block_size, 0);
148
if (ret < 0) {
149
return ret;
150
}
151
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
152
return -EINVAL;
153
}
154
155
- ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4, 0);
156
+ ret = bdrv_pread(bs->file, 128 + 4, 4, &s->n_blocks, 0);
157
if (ret < 0) {
158
return ret;
159
}
160
@@ -XXX,XX +XXX,XX @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
161
return -ENOMEM;
162
}
163
164
- ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size, 0);
165
+ ret = bdrv_pread(bs->file, 128 + 4 + 4, offsets_size, s->offsets, 0);
166
if (ret < 0) {
167
goto fail;
168
}
169
@@ -XXX,XX +XXX,XX @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
170
int ret;
171
uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
172
173
- ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
174
- bytes, 0);
175
+ ret = bdrv_pread(bs->file, s->offsets[block_num], bytes,
176
+ s->compressed_block, 0);
177
if (ret != bytes) {
178
return -1;
179
}
180
diff --git a/block/crypto.c b/block/crypto.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/block/crypto.c
183
+++ b/block/crypto.c
184
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
185
BlockDriverState *bs = opaque;
186
ssize_t ret;
187
188
- ret = bdrv_pread(bs->file, offset, buf, buflen, 0);
189
+ ret = bdrv_pread(bs->file, offset, buflen, buf, 0);
190
if (ret < 0) {
191
error_setg_errno(errp, -ret, "Could not read encryption header");
192
return ret;
193
@@ -XXX,XX +XXX,XX @@ static ssize_t block_crypto_write_func(QCryptoBlock *block,
194
BlockDriverState *bs = opaque;
195
ssize_t ret;
196
197
- ret = bdrv_pwrite(bs->file, offset, buf, buflen, 0);
198
+ ret = bdrv_pwrite(bs->file, offset, buflen, buf, 0);
199
if (ret < 0) {
200
error_setg_errno(errp, -ret, "Could not write encryption header");
201
return ret;
202
diff --git a/block/dmg.c b/block/dmg.c
203
index XXXXXXX..XXXXXXX 100644
204
--- a/block/dmg.c
205
+++ b/block/dmg.c
206
@@ -XXX,XX +XXX,XX @@ static int read_uint64(BlockDriverState *bs, int64_t offset, uint64_t *result)
207
uint64_t buffer;
208
int ret;
209
210
- ret = bdrv_pread(bs->file, offset, &buffer, 8, 0);
211
+ ret = bdrv_pread(bs->file, offset, 8, &buffer, 0);
212
if (ret < 0) {
213
return ret;
214
}
215
@@ -XXX,XX +XXX,XX @@ static int read_uint32(BlockDriverState *bs, int64_t offset, uint32_t *result)
216
uint32_t buffer;
217
int ret;
218
219
- ret = bdrv_pread(bs->file, offset, &buffer, 4, 0);
220
+ ret = bdrv_pread(bs->file, offset, 4, &buffer, 0);
221
if (ret < 0) {
222
return ret;
223
}
224
@@ -XXX,XX +XXX,XX @@ static int64_t dmg_find_koly_offset(BdrvChild *file, Error **errp)
225
offset = length - 511 - 512;
226
}
227
length = length < 515 ? length : 515;
228
- ret = bdrv_pread(file, offset, buffer, length, 0);
229
+ ret = bdrv_pread(file, offset, length, buffer, 0);
230
if (ret < 0) {
231
error_setg_errno(errp, -ret, "Failed while reading UDIF trailer");
232
return ret;
233
@@ -XXX,XX +XXX,XX @@ static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds,
234
offset += 4;
235
236
buffer = g_realloc(buffer, count);
237
- ret = bdrv_pread(bs->file, offset, buffer, count, 0);
238
+ ret = bdrv_pread(bs->file, offset, count, buffer, 0);
239
if (ret < 0) {
240
goto fail;
241
}
242
@@ -XXX,XX +XXX,XX @@ static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds,
243
244
buffer = g_malloc(info_length + 1);
245
buffer[info_length] = '\0';
246
- ret = bdrv_pread(bs->file, info_begin, buffer, info_length, 0);
247
+ ret = bdrv_pread(bs->file, info_begin, info_length, buffer, 0);
248
if (ret != info_length) {
249
ret = -EINVAL;
250
goto fail;
251
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
252
case UDZO: { /* zlib compressed */
253
/* we need to buffer, because only the chunk as whole can be
254
* inflated. */
255
- ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
256
- s->lengths[chunk], 0);
257
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
258
+ s->compressed_chunk, 0);
259
if (ret != s->lengths[chunk]) {
260
return -1;
261
}
262
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
263
}
264
/* we need to buffer, because only the chunk as whole can be
265
* inflated. */
266
- ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
267
- s->lengths[chunk], 0);
268
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
269
+ s->compressed_chunk, 0);
270
if (ret != s->lengths[chunk]) {
271
return -1;
272
}
273
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
274
}
275
/* we need to buffer, because only the chunk as whole can be
276
* inflated. */
277
- ret = bdrv_pread(bs->file, s->offsets[chunk], s->compressed_chunk,
278
- s->lengths[chunk], 0);
279
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
280
+ s->compressed_chunk, 0);
281
if (ret != s->lengths[chunk]) {
282
return -1;
283
}
284
@@ -XXX,XX +XXX,XX @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num)
285
}
286
break;
287
case UDRW: /* copy */
288
- ret = bdrv_pread(bs->file, s->offsets[chunk],
289
- s->uncompressed_chunk, s->lengths[chunk], 0);
290
+ ret = bdrv_pread(bs->file, s->offsets[chunk], s->lengths[chunk],
291
+ s->uncompressed_chunk, 0);
292
if (ret != s->lengths[chunk]) {
293
return -1;
294
}
61
}
295
diff --git a/block/io.c b/block/io.c
62
diff --git a/block/io.c b/block/io.c
296
index XXXXXXX..XXXXXXX 100644
63
index XXXXXXX..XXXXXXX 100644
297
--- a/block/io.c
64
--- a/block/io.c
298
+++ b/block/io.c
65
+++ b/block/io.c
299
@@ -XXX,XX +XXX,XX @@ int bdrv_make_zero(BdrvChild *child, BdrvRequestFlags flags)
66
@@ -XXX,XX +XXX,XX @@ static bool coroutine_fn wait_serialising_requests(BdrvTrackedRequest *self)
300
}
67
* (instead of producing a deadlock in the former case). */
301
68
if (!req->waiting_for) {
302
/* See bdrv_pwrite() for the return codes */
69
self->waiting_for = req;
303
-int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes,
70
- qemu_co_queue_wait(&req->wait_queue);
304
+int bdrv_pread(BdrvChild *child, int64_t offset, int64_t bytes, void *buf,
71
+ qemu_co_queue_wait(&req->wait_queue, NULL);
305
BdrvRequestFlags flags)
72
self->waiting_for = NULL;
306
{
73
retry = true;
307
int ret;
74
waited = true;
308
@@ -XXX,XX +XXX,XX @@ int bdrv_pread(BdrvChild *child, int64_t offset, void *buf, int64_t bytes,
75
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
309
-EINVAL Invalid offset or number of bytes
76
310
-EACCES Trying to write a read-only device
77
/* Wait until any previous flushes are completed */
311
*/
78
while (bs->active_flush_req) {
312
-int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
79
- qemu_co_queue_wait(&bs->flush_queue);
313
- int64_t bytes, BdrvRequestFlags flags)
80
+ qemu_co_queue_wait(&bs->flush_queue, NULL);
314
+int bdrv_pwrite(BdrvChild *child, int64_t offset, int64_t bytes,
81
}
315
+ const void *buf, BdrvRequestFlags flags)
82
316
{
83
bs->active_flush_req = true;
317
int ret;
84
diff --git a/block/nbd-client.c b/block/nbd-client.c
318
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
85
index XXXXXXX..XXXXXXX 100644
319
@@ -XXX,XX +XXX,XX @@ int bdrv_pwrite(BdrvChild *child, int64_t offset, const void *buf,
86
--- a/block/nbd-client.c
320
*
87
+++ b/block/nbd-client.c
321
* Returns 0 on success, -errno in error cases.
88
@@ -XXX,XX +XXX,XX @@ static void nbd_coroutine_start(NBDClientSession *s,
322
*/
89
/* Poor man semaphore. The free_sema is locked when no other request
323
-int bdrv_pwrite_sync(BdrvChild *child, int64_t offset,
90
* can be accepted, and unlocked after receiving one reply. */
324
- const void *buf, int64_t count, BdrvRequestFlags flags)
91
if (s->in_flight == MAX_NBD_REQUESTS) {
325
+int bdrv_pwrite_sync(BdrvChild *child, int64_t offset, int64_t bytes,
92
- qemu_co_queue_wait(&s->free_sema);
326
+ const void *buf, BdrvRequestFlags flags)
93
+ qemu_co_queue_wait(&s->free_sema, NULL);
327
{
94
assert(s->in_flight < MAX_NBD_REQUESTS);
328
int ret;
95
}
329
IO_CODE();
96
s->in_flight++;
330
331
- ret = bdrv_pwrite(child, offset, buf, count, flags);
332
+ ret = bdrv_pwrite(child, offset, bytes, buf, flags);
333
if (ret < 0) {
334
return ret;
335
}
336
diff --git a/block/parallels-ext.c b/block/parallels-ext.c
337
index XXXXXXX..XXXXXXX 100644
338
--- a/block/parallels-ext.c
339
+++ b/block/parallels-ext.c
340
@@ -XXX,XX +XXX,XX @@ static int parallels_load_bitmap_data(BlockDriverState *bs,
341
if (entry == 1) {
342
bdrv_dirty_bitmap_deserialize_ones(bitmap, offset, count, false);
343
} else {
344
- ret = bdrv_pread(bs->file, entry << BDRV_SECTOR_BITS, buf,
345
- s->cluster_size, 0);
346
+ ret = bdrv_pread(bs->file, entry << BDRV_SECTOR_BITS,
347
+ s->cluster_size, buf, 0);
348
if (ret < 0) {
349
error_setg_errno(errp, -ret,
350
"Failed to read bitmap data cluster");
351
@@ -XXX,XX +XXX,XX @@ int parallels_read_format_extension(BlockDriverState *bs,
352
353
assert(ext_off > 0);
354
355
- ret = bdrv_pread(bs->file, ext_off, ext_cluster, s->cluster_size, 0);
356
+ ret = bdrv_pread(bs->file, ext_off, s->cluster_size, ext_cluster, 0);
357
if (ret < 0) {
358
error_setg_errno(errp, -ret, "Failed to read Format Extension cluster");
359
goto out;
360
diff --git a/block/parallels.c b/block/parallels.c
361
index XXXXXXX..XXXXXXX 100644
362
--- a/block/parallels.c
363
+++ b/block/parallels.c
364
@@ -XXX,XX +XXX,XX @@ static coroutine_fn int parallels_co_flush_to_os(BlockDriverState *bs)
365
if (off + to_write > s->header_size) {
366
to_write = s->header_size - off;
367
}
368
- ret = bdrv_pwrite(bs->file, off, (uint8_t *)s->header + off, to_write,
369
+ ret = bdrv_pwrite(bs->file, off, to_write, (uint8_t *)s->header + off,
370
0);
371
if (ret < 0) {
372
qemu_co_mutex_unlock(&s->lock);
373
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
374
375
ret = 0;
376
if (flush_bat) {
377
- ret = bdrv_pwrite_sync(bs->file, 0, s->header, s->header_size, 0);
378
+ ret = bdrv_pwrite_sync(bs->file, 0, s->header_size, s->header, 0);
379
if (ret < 0) {
380
res->check_errors++;
381
goto out;
382
@@ -XXX,XX +XXX,XX @@ static int parallels_update_header(BlockDriverState *bs)
383
if (size > s->header_size) {
384
size = s->header_size;
385
}
386
- return bdrv_pwrite_sync(bs->file, 0, s->header, size, 0);
387
+ return bdrv_pwrite_sync(bs->file, 0, size, s->header, 0);
388
}
389
390
static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
391
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
392
return -EINVAL;
393
}
394
395
- ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph), 0);
396
+ ret = bdrv_pread(bs->file, 0, sizeof(ph), &ph, 0);
397
if (ret < 0) {
398
goto fail;
399
}
400
@@ -XXX,XX +XXX,XX @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
401
s->header_size = size;
402
}
403
404
- ret = bdrv_pread(bs->file, 0, s->header, s->header_size, 0);
405
+ ret = bdrv_pread(bs->file, 0, s->header_size, s->header, 0);
406
if (ret < 0) {
407
goto fail;
408
}
409
diff --git a/block/qcow.c b/block/qcow.c
410
index XXXXXXX..XXXXXXX 100644
411
--- a/block/qcow.c
412
+++ b/block/qcow.c
413
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
414
goto fail;
415
}
416
417
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
418
+ ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
419
if (ret < 0) {
420
goto fail;
421
}
422
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
423
goto fail;
424
}
425
426
- ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
427
- s->l1_size * sizeof(uint64_t), 0);
428
+ ret = bdrv_pread(bs->file, s->l1_table_offset,
429
+ s->l1_size * sizeof(uint64_t), s->l1_table, 0);
430
if (ret < 0) {
431
goto fail;
432
}
433
@@ -XXX,XX +XXX,XX @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
434
ret = -EINVAL;
435
goto fail;
436
}
437
- ret = bdrv_pread(bs->file, header.backing_file_offset,
438
- bs->auto_backing_file, len, 0);
439
+ ret = bdrv_pread(bs->file, header.backing_file_offset, len,
440
+ bs->auto_backing_file, 0);
441
if (ret < 0) {
442
goto fail;
443
}
444
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
445
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
446
ret = bdrv_pwrite_sync(bs->file,
447
s->l1_table_offset + l1_index * sizeof(tmp),
448
- &tmp, sizeof(tmp), 0);
449
+ sizeof(tmp), &tmp, 0);
450
if (ret < 0) {
451
return ret;
452
}
453
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
454
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
455
if (new_l2_table) {
456
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
457
- ret = bdrv_pwrite_sync(bs->file, l2_offset, l2_table,
458
- s->l2_size * sizeof(uint64_t), 0);
459
+ ret = bdrv_pwrite_sync(bs->file, l2_offset,
460
+ s->l2_size * sizeof(uint64_t), l2_table, 0);
461
if (ret < 0) {
462
return ret;
463
}
464
} else {
465
- ret = bdrv_pread(bs->file, l2_offset, l2_table,
466
- s->l2_size * sizeof(uint64_t), 0);
467
+ ret = bdrv_pread(bs->file, l2_offset, s->l2_size * sizeof(uint64_t),
468
+ l2_table, 0);
469
if (ret < 0) {
470
return ret;
471
}
472
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
473
cluster_offset = QEMU_ALIGN_UP(cluster_offset, s->cluster_size);
474
/* write the cluster content */
475
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
476
- ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_cache,
477
- s->cluster_size, 0);
478
+ ret = bdrv_pwrite(bs->file, cluster_offset, s->cluster_size,
479
+ s->cluster_cache, 0);
480
if (ret < 0) {
481
return ret;
482
}
483
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
484
}
485
BLKDBG_EVENT(bs->file, BLKDBG_WRITE_AIO);
486
ret = bdrv_pwrite(bs->file, cluster_offset + i,
487
- s->cluster_data,
488
- BDRV_SECTOR_SIZE, 0);
489
+ BDRV_SECTOR_SIZE,
490
+ s->cluster_data, 0);
491
if (ret < 0) {
492
return ret;
493
}
494
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
495
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
496
}
497
ret = bdrv_pwrite_sync(bs->file, l2_offset + l2_index * sizeof(tmp),
498
- &tmp, sizeof(tmp), 0);
499
+ sizeof(tmp), &tmp, 0);
500
if (ret < 0) {
501
return ret;
502
}
503
@@ -XXX,XX +XXX,XX @@ static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
504
csize = cluster_offset >> (63 - s->cluster_bits);
505
csize &= (s->cluster_size - 1);
506
BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED);
507
- ret = bdrv_pread(bs->file, coffset, s->cluster_data, csize, 0);
508
+ ret = bdrv_pread(bs->file, coffset, csize, s->cluster_data, 0);
509
if (ret != csize)
510
return -1;
511
if (decompress_buffer(s->cluster_cache, s->cluster_size,
512
@@ -XXX,XX +XXX,XX @@ static int qcow_make_empty(BlockDriverState *bs)
513
int ret;
514
515
memset(s->l1_table, 0, l1_length);
516
- if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, s->l1_table, l1_length,
517
+ if (bdrv_pwrite_sync(bs->file, s->l1_table_offset, l1_length, s->l1_table,
518
0) < 0)
519
return -1;
520
ret = bdrv_truncate(bs->file, s->l1_table_offset + l1_length, false,
521
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
522
index XXXXXXX..XXXXXXX 100644
523
--- a/block/qcow2-bitmap.c
524
+++ b/block/qcow2-bitmap.c
525
@@ -XXX,XX +XXX,XX @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
526
}
527
528
assert(tb->size <= BME_MAX_TABLE_SIZE);
529
- ret = bdrv_pread(bs->file, tb->offset, table,
530
- tb->size * BME_TABLE_ENTRY_SIZE, 0);
531
+ ret = bdrv_pread(bs->file, tb->offset, tb->size * BME_TABLE_ENTRY_SIZE,
532
+ table, 0);
533
if (ret < 0) {
534
goto fail;
535
}
536
@@ -XXX,XX +XXX,XX @@ static int load_bitmap_data(BlockDriverState *bs,
537
* already cleared */
538
}
539
} else {
540
- ret = bdrv_pread(bs->file, data_offset, buf, s->cluster_size, 0);
541
+ ret = bdrv_pread(bs->file, data_offset, s->cluster_size, buf, 0);
542
if (ret < 0) {
543
goto finish;
544
}
545
@@ -XXX,XX +XXX,XX @@ static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset,
546
}
547
dir_end = dir + size;
548
549
- ret = bdrv_pread(bs->file, offset, dir, size, 0);
550
+ ret = bdrv_pread(bs->file, offset, size, dir, 0);
551
if (ret < 0) {
552
error_setg_errno(errp, -ret, "Failed to read bitmap directory");
553
goto fail;
554
@@ -XXX,XX +XXX,XX @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list,
555
goto fail;
556
}
557
558
- ret = bdrv_pwrite(bs->file, dir_offset, dir, dir_size, 0);
559
+ ret = bdrv_pwrite(bs->file, dir_offset, dir_size, dir, 0);
560
if (ret < 0) {
561
goto fail;
562
}
563
@@ -XXX,XX +XXX,XX @@ static uint64_t *store_bitmap_data(BlockDriverState *bs,
564
goto fail;
565
}
566
567
- ret = bdrv_pwrite(bs->file, off, buf, s->cluster_size, 0);
568
+ ret = bdrv_pwrite(bs->file, off, s->cluster_size, buf, 0);
569
if (ret < 0) {
570
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
571
bm_name);
572
@@ -XXX,XX +XXX,XX @@ static int store_bitmap(BlockDriverState *bs, Qcow2Bitmap *bm, Error **errp)
573
}
574
575
bitmap_table_to_be(tb, tb_size);
576
- ret = bdrv_pwrite(bs->file, tb_offset, tb, tb_size * sizeof(tb[0]), 0);
577
+ ret = bdrv_pwrite(bs->file, tb_offset, tb_size * sizeof(tb[0]), tb, 0);
578
if (ret < 0) {
579
error_setg_errno(errp, -ret, "Failed to write bitmap '%s' to file",
580
bm_name);
581
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
582
index XXXXXXX..XXXXXXX 100644
583
--- a/block/qcow2-cache.c
584
+++ b/block/qcow2-cache.c
585
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
586
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
587
}
588
589
- ret = bdrv_pwrite(bs->file, c->entries[i].offset,
590
- qcow2_cache_get_table_addr(c, i), c->table_size, 0);
591
+ ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->table_size,
592
+ qcow2_cache_get_table_addr(c, i), 0);
593
if (ret < 0) {
594
return ret;
595
}
596
@@ -XXX,XX +XXX,XX @@ static int qcow2_cache_do_get(BlockDriverState *bs, Qcow2Cache *c,
597
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
598
}
599
600
- ret = bdrv_pread(bs->file, offset, qcow2_cache_get_table_addr(c, i),
601
- c->table_size, 0);
602
+ ret = bdrv_pread(bs->file, offset, c->table_size,
603
+ qcow2_cache_get_table_addr(c, i), 0);
604
if (ret < 0) {
605
return ret;
606
}
607
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
97
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
608
index XXXXXXX..XXXXXXX 100644
98
index XXXXXXX..XXXXXXX 100644
609
--- a/block/qcow2-cluster.c
99
--- a/block/qcow2-cluster.c
610
+++ b/block/qcow2-cluster.c
100
+++ b/block/qcow2-cluster.c
611
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
101
@@ -XXX,XX +XXX,XX @@ static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset,
612
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
102
if (bytes == 0) {
613
for(i = 0; i < s->l1_size; i++)
103
/* Wait for the dependency to complete. We need to recheck
614
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
104
* the free/allocated clusters when we continue. */
615
- ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_table,
105
- qemu_co_mutex_unlock(&s->lock);
616
- new_l1_size2, 0);
106
- qemu_co_queue_wait(&old_alloc->dependent_requests);
617
+ ret = bdrv_pwrite_sync(bs->file, new_l1_table_offset, new_l1_size2,
107
- qemu_co_mutex_lock(&s->lock);
618
+ new_l1_table, 0);
108
+ qemu_co_queue_wait(&old_alloc->dependent_requests, &s->lock);
619
if (ret < 0)
109
return -EAGAIN;
620
goto fail;
621
for(i = 0; i < s->l1_size; i++)
622
@@ -XXX,XX +XXX,XX @@ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size,
623
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_ACTIVATE_TABLE);
624
stl_be_p(data, new_l1_size);
625
stq_be_p(data + 4, new_l1_table_offset);
626
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size), data,
627
- sizeof(data), 0);
628
+ ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_size),
629
+ sizeof(data), data, 0);
630
if (ret < 0) {
631
goto fail;
632
}
633
@@ -XXX,XX +XXX,XX @@ int qcow2_write_l1_entry(BlockDriverState *bs, int l1_index)
634
BLKDBG_EVENT(bs->file, BLKDBG_L1_UPDATE);
635
ret = bdrv_pwrite_sync(bs->file,
636
s->l1_table_offset + L1E_SIZE * l1_start_index,
637
- buf, bufsize, 0);
638
+ bufsize, buf, 0);
639
if (ret < 0) {
640
return ret;
641
}
642
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
643
(void **)&l2_slice);
644
} else {
645
/* load inactive L2 tables from disk */
646
- ret = bdrv_pread(bs->file, slice_offset, l2_slice,
647
- slice_size2, 0);
648
+ ret = bdrv_pread(bs->file, slice_offset, slice_size2,
649
+ l2_slice, 0);
650
}
651
if (ret < 0) {
652
goto fail;
653
@@ -XXX,XX +XXX,XX @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
654
goto fail;
655
}
656
657
- ret = bdrv_pwrite(bs->file, slice_offset, l2_slice,
658
- slice_size2, 0);
659
+ ret = bdrv_pwrite(bs->file, slice_offset, slice_size2,
660
+ l2_slice, 0);
661
if (ret < 0) {
662
goto fail;
663
}
664
@@ -XXX,XX +XXX,XX @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
665
666
l1_table = new_l1_table;
667
668
- ret = bdrv_pread(bs->file, s->snapshots[i].l1_table_offset, l1_table,
669
- l1_size2, 0);
670
+ ret = bdrv_pread(bs->file, s->snapshots[i].l1_table_offset, l1_size2,
671
+ l1_table, 0);
672
if (ret < 0) {
673
goto fail;
674
}
675
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
676
index XXXXXXX..XXXXXXX 100644
677
--- a/block/qcow2-refcount.c
678
+++ b/block/qcow2-refcount.c
679
@@ -XXX,XX +XXX,XX @@ int qcow2_refcount_init(BlockDriverState *bs)
680
}
681
BLKDBG_EVENT(bs->file, BLKDBG_REFTABLE_LOAD);
682
ret = bdrv_pread(bs->file, s->refcount_table_offset,
683
- s->refcount_table, refcount_table_size2, 0);
684
+ refcount_table_size2, s->refcount_table, 0);
685
if (ret < 0) {
686
goto fail;
687
}
688
@@ -XXX,XX +XXX,XX @@ static int alloc_refcount_block(BlockDriverState *bs,
689
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_HOOKUP);
690
ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset +
691
refcount_table_index * REFTABLE_ENTRY_SIZE,
692
- &data64, sizeof(data64), 0);
693
+ sizeof(data64), &data64, 0);
694
if (ret < 0) {
695
goto fail;
696
}
697
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
698
}
699
700
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE);
701
- ret = bdrv_pwrite_sync(bs->file, table_offset, new_table,
702
- table_size * REFTABLE_ENTRY_SIZE, 0);
703
+ ret = bdrv_pwrite_sync(bs->file, table_offset,
704
+ table_size * REFTABLE_ENTRY_SIZE, new_table, 0);
705
if (ret < 0) {
706
goto fail;
707
}
708
@@ -XXX,XX +XXX,XX @@ int64_t qcow2_refcount_area(BlockDriverState *bs, uint64_t start_offset,
709
data.d32 = cpu_to_be32(table_clusters);
710
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE);
711
ret = bdrv_pwrite_sync(bs->file,
712
- offsetof(QCowHeader, refcount_table_offset), &data,
713
- sizeof(data), 0);
714
+ offsetof(QCowHeader, refcount_table_offset),
715
+ sizeof(data), &data, 0);
716
if (ret < 0) {
717
goto fail;
718
}
719
@@ -XXX,XX +XXX,XX @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
720
}
721
l1_allocated = true;
722
723
- ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size2, 0);
724
+ ret = bdrv_pread(bs->file, l1_table_offset, l1_size2, l1_table, 0);
725
if (ret < 0) {
726
goto fail;
727
}
728
@@ -XXX,XX +XXX,XX @@ fail:
729
cpu_to_be64s(&l1_table[i]);
730
}
731
732
- ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_table, l1_size2,
733
+ ret = bdrv_pwrite_sync(bs->file, l1_table_offset, l1_size2, l1_table,
734
0);
735
736
for (i = 0; i < l1_size; i++) {
737
@@ -XXX,XX +XXX,XX @@ static int fix_l2_entry_by_zero(BlockDriverState *bs, BdrvCheckResult *res,
738
goto fail;
739
}
740
741
- ret = bdrv_pwrite_sync(bs->file, l2e_offset, &l2_table[idx],
742
- l2_entry_size(s), 0);
743
+ ret = bdrv_pwrite_sync(bs->file, l2e_offset, l2_entry_size(s),
744
+ &l2_table[idx], 0);
745
if (ret < 0) {
746
fprintf(stderr, "ERROR: Failed to overwrite L2 "
747
"table entry: %s\n", strerror(-ret));
748
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l2(BlockDriverState *bs, BdrvCheckResult *res,
749
bool metadata_overlap;
750
751
/* Read L2 table from disk */
752
- ret = bdrv_pread(bs->file, l2_offset, l2_table, l2_size_bytes, 0);
753
+ ret = bdrv_pread(bs->file, l2_offset, l2_size_bytes, l2_table, 0);
754
if (ret < 0) {
755
fprintf(stderr, "ERROR: I/O error in check_refcounts_l2\n");
756
res->check_errors++;
757
@@ -XXX,XX +XXX,XX @@ static int check_refcounts_l1(BlockDriverState *bs,
758
}
759
760
/* Read L1 table entries from disk */
761
- ret = bdrv_pread(bs->file, l1_table_offset, l1_table, l1_size_bytes, 0);
762
+ ret = bdrv_pread(bs->file, l1_table_offset, l1_size_bytes, l1_table, 0);
763
if (ret < 0) {
764
fprintf(stderr, "ERROR: I/O error in check_refcounts_l1\n");
765
res->check_errors++;
766
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
767
}
110
}
768
}
111
}
769
112
diff --git a/block/sheepdog.c b/block/sheepdog.c
770
- ret = bdrv_pread(bs->file, l2_offset, l2_table,
113
index XXXXXXX..XXXXXXX 100644
771
- s->l2_size * l2_entry_size(s), 0);
114
--- a/block/sheepdog.c
772
+ ret = bdrv_pread(bs->file, l2_offset, s->l2_size * l2_entry_size(s),
115
+++ b/block/sheepdog.c
773
+ l2_table, 0);
116
@@ -XXX,XX +XXX,XX @@ static void wait_for_overlapping_aiocb(BDRVSheepdogState *s, SheepdogAIOCB *acb)
774
if (ret < 0) {
117
retry:
775
fprintf(stderr, "ERROR: Could not read L2 table: %s\n",
118
QLIST_FOREACH(cb, &s->inflight_aiocb_head, aiocb_siblings) {
776
strerror(-ret));
119
if (AIOCBOverlapping(acb, cb)) {
777
@@ -XXX,XX +XXX,XX @@ static int check_oflag_copied(BlockDriverState *bs, BdrvCheckResult *res,
120
- qemu_co_queue_wait(&s->overlapping_queue);
778
goto fail;
121
+ qemu_co_queue_wait(&s->overlapping_queue, NULL);
779
}
122
goto retry;
780
781
- ret = bdrv_pwrite(bs->file, l2_offset, l2_table, s->cluster_size,
782
+ ret = bdrv_pwrite(bs->file, l2_offset, s->cluster_size, l2_table,
783
0);
784
if (ret < 0) {
785
fprintf(stderr, "ERROR: Could not write L2 table: %s\n",
786
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcounts_write_refblocks(
787
on_disk_refblock = (void *)((char *) *refcount_table +
788
refblock_index * s->cluster_size);
789
790
- ret = bdrv_pwrite(bs->file, refblock_offset, on_disk_refblock,
791
- s->cluster_size, 0);
792
+ ret = bdrv_pwrite(bs->file, refblock_offset, s->cluster_size,
793
+ on_disk_refblock, 0);
794
if (ret < 0) {
795
error_setg_errno(errp, -ret, "ERROR writing refblock");
796
return ret;
797
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcount_structure(BlockDriverState *bs,
798
}
799
800
assert(reftable_length < INT_MAX);
801
- ret = bdrv_pwrite(bs->file, reftable_offset, on_disk_reftable,
802
- reftable_length, 0);
803
+ ret = bdrv_pwrite(bs->file, reftable_offset, reftable_length,
804
+ on_disk_reftable, 0);
805
if (ret < 0) {
806
error_setg_errno(errp, -ret, "ERROR writing reftable");
807
goto fail;
808
@@ -XXX,XX +XXX,XX @@ static int rebuild_refcount_structure(BlockDriverState *bs,
809
cpu_to_be32(reftable_clusters);
810
ret = bdrv_pwrite_sync(bs->file,
811
offsetof(QCowHeader, refcount_table_offset),
812
- &reftable_offset_and_clusters,
813
- sizeof(reftable_offset_and_clusters), 0);
814
+ sizeof(reftable_offset_and_clusters),
815
+ &reftable_offset_and_clusters, 0);
816
if (ret < 0) {
817
error_setg_errno(errp, -ret, "ERROR setting reftable");
818
goto fail;
819
@@ -XXX,XX +XXX,XX @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
820
return -ENOMEM;
821
}
822
823
- ret = bdrv_pread(bs->file, l1_ofs, l1, l1_sz2, 0);
824
+ ret = bdrv_pread(bs->file, l1_ofs, l1_sz2, l1, 0);
825
if (ret < 0) {
826
g_free(l1);
827
return ret;
828
@@ -XXX,XX +XXX,XX @@ static int flush_refblock(BlockDriverState *bs, uint64_t **reftable,
829
return ret;
830
}
123
}
831
124
}
832
- ret = bdrv_pwrite(bs->file, offset, refblock, s->cluster_size, 0);
125
diff --git a/block/throttle-groups.c b/block/throttle-groups.c
833
+ ret = bdrv_pwrite(bs->file, offset, s->cluster_size, refblock, 0);
126
index XXXXXXX..XXXXXXX 100644
834
if (ret < 0) {
127
--- a/block/throttle-groups.c
835
error_setg_errno(errp, -ret, "Failed to write refblock");
128
+++ b/block/throttle-groups.c
836
return ret;
129
@@ -XXX,XX +XXX,XX @@ void coroutine_fn throttle_group_co_io_limits_intercept(BlockBackend *blk,
837
@@ -XXX,XX +XXX,XX @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order,
130
if (must_wait || blkp->pending_reqs[is_write]) {
838
cpu_to_be64s(&new_reftable[i]);
131
blkp->pending_reqs[is_write]++;
839
}
132
qemu_mutex_unlock(&tg->lock);
840
133
- qemu_co_queue_wait(&blkp->throttled_reqs[is_write]);
841
- ret = bdrv_pwrite(bs->file, new_reftable_offset, new_reftable,
134
+ qemu_co_queue_wait(&blkp->throttled_reqs[is_write], NULL);
842
- new_reftable_size * REFTABLE_ENTRY_SIZE, 0);
135
qemu_mutex_lock(&tg->lock);
843
+ ret = bdrv_pwrite(bs->file, new_reftable_offset,
136
blkp->pending_reqs[is_write]--;
844
+ new_reftable_size * REFTABLE_ENTRY_SIZE, new_reftable,
137
}
845
+ 0);
138
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
846
139
index XXXXXXX..XXXXXXX 100644
847
for (i = 0; i < new_reftable_size; i++) {
140
--- a/hw/9pfs/9p.c
848
be64_to_cpus(&new_reftable[i]);
141
+++ b/hw/9pfs/9p.c
849
@@ -XXX,XX +XXX,XX @@ int qcow2_shrink_reftable(BlockDriverState *bs)
142
@@ -XXX,XX +XXX,XX @@ static void coroutine_fn v9fs_flush(void *opaque)
850
reftable_tmp[i] = unused_block ? 0 : cpu_to_be64(s->refcount_table[i]);
143
/*
851
}
144
* Wait for pdu to complete.
852
145
*/
853
- ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset, reftable_tmp,
146
- qemu_co_queue_wait(&cancel_pdu->complete);
854
- s->refcount_table_size * REFTABLE_ENTRY_SIZE, 0);
147
+ qemu_co_queue_wait(&cancel_pdu->complete, NULL);
855
+ ret = bdrv_pwrite_sync(bs->file, s->refcount_table_offset,
148
cancel_pdu->cancelled = 0;
856
+ s->refcount_table_size * REFTABLE_ENTRY_SIZE,
149
pdu_free(cancel_pdu);
857
+ reftable_tmp, 0);
150
}
858
/*
151
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
859
* If the write in the reftable failed the image may contain a partially
152
index XXXXXXX..XXXXXXX 100644
860
* overwritten reftable. In this case it would be better to clear the
153
--- a/util/qemu-coroutine-lock.c
861
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
154
+++ b/util/qemu-coroutine-lock.c
862
index XXXXXXX..XXXXXXX 100644
155
@@ -XXX,XX +XXX,XX @@ void qemu_co_queue_init(CoQueue *queue)
863
--- a/block/qcow2-snapshot.c
156
QSIMPLEQ_INIT(&queue->entries);
864
+++ b/block/qcow2-snapshot.c
865
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
866
867
/* Read statically sized part of the snapshot header */
868
offset = ROUND_UP(offset, 8);
869
- ret = bdrv_pread(bs->file, offset, &h, sizeof(h), 0);
870
+ ret = bdrv_pread(bs->file, offset, sizeof(h), &h, 0);
871
if (ret < 0) {
872
error_setg_errno(errp, -ret, "Failed to read snapshot table");
873
goto fail;
874
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
875
}
876
877
/* Read known extra data */
878
- ret = bdrv_pread(bs->file, offset, &extra,
879
- MIN(sizeof(extra), sn->extra_data_size), 0);
880
+ ret = bdrv_pread(bs->file, offset,
881
+ MIN(sizeof(extra), sn->extra_data_size), &extra, 0);
882
if (ret < 0) {
883
error_setg_errno(errp, -ret, "Failed to read snapshot table");
884
goto fail;
885
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
886
/* Store unknown extra data */
887
unknown_extra_data_size = sn->extra_data_size - sizeof(extra);
888
sn->unknown_extra_data = g_malloc(unknown_extra_data_size);
889
- ret = bdrv_pread(bs->file, offset, sn->unknown_extra_data,
890
- unknown_extra_data_size, 0);
891
+ ret = bdrv_pread(bs->file, offset, unknown_extra_data_size,
892
+ sn->unknown_extra_data, 0);
893
if (ret < 0) {
894
error_setg_errno(errp, -ret,
895
"Failed to read snapshot table");
896
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
897
898
/* Read snapshot ID */
899
sn->id_str = g_malloc(id_str_size + 1);
900
- ret = bdrv_pread(bs->file, offset, sn->id_str, id_str_size, 0);
901
+ ret = bdrv_pread(bs->file, offset, id_str_size, sn->id_str, 0);
902
if (ret < 0) {
903
error_setg_errno(errp, -ret, "Failed to read snapshot table");
904
goto fail;
905
@@ -XXX,XX +XXX,XX @@ static int qcow2_do_read_snapshots(BlockDriverState *bs, bool repair,
906
907
/* Read snapshot name */
908
sn->name = g_malloc(name_size + 1);
909
- ret = bdrv_pread(bs->file, offset, sn->name, name_size, 0);
910
+ ret = bdrv_pread(bs->file, offset, name_size, sn->name, 0);
911
if (ret < 0) {
912
error_setg_errno(errp, -ret, "Failed to read snapshot table");
913
goto fail;
914
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
915
h.name_size = cpu_to_be16(name_size);
916
offset = ROUND_UP(offset, 8);
917
918
- ret = bdrv_pwrite(bs->file, offset, &h, sizeof(h), 0);
919
+ ret = bdrv_pwrite(bs->file, offset, sizeof(h), &h, 0);
920
if (ret < 0) {
921
goto fail;
922
}
923
offset += sizeof(h);
924
925
- ret = bdrv_pwrite(bs->file, offset, &extra, sizeof(extra), 0);
926
+ ret = bdrv_pwrite(bs->file, offset, sizeof(extra), &extra, 0);
927
if (ret < 0) {
928
goto fail;
929
}
930
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
931
assert(unknown_extra_data_size <= BDRV_REQUEST_MAX_BYTES);
932
assert(sn->unknown_extra_data);
933
934
- ret = bdrv_pwrite(bs->file, offset, sn->unknown_extra_data,
935
- unknown_extra_data_size, 0);
936
+ ret = bdrv_pwrite(bs->file, offset, unknown_extra_data_size,
937
+ sn->unknown_extra_data, 0);
938
if (ret < 0) {
939
goto fail;
940
}
941
offset += unknown_extra_data_size;
942
}
943
944
- ret = bdrv_pwrite(bs->file, offset, sn->id_str, id_str_size, 0);
945
+ ret = bdrv_pwrite(bs->file, offset, id_str_size, sn->id_str, 0);
946
if (ret < 0) {
947
goto fail;
948
}
949
offset += id_str_size;
950
951
- ret = bdrv_pwrite(bs->file, offset, sn->name, name_size, 0);
952
+ ret = bdrv_pwrite(bs->file, offset, name_size, sn->name, 0);
953
if (ret < 0) {
954
goto fail;
955
}
956
@@ -XXX,XX +XXX,XX @@ int qcow2_write_snapshots(BlockDriverState *bs)
957
header_data.snapshots_offset = cpu_to_be64(snapshots_offset);
958
959
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
960
- &header_data, sizeof(header_data), 0);
961
+ sizeof(header_data), &header_data, 0);
962
if (ret < 0) {
963
goto fail;
964
}
965
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
966
967
/* qcow2_do_open() discards this information in check mode */
968
ret = bdrv_pread(bs->file, offsetof(QCowHeader, nb_snapshots),
969
- &snapshot_table_pointer, sizeof(snapshot_table_pointer),
970
+ sizeof(snapshot_table_pointer), &snapshot_table_pointer,
971
0);
972
if (ret < 0) {
973
result->check_errors++;
974
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
975
976
snapshot_table_pointer.nb_snapshots = cpu_to_be32(s->nb_snapshots);
977
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
978
- &snapshot_table_pointer.nb_snapshots,
979
- sizeof(snapshot_table_pointer.nb_snapshots), 0);
980
+ sizeof(snapshot_table_pointer.nb_snapshots),
981
+ &snapshot_table_pointer.nb_snapshots, 0);
982
if (ret < 0) {
983
result->check_errors++;
984
fprintf(stderr, "ERROR failed to update the snapshot count in the "
985
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
986
goto fail;
987
}
988
989
- ret = bdrv_pwrite(bs->file, sn->l1_table_offset, l1_table,
990
- s->l1_size * L1E_SIZE, 0);
991
+ ret = bdrv_pwrite(bs->file, sn->l1_table_offset, s->l1_size * L1E_SIZE,
992
+ l1_table, 0);
993
if (ret < 0) {
994
goto fail;
995
}
996
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
997
goto fail;
998
}
999
1000
- ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_table, sn_l1_bytes,
1001
+ ret = bdrv_pread(bs->file, sn->l1_table_offset, sn_l1_bytes, sn_l1_table,
1002
0);
1003
if (ret < 0) {
1004
goto fail;
1005
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
1006
goto fail;
1007
}
1008
1009
- ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, sn_l1_table,
1010
- cur_l1_bytes, 0);
1011
+ ret = bdrv_pwrite_sync(bs->file, s->l1_table_offset, cur_l1_bytes,
1012
+ sn_l1_table, 0);
1013
if (ret < 0) {
1014
goto fail;
1015
}
1016
@@ -XXX,XX +XXX,XX @@ int qcow2_snapshot_load_tmp(BlockDriverState *bs,
1017
return -ENOMEM;
1018
}
1019
1020
- ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_table,
1021
- new_l1_bytes, 0);
1022
+ ret = bdrv_pread(bs->file, sn->l1_table_offset, new_l1_bytes,
1023
+ new_l1_table, 0);
1024
if (ret < 0) {
1025
error_setg(errp, "Failed to read l1 table for snapshot");
1026
qemu_vfree(new_l1_table);
1027
diff --git a/block/qcow2.c b/block/qcow2.c
1028
index XXXXXXX..XXXXXXX 100644
1029
--- a/block/qcow2.c
1030
+++ b/block/qcow2.c
1031
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
1032
return -1;
1033
}
1034
1035
- ret = bdrv_pread(bs->file, s->crypto_header.offset + offset, buf, buflen,
1036
+ ret = bdrv_pread(bs->file, s->crypto_header.offset + offset, buflen, buf,
1037
0);
1038
if (ret < 0) {
1039
error_setg_errno(errp, -ret, "Could not read encryption header");
1040
@@ -XXX,XX +XXX,XX @@ static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
1041
return -1;
1042
}
1043
1044
- ret = bdrv_pwrite(bs->file, s->crypto_header.offset + offset, buf, buflen,
1045
+ ret = bdrv_pwrite(bs->file, s->crypto_header.offset + offset, buflen, buf,
1046
0);
1047
if (ret < 0) {
1048
error_setg_errno(errp, -ret, "Could not read encryption header");
1049
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1050
printf("attempting to read extended header in offset %lu\n", offset);
1051
#endif
1052
1053
- ret = bdrv_pread(bs->file, offset, &ext, sizeof(ext), 0);
1054
+ ret = bdrv_pread(bs->file, offset, sizeof(ext), &ext, 0);
1055
if (ret < 0) {
1056
error_setg_errno(errp, -ret, "qcow2_read_extension: ERROR: "
1057
"pread fail from offset %" PRIu64, offset);
1058
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1059
sizeof(bs->backing_format));
1060
return 2;
1061
}
1062
- ret = bdrv_pread(bs->file, offset, bs->backing_format, ext.len, 0);
1063
+ ret = bdrv_pread(bs->file, offset, ext.len, bs->backing_format, 0);
1064
if (ret < 0) {
1065
error_setg_errno(errp, -ret, "ERROR: ext_backing_format: "
1066
"Could not read format name");
1067
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1068
case QCOW2_EXT_MAGIC_FEATURE_TABLE:
1069
if (p_feature_table != NULL) {
1070
void *feature_table = g_malloc0(ext.len + 2 * sizeof(Qcow2Feature));
1071
- ret = bdrv_pread(bs->file, offset, feature_table, ext.len, 0);
1072
+ ret = bdrv_pread(bs->file, offset, ext.len, feature_table, 0);
1073
if (ret < 0) {
1074
error_setg_errno(errp, -ret, "ERROR: ext_feature_table: "
1075
"Could not read table");
1076
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1077
return -EINVAL;
1078
}
1079
1080
- ret = bdrv_pread(bs->file, offset, &s->crypto_header, ext.len, 0);
1081
+ ret = bdrv_pread(bs->file, offset, ext.len, &s->crypto_header, 0);
1082
if (ret < 0) {
1083
error_setg_errno(errp, -ret,
1084
"Unable to read CRYPTO header extension");
1085
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1086
break;
1087
}
1088
1089
- ret = bdrv_pread(bs->file, offset, &bitmaps_ext, ext.len, 0);
1090
+ ret = bdrv_pread(bs->file, offset, ext.len, &bitmaps_ext, 0);
1091
if (ret < 0) {
1092
error_setg_errno(errp, -ret, "bitmaps_ext: "
1093
"Could not read ext header");
1094
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1095
case QCOW2_EXT_MAGIC_DATA_FILE:
1096
{
1097
s->image_data_file = g_malloc0(ext.len + 1);
1098
- ret = bdrv_pread(bs->file, offset, s->image_data_file, ext.len, 0);
1099
+ ret = bdrv_pread(bs->file, offset, ext.len, s->image_data_file, 0);
1100
if (ret < 0) {
1101
error_setg_errno(errp, -ret,
1102
"ERROR: Could not read data file name");
1103
@@ -XXX,XX +XXX,XX @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
1104
uext->len = ext.len;
1105
QLIST_INSERT_HEAD(&s->unknown_header_ext, uext, next);
1106
1107
- ret = bdrv_pread(bs->file, offset, uext->data, uext->len, 0);
1108
+ ret = bdrv_pread(bs->file, offset, uext->len, uext->data, 0);
1109
if (ret < 0) {
1110
error_setg_errno(errp, -ret, "ERROR: unknown extension: "
1111
"Could not read data");
1112
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
1113
1114
val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY);
1115
ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features),
1116
- &val, sizeof(val), 0);
1117
+ sizeof(val), &val, 0);
1118
if (ret < 0) {
1119
return ret;
1120
}
1121
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1122
uint64_t l1_vm_state_index;
1123
bool update_header = false;
1124
1125
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
1126
+ ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
1127
if (ret < 0) {
1128
error_setg_errno(errp, -ret, "Could not read qcow2 header");
1129
goto fail;
1130
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1131
if (header.header_length > sizeof(header)) {
1132
s->unknown_header_fields_size = header.header_length - sizeof(header);
1133
s->unknown_header_fields = g_malloc(s->unknown_header_fields_size);
1134
- ret = bdrv_pread(bs->file, sizeof(header), s->unknown_header_fields,
1135
- s->unknown_header_fields_size, 0);
1136
+ ret = bdrv_pread(bs->file, sizeof(header),
1137
+ s->unknown_header_fields_size,
1138
+ s->unknown_header_fields, 0);
1139
if (ret < 0) {
1140
error_setg_errno(errp, -ret, "Could not read unknown qcow2 header "
1141
"fields");
1142
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1143
ret = -ENOMEM;
1144
goto fail;
1145
}
1146
- ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_table,
1147
- s->l1_size * L1E_SIZE, 0);
1148
+ ret = bdrv_pread(bs->file, s->l1_table_offset, s->l1_size * L1E_SIZE,
1149
+ s->l1_table, 0);
1150
if (ret < 0) {
1151
error_setg_errno(errp, -ret, "Could not read L1 table");
1152
goto fail;
1153
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
1154
ret = -EINVAL;
1155
goto fail;
1156
}
1157
- ret = bdrv_pread(bs->file, header.backing_file_offset,
1158
- bs->auto_backing_file, len, 0);
1159
+ ret = bdrv_pread(bs->file, header.backing_file_offset, len,
1160
+ bs->auto_backing_file, 0);
1161
if (ret < 0) {
1162
error_setg_errno(errp, -ret, "Could not read backing file name");
1163
goto fail;
1164
@@ -XXX,XX +XXX,XX @@ int qcow2_update_header(BlockDriverState *bs)
1165
}
1166
1167
/* Write the new header */
1168
- ret = bdrv_pwrite(bs->file, 0, header, s->cluster_size, 0);
1169
+ ret = bdrv_pwrite(bs->file, 0, s->cluster_size, header, 0);
1170
if (ret < 0) {
1171
goto fail;
1172
}
1173
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
1174
1175
/* write updated header.size */
1176
offset = cpu_to_be64(offset);
1177
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size), &offset,
1178
- sizeof(offset), 0);
1179
+ ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
1180
+ sizeof(offset), &offset, 0);
1181
if (ret < 0) {
1182
error_setg_errno(errp, -ret, "Failed to update the image size");
1183
goto fail;
1184
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
1185
l1_ofs_rt_ofs_cls.reftable_offset = cpu_to_be64(s->cluster_size);
1186
l1_ofs_rt_ofs_cls.reftable_clusters = cpu_to_be32(1);
1187
ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, l1_table_offset),
1188
- &l1_ofs_rt_ofs_cls, sizeof(l1_ofs_rt_ofs_cls), 0);
1189
+ sizeof(l1_ofs_rt_ofs_cls), &l1_ofs_rt_ofs_cls, 0);
1190
if (ret < 0) {
1191
goto fail_broken_refcounts;
1192
}
1193
@@ -XXX,XX +XXX,XX @@ static int make_completely_empty(BlockDriverState *bs)
1194
1195
/* Enter the first refblock into the reftable */
1196
rt_entry = cpu_to_be64(2 * s->cluster_size);
1197
- ret = bdrv_pwrite_sync(bs->file, s->cluster_size, &rt_entry,
1198
- sizeof(rt_entry), 0);
1199
+ ret = bdrv_pwrite_sync(bs->file, s->cluster_size, sizeof(rt_entry),
1200
+ &rt_entry, 0);
1201
if (ret < 0) {
1202
goto fail_broken_refcounts;
1203
}
1204
diff --git a/block/qed.c b/block/qed.c
1205
index XXXXXXX..XXXXXXX 100644
1206
--- a/block/qed.c
1207
+++ b/block/qed.c
1208
@@ -XXX,XX +XXX,XX @@ int qed_write_header_sync(BDRVQEDState *s)
1209
int ret;
1210
1211
qed_header_cpu_to_le(&s->header, &le);
1212
- ret = bdrv_pwrite(s->bs->file, 0, &le, sizeof(le), 0);
1213
+ ret = bdrv_pwrite(s->bs->file, 0, sizeof(le), &le, 0);
1214
if (ret != sizeof(le)) {
1215
return ret;
1216
}
1217
@@ -XXX,XX +XXX,XX @@ static int qed_read_string(BdrvChild *file, uint64_t offset, size_t n,
1218
if (n >= buflen) {
1219
return -EINVAL;
1220
}
1221
- ret = bdrv_pread(file, offset, buf, n, 0);
1222
+ ret = bdrv_pread(file, offset, n, buf, 0);
1223
if (ret < 0) {
1224
return ret;
1225
}
1226
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options,
1227
int64_t file_size;
1228
int ret;
1229
1230
- ret = bdrv_pread(bs->file, 0, &le_header, sizeof(le_header), 0);
1231
+ ret = bdrv_pread(bs->file, 0, sizeof(le_header), &le_header, 0);
1232
if (ret < 0) {
1233
error_setg(errp, "Failed to read QED header");
1234
return ret;
1235
@@ -XXX,XX +XXX,XX @@ static int bdrv_qed_change_backing_file(BlockDriverState *bs,
1236
}
1237
1238
/* Write new header */
1239
- ret = bdrv_pwrite_sync(bs->file, 0, buffer, buffer_len, 0);
1240
+ ret = bdrv_pwrite_sync(bs->file, 0, buffer_len, buffer, 0);
1241
g_free(buffer);
1242
if (ret == 0) {
1243
memcpy(&s->header, &new_header, sizeof(new_header));
1244
diff --git a/block/vdi.c b/block/vdi.c
1245
index XXXXXXX..XXXXXXX 100644
1246
--- a/block/vdi.c
1247
+++ b/block/vdi.c
1248
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
1249
1250
logout("\n");
1251
1252
- ret = bdrv_pread(bs->file, 0, &header, sizeof(header), 0);
1253
+ ret = bdrv_pread(bs->file, 0, sizeof(header), &header, 0);
1254
if (ret < 0) {
1255
goto fail;
1256
}
1257
@@ -XXX,XX +XXX,XX @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
1258
goto fail;
1259
}
1260
1261
- ret = bdrv_pread(bs->file, header.offset_bmap, s->bmap,
1262
- bmap_size * SECTOR_SIZE, 0);
1263
+ ret = bdrv_pread(bs->file, header.offset_bmap, bmap_size * SECTOR_SIZE,
1264
+ s->bmap, 0);
1265
if (ret < 0) {
1266
goto fail_free_bmap;
1267
}
1268
@@ -XXX,XX +XXX,XX @@ vdi_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes,
1269
* so this full-cluster write does not overlap a partial write
1270
* of the same cluster, issued from the "else" branch.
1271
*/
1272
- ret = bdrv_pwrite(bs->file, data_offset, block, s->block_size, 0);
1273
+ ret = bdrv_pwrite(bs->file, data_offset, s->block_size, block, 0);
1274
qemu_co_rwlock_unlock(&s->bmap_lock);
1275
} else {
1276
nonallocating_write:
1277
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
1278
assert(VDI_IS_ALLOCATED(bmap_first));
1279
*header = s->header;
1280
vdi_header_to_le(header);
1281
- ret = bdrv_pwrite(bs->file, 0, header, sizeof(*header), 0);
1282
+ ret = bdrv_pwrite(bs->file, 0, sizeof(*header), header, 0);
1283
g_free(header);
1284
1285
if (ret < 0) {
1286
@@ -XXX,XX +XXX,XX @@ nonallocating_write:
1287
base = ((uint8_t *)&s->bmap[0]) + bmap_first * SECTOR_SIZE;
1288
logout("will write %u block map sectors starting from entry %u\n",
1289
n_sectors, bmap_first);
1290
- ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE, base,
1291
- n_sectors * SECTOR_SIZE, 0);
1292
+ ret = bdrv_pwrite(bs->file, offset * SECTOR_SIZE,
1293
+ n_sectors * SECTOR_SIZE, base, 0);
1294
}
1295
1296
return ret < 0 ? ret : 0;
1297
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
1298
index XXXXXXX..XXXXXXX 100644
1299
--- a/block/vhdx-log.c
1300
+++ b/block/vhdx-log.c
1301
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_peek_hdr(BlockDriverState *bs, VHDXLogEntries *log,
1302
1303
offset = log->offset + read;
1304
1305
- ret = bdrv_pread(bs->file, offset, hdr, sizeof(VHDXLogEntryHeader), 0);
1306
+ ret = bdrv_pread(bs->file, offset, sizeof(VHDXLogEntryHeader), hdr, 0);
1307
if (ret < 0) {
1308
goto exit;
1309
}
1310
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log,
1311
}
1312
offset = log->offset + read;
1313
1314
- ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE, 0);
1315
+ ret = bdrv_pread(bs->file, offset, VHDX_LOG_SECTOR_SIZE, buffer, 0);
1316
if (ret < 0) {
1317
goto exit;
1318
}
1319
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log,
1320
/* full */
1321
break;
1322
}
1323
- ret = bdrv_pwrite(bs->file, offset, buffer_tmp, VHDX_LOG_SECTOR_SIZE,
1324
+ ret = bdrv_pwrite(bs->file, offset, VHDX_LOG_SECTOR_SIZE, buffer_tmp,
1325
0);
1326
if (ret < 0) {
1327
goto exit;
1328
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_flush_desc(BlockDriverState *bs, VHDXLogDescriptor *desc,
1329
1330
/* count is only > 1 if we are writing zeroes */
1331
for (i = 0; i < count; i++) {
1332
- ret = bdrv_pwrite_sync(bs->file, file_offset, buffer,
1333
- VHDX_LOG_SECTOR_SIZE, 0);
1334
+ ret = bdrv_pwrite_sync(bs->file, file_offset, VHDX_LOG_SECTOR_SIZE,
1335
+ buffer, 0);
1336
if (ret < 0) {
1337
goto exit;
1338
}
1339
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
1340
1341
if (i == 0 && leading_length) {
1342
/* partial sector at the front of the buffer */
1343
- ret = bdrv_pread(bs->file, file_offset, merged_sector,
1344
- VHDX_LOG_SECTOR_SIZE, 0);
1345
+ ret = bdrv_pread(bs->file, file_offset, VHDX_LOG_SECTOR_SIZE,
1346
+ merged_sector, 0);
1347
if (ret < 0) {
1348
goto exit;
1349
}
1350
@@ -XXX,XX +XXX,XX @@ static int vhdx_log_write(BlockDriverState *bs, BDRVVHDXState *s,
1351
} else if (i == sectors - 1 && trailing_length) {
1352
/* partial sector at the end of the buffer */
1353
ret = bdrv_pread(bs->file, file_offset,
1354
- merged_sector + trailing_length,
1355
- VHDX_LOG_SECTOR_SIZE - trailing_length, 0);
1356
+ VHDX_LOG_SECTOR_SIZE - trailing_length,
1357
+ merged_sector + trailing_length, 0);
1358
if (ret < 0) {
1359
goto exit;
1360
}
1361
diff --git a/block/vhdx.c b/block/vhdx.c
1362
index XXXXXXX..XXXXXXX 100644
1363
--- a/block/vhdx.c
1364
+++ b/block/vhdx.c
1365
@@ -XXX,XX +XXX,XX @@ static int vhdx_write_header(BdrvChild *file, VHDXHeader *hdr,
1366
buffer = qemu_blockalign(bs_file, VHDX_HEADER_SIZE);
1367
if (read) {
1368
/* if true, we can't assume the extra reserved bytes are 0 */
1369
- ret = bdrv_pread(file, offset, buffer, VHDX_HEADER_SIZE, 0);
1370
+ ret = bdrv_pread(file, offset, VHDX_HEADER_SIZE, buffer, 0);
1371
if (ret < 0) {
1372
goto exit;
1373
}
1374
@@ -XXX,XX +XXX,XX @@ static int vhdx_write_header(BdrvChild *file, VHDXHeader *hdr,
1375
vhdx_header_le_export(hdr, header_le);
1376
vhdx_update_checksum(buffer, VHDX_HEADER_SIZE,
1377
offsetof(VHDXHeader, checksum));
1378
- ret = bdrv_pwrite_sync(file, offset, header_le, sizeof(VHDXHeader), 0);
1379
+ ret = bdrv_pwrite_sync(file, offset, sizeof(VHDXHeader), header_le, 0);
1380
1381
exit:
1382
qemu_vfree(buffer);
1383
@@ -XXX,XX +XXX,XX @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
1384
/* We have to read the whole VHDX_HEADER_SIZE instead of
1385
* sizeof(VHDXHeader), because the checksum is over the whole
1386
* region */
1387
- ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, buffer, VHDX_HEADER_SIZE,
1388
+ ret = bdrv_pread(bs->file, VHDX_HEADER1_OFFSET, VHDX_HEADER_SIZE, buffer,
1389
0);
1390
if (ret < 0) {
1391
goto fail;
1392
@@ -XXX,XX +XXX,XX @@ static void vhdx_parse_header(BlockDriverState *bs, BDRVVHDXState *s,
1393
}
1394
}
1395
1396
- ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, buffer, VHDX_HEADER_SIZE,
1397
+ ret = bdrv_pread(bs->file, VHDX_HEADER2_OFFSET, VHDX_HEADER_SIZE, buffer,
1398
0);
1399
if (ret < 0) {
1400
goto fail;
1401
@@ -XXX,XX +XXX,XX @@ static int vhdx_open_region_tables(BlockDriverState *bs, BDRVVHDXState *s)
1402
* whole block */
1403
buffer = qemu_blockalign(bs, VHDX_HEADER_BLOCK_SIZE);
1404
1405
- ret = bdrv_pread(bs->file, VHDX_REGION_TABLE_OFFSET, buffer,
1406
- VHDX_HEADER_BLOCK_SIZE, 0);
1407
+ ret = bdrv_pread(bs->file, VHDX_REGION_TABLE_OFFSET,
1408
+ VHDX_HEADER_BLOCK_SIZE, buffer, 0);
1409
if (ret < 0) {
1410
goto fail;
1411
}
1412
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1413
1414
buffer = qemu_blockalign(bs, VHDX_METADATA_TABLE_MAX_SIZE);
1415
1416
- ret = bdrv_pread(bs->file, s->metadata_rt.file_offset, buffer,
1417
- VHDX_METADATA_TABLE_MAX_SIZE, 0);
1418
+ ret = bdrv_pread(bs->file, s->metadata_rt.file_offset,
1419
+ VHDX_METADATA_TABLE_MAX_SIZE, buffer, 0);
1420
if (ret < 0) {
1421
goto exit;
1422
}
1423
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1424
ret = bdrv_pread(bs->file,
1425
s->metadata_entries.file_parameters_entry.offset
1426
+ s->metadata_rt.file_offset,
1427
- &s->params,
1428
sizeof(s->params),
1429
+ &s->params,
1430
0);
1431
1432
if (ret < 0) {
1433
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1434
ret = bdrv_pread(bs->file,
1435
s->metadata_entries.virtual_disk_size_entry.offset
1436
+ s->metadata_rt.file_offset,
1437
- &s->virtual_disk_size,
1438
sizeof(uint64_t),
1439
+ &s->virtual_disk_size,
1440
0);
1441
if (ret < 0) {
1442
goto exit;
1443
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1444
ret = bdrv_pread(bs->file,
1445
s->metadata_entries.logical_sector_size_entry.offset
1446
+ s->metadata_rt.file_offset,
1447
- &s->logical_sector_size,
1448
sizeof(uint32_t),
1449
+ &s->logical_sector_size,
1450
0);
1451
if (ret < 0) {
1452
goto exit;
1453
@@ -XXX,XX +XXX,XX @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
1454
ret = bdrv_pread(bs->file,
1455
s->metadata_entries.phys_sector_size_entry.offset
1456
+ s->metadata_rt.file_offset,
1457
- &s->physical_sector_size,
1458
sizeof(uint32_t),
1459
+ &s->physical_sector_size,
1460
0);
1461
if (ret < 0) {
1462
goto exit;
1463
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
1464
QLIST_INIT(&s->regions);
1465
1466
/* validate the file signature */
1467
- ret = bdrv_pread(bs->file, 0, &signature, sizeof(uint64_t), 0);
1468
+ ret = bdrv_pread(bs->file, 0, sizeof(uint64_t), &signature, 0);
1469
if (ret < 0) {
1470
goto fail;
1471
}
1472
@@ -XXX,XX +XXX,XX @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
1473
goto fail;
1474
}
1475
1476
- ret = bdrv_pread(bs->file, s->bat_offset, s->bat, s->bat_rt.length, 0);
1477
+ ret = bdrv_pread(bs->file, s->bat_offset, s->bat_rt.length, s->bat, 0);
1478
if (ret < 0) {
1479
goto fail;
1480
}
1481
diff --git a/block/vmdk.c b/block/vmdk.c
1482
index XXXXXXX..XXXXXXX 100644
1483
--- a/block/vmdk.c
1484
+++ b/block/vmdk.c
1485
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_cid(BlockDriverState *bs, int parent, uint32_t *pcid)
1486
int ret;
1487
1488
desc = g_malloc0(DESC_SIZE);
1489
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1490
+ ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
1491
if (ret < 0) {
1492
goto out;
1493
}
1494
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
1495
1496
desc = g_malloc0(DESC_SIZE);
1497
tmp_desc = g_malloc0(DESC_SIZE);
1498
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1499
+ ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
1500
if (ret < 0) {
1501
goto out;
1502
}
1503
@@ -XXX,XX +XXX,XX @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
1504
pstrcat(desc, DESC_SIZE, tmp_desc);
1505
}
1506
1507
- ret = bdrv_pwrite_sync(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1508
+ ret = bdrv_pwrite_sync(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
1509
1510
out:
1511
g_free(desc);
1512
@@ -XXX,XX +XXX,XX @@ static int vmdk_parent_open(BlockDriverState *bs)
1513
int ret;
1514
1515
desc = g_malloc0(DESC_SIZE + 1);
1516
- ret = bdrv_pread(bs->file, s->desc_offset, desc, DESC_SIZE, 0);
1517
+ ret = bdrv_pread(bs->file, s->desc_offset, DESC_SIZE, desc, 0);
1518
if (ret < 0) {
1519
goto out;
1520
}
1521
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
1522
return -ENOMEM;
1523
}
1524
1525
- ret = bdrv_pread(extent->file, extent->l1_table_offset, extent->l1_table,
1526
- l1_size, 0);
1527
+ ret = bdrv_pread(extent->file, extent->l1_table_offset, l1_size,
1528
+ extent->l1_table, 0);
1529
if (ret < 0) {
1530
bdrv_refresh_filename(extent->file->bs);
1531
error_setg_errno(errp, -ret,
1532
@@ -XXX,XX +XXX,XX @@ static int vmdk_init_tables(BlockDriverState *bs, VmdkExtent *extent,
1533
goto fail_l1;
1534
}
1535
ret = bdrv_pread(extent->file, extent->l1_backup_table_offset,
1536
- extent->l1_backup_table, l1_size, 0);
1537
+ l1_size, extent->l1_backup_table, 0);
1538
if (ret < 0) {
1539
bdrv_refresh_filename(extent->file->bs);
1540
error_setg_errno(errp, -ret,
1541
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmfs_sparse(BlockDriverState *bs,
1542
VMDK3Header header;
1543
VmdkExtent *extent = NULL;
1544
1545
- ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header), 0);
1546
+ ret = bdrv_pread(file, sizeof(magic), sizeof(header), &header, 0);
1547
if (ret < 0) {
1548
bdrv_refresh_filename(file->bs);
1549
error_setg_errno(errp, -ret,
1550
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_se_sparse(BlockDriverState *bs,
1551
1552
assert(sizeof(const_header) == SECTOR_SIZE);
1553
1554
- ret = bdrv_pread(file, 0, &const_header, sizeof(const_header), 0);
1555
+ ret = bdrv_pread(file, 0, sizeof(const_header), &const_header, 0);
1556
if (ret < 0) {
1557
bdrv_refresh_filename(file->bs);
1558
error_setg_errno(errp, -ret,
1559
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_se_sparse(BlockDriverState *bs,
1560
assert(sizeof(volatile_header) == SECTOR_SIZE);
1561
1562
ret = bdrv_pread(file, const_header.volatile_header_offset * SECTOR_SIZE,
1563
- &volatile_header, sizeof(volatile_header), 0);
1564
+ sizeof(volatile_header), &volatile_header, 0);
1565
if (ret < 0) {
1566
bdrv_refresh_filename(file->bs);
1567
error_setg_errno(errp, -ret,
1568
@@ -XXX,XX +XXX,XX @@ static char *vmdk_read_desc(BdrvChild *file, uint64_t desc_offset, Error **errp)
1569
size = MIN(size, (1 << 20) - 1); /* avoid unbounded allocation */
1570
buf = g_malloc(size + 1);
1571
1572
- ret = bdrv_pread(file, desc_offset, buf, size, 0);
1573
+ ret = bdrv_pread(file, desc_offset, size, buf, 0);
1574
if (ret < 0) {
1575
error_setg_errno(errp, -ret, "Could not read from file");
1576
g_free(buf);
1577
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
1578
int64_t l1_backup_offset = 0;
1579
bool compressed;
1580
1581
- ret = bdrv_pread(file, sizeof(magic), &header, sizeof(header), 0);
1582
+ ret = bdrv_pread(file, sizeof(magic), sizeof(header), &header, 0);
1583
if (ret < 0) {
1584
bdrv_refresh_filename(file->bs);
1585
error_setg_errno(errp, -ret,
1586
@@ -XXX,XX +XXX,XX @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
1587
} QEMU_PACKED footer;
1588
1589
ret = bdrv_pread(file, bs->file->bs->total_sectors * 512 - 1536,
1590
- &footer, sizeof(footer), 0);
1591
+ sizeof(footer), &footer, 0);
1592
if (ret < 0) {
1593
error_setg_errno(errp, -ret, "Failed to read footer");
1594
return ret;
1595
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1596
if (copy_from_backing) {
1597
/* qcow2 emits this on bs->file instead of bs->backing */
1598
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
1599
- ret = bdrv_pread(bs->backing, offset, whole_grain,
1600
- skip_start_bytes, 0);
1601
+ ret = bdrv_pread(bs->backing, offset, skip_start_bytes,
1602
+ whole_grain, 0);
1603
if (ret < 0) {
1604
ret = VMDK_ERROR;
1605
goto exit;
1606
}
1607
}
1608
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
1609
- ret = bdrv_pwrite(extent->file, cluster_offset, whole_grain,
1610
- skip_start_bytes, 0);
1611
+ ret = bdrv_pwrite(extent->file, cluster_offset, skip_start_bytes,
1612
+ whole_grain, 0);
1613
if (ret < 0) {
1614
ret = VMDK_ERROR;
1615
goto exit;
1616
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1617
/* qcow2 emits this on bs->file instead of bs->backing */
1618
BLKDBG_EVENT(extent->file, BLKDBG_COW_READ);
1619
ret = bdrv_pread(bs->backing, offset + skip_end_bytes,
1620
- whole_grain + skip_end_bytes,
1621
- cluster_bytes - skip_end_bytes, 0);
1622
+ cluster_bytes - skip_end_bytes,
1623
+ whole_grain + skip_end_bytes, 0);
1624
if (ret < 0) {
1625
ret = VMDK_ERROR;
1626
goto exit;
1627
@@ -XXX,XX +XXX,XX @@ static int get_whole_cluster(BlockDriverState *bs,
1628
}
1629
BLKDBG_EVENT(extent->file, BLKDBG_COW_WRITE);
1630
ret = bdrv_pwrite(extent->file, cluster_offset + skip_end_bytes,
1631
- whole_grain + skip_end_bytes,
1632
- cluster_bytes - skip_end_bytes, 0);
1633
+ cluster_bytes - skip_end_bytes,
1634
+ whole_grain + skip_end_bytes, 0);
1635
if (ret < 0) {
1636
ret = VMDK_ERROR;
1637
goto exit;
1638
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
1639
if (bdrv_pwrite(extent->file,
1640
((int64_t)m_data->l2_offset * 512)
1641
+ (m_data->l2_index * sizeof(offset)),
1642
- &offset, sizeof(offset), 0) < 0) {
1643
+ sizeof(offset), &offset, 0) < 0) {
1644
return VMDK_ERROR;
1645
}
1646
/* update backup L2 table */
1647
@@ -XXX,XX +XXX,XX @@ static int vmdk_L2update(VmdkExtent *extent, VmdkMetaData *m_data,
1648
if (bdrv_pwrite(extent->file,
1649
((int64_t)m_data->l2_offset * 512)
1650
+ (m_data->l2_index * sizeof(offset)),
1651
- &offset, sizeof(offset), 0) < 0) {
1652
+ sizeof(offset), &offset, 0) < 0) {
1653
return VMDK_ERROR;
1654
}
1655
}
1656
@@ -XXX,XX +XXX,XX @@ static int get_cluster_offset(BlockDriverState *bs,
1657
BLKDBG_EVENT(extent->file, BLKDBG_L2_LOAD);
1658
if (bdrv_pread(extent->file,
1659
(int64_t)l2_offset * 512,
1660
- l2_table,
1661
l2_size_bytes,
1662
+ l2_table,
1663
0
1664
) != l2_size_bytes) {
1665
return VMDK_ERROR;
1666
@@ -XXX,XX +XXX,XX @@ static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset,
1667
cluster_buf = g_malloc(buf_bytes);
1668
uncomp_buf = g_malloc(cluster_bytes);
1669
BLKDBG_EVENT(extent->file, BLKDBG_READ_COMPRESSED);
1670
- ret = bdrv_pread(extent->file, cluster_offset, cluster_buf, buf_bytes, 0);
1671
+ ret = bdrv_pread(extent->file, cluster_offset, buf_bytes, cluster_buf, 0);
1672
if (ret < 0) {
1673
goto out;
1674
}
1675
diff --git a/block/vpc.c b/block/vpc.c
1676
index XXXXXXX..XXXXXXX 100644
1677
--- a/block/vpc.c
1678
+++ b/block/vpc.c
1679
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1680
goto fail;
1681
}
1682
1683
- ret = bdrv_pread(bs->file, 0, &s->footer, sizeof(s->footer), 0);
1684
+ ret = bdrv_pread(bs->file, 0, sizeof(s->footer), &s->footer, 0);
1685
if (ret < 0) {
1686
error_setg(errp, "Unable to read VHD header");
1687
goto fail;
1688
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1689
}
1690
1691
/* If a fixed disk, the footer is found only at the end of the file */
1692
- ret = bdrv_pread(bs->file, offset - sizeof(*footer), footer,
1693
- sizeof(*footer), 0);
1694
+ ret = bdrv_pread(bs->file, offset - sizeof(*footer), sizeof(*footer),
1695
+ footer, 0);
1696
if (ret < 0) {
1697
goto fail;
1698
}
1699
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1700
1701
if (disk_type == VHD_DYNAMIC) {
1702
ret = bdrv_pread(bs->file, be64_to_cpu(footer->data_offset),
1703
- &dyndisk_header, sizeof(dyndisk_header), 0);
1704
+ sizeof(dyndisk_header), &dyndisk_header, 0);
1705
if (ret < 0) {
1706
error_setg(errp, "Error reading dynamic VHD header");
1707
goto fail;
1708
@@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
1709
1710
s->bat_offset = be64_to_cpu(dyndisk_header.table_offset);
1711
1712
- ret = bdrv_pread(bs->file, s->bat_offset, s->pagetable,
1713
- pagetable_size, 0);
1714
+ ret = bdrv_pread(bs->file, s->bat_offset, pagetable_size,
1715
+ s->pagetable, 0);
1716
if (ret < 0) {
1717
error_setg(errp, "Error reading pagetable");
1718
goto fail;
1719
@@ -XXX,XX +XXX,XX @@ static inline int64_t get_image_offset(BlockDriverState *bs, uint64_t offset,
1720
1721
s->last_bitmap_offset = bitmap_offset;
1722
memset(bitmap, 0xff, s->bitmap_size);
1723
- r = bdrv_pwrite_sync(bs->file, bitmap_offset, bitmap, s->bitmap_size,
1724
+ r = bdrv_pwrite_sync(bs->file, bitmap_offset, s->bitmap_size, bitmap,
1725
0);
1726
if (r < 0) {
1727
*err = r;
1728
@@ -XXX,XX +XXX,XX @@ static int rewrite_footer(BlockDriverState *bs)
1729
BDRVVPCState *s = bs->opaque;
1730
int64_t offset = s->free_data_block_offset;
1731
1732
- ret = bdrv_pwrite_sync(bs->file, offset, &s->footer, sizeof(s->footer), 0);
1733
+ ret = bdrv_pwrite_sync(bs->file, offset, sizeof(s->footer), &s->footer, 0);
1734
if (ret < 0)
1735
return ret;
1736
1737
@@ -XXX,XX +XXX,XX @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset)
1738
1739
/* Initialize the block's bitmap */
1740
memset(bitmap, 0xff, s->bitmap_size);
1741
- ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
1742
- s->bitmap_size, 0);
1743
+ ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset,
1744
+ s->bitmap_size, bitmap, 0);
1745
if (ret < 0) {
1746
return ret;
1747
}
1748
@@ -XXX,XX +XXX,XX @@ static int64_t alloc_block(BlockDriverState *bs, int64_t offset)
1749
/* Write BAT entry to disk */
1750
bat_offset = s->bat_offset + (4 * index);
1751
bat_value = cpu_to_be32(s->pagetable[index]);
1752
- ret = bdrv_pwrite_sync(bs->file, bat_offset, &bat_value, 4, 0);
1753
+ ret = bdrv_pwrite_sync(bs->file, bat_offset, 4, &bat_value, 0);
1754
if (ret < 0)
1755
goto fail;
1756
1757
diff --git a/block/vvfat.c b/block/vvfat.c
1758
index XXXXXXX..XXXXXXX 100644
1759
--- a/block/vvfat.c
1760
+++ b/block/vvfat.c
1761
@@ -XXX,XX +XXX,XX @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
1762
DLOG(fprintf(stderr, "sectors %" PRId64 "+%" PRId64
1763
" allocated\n", sector_num,
1764
n >> BDRV_SECTOR_BITS));
1765
- if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE,
1766
- buf + i * 0x200, n, 0) < 0) {
1767
+ if (bdrv_pread(s->qcow, sector_num * BDRV_SECTOR_SIZE, n,
1768
+ buf + i * 0x200, 0) < 0) {
1769
return -1;
1770
}
1771
i += (n >> BDRV_SECTOR_BITS) - 1;
1772
@@ -XXX,XX +XXX,XX @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
1773
return -1;
1774
}
1775
res = bdrv_pwrite(s->qcow, offset * BDRV_SECTOR_SIZE,
1776
- s->cluster_buffer, BDRV_SECTOR_SIZE,
1777
+ BDRV_SECTOR_SIZE, s->cluster_buffer,
1778
0);
1779
if (res < 0) {
1780
return -2;
1781
@@ -XXX,XX +XXX,XX @@ DLOG(checkpoint());
1782
* Use qcow backend. Commit later.
1783
*/
1784
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
1785
- ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE, buf,
1786
- nb_sectors * BDRV_SECTOR_SIZE, 0);
1787
+ ret = bdrv_pwrite(s->qcow, sector_num * BDRV_SECTOR_SIZE,
1788
+ nb_sectors * BDRV_SECTOR_SIZE, buf, 0);
1789
if (ret < 0) {
1790
fprintf(stderr, "Error writing to qcow backend\n");
1791
return ret;
1792
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
1793
index XXXXXXX..XXXXXXX 100644
1794
--- a/tests/unit/test-block-iothread.c
1795
+++ b/tests/unit/test-block-iothread.c
1796
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pread(BdrvChild *c)
1797
int ret;
1798
1799
/* Success */
1800
- ret = bdrv_pread(c, 0, buf, sizeof(buf), 0);
1801
+ ret = bdrv_pread(c, 0, sizeof(buf), buf, 0);
1802
g_assert_cmpint(ret, ==, 512);
1803
1804
/* Early error: Negative offset */
1805
- ret = bdrv_pread(c, -2, buf, sizeof(buf), 0);
1806
+ ret = bdrv_pread(c, -2, sizeof(buf), buf, 0);
1807
g_assert_cmpint(ret, ==, -EIO);
1808
}
157
}
1809
158
1810
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_pwrite(BdrvChild *c)
159
-void coroutine_fn qemu_co_queue_wait(CoQueue *queue)
1811
int ret;
160
+void coroutine_fn qemu_co_queue_wait(CoQueue *queue, CoMutex *mutex)
1812
161
{
1813
/* Success */
162
Coroutine *self = qemu_coroutine_self();
1814
- ret = bdrv_pwrite(c, 0, buf, sizeof(buf), 0);
163
QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next);
1815
+ ret = bdrv_pwrite(c, 0, sizeof(buf), buf, 0);
164
+
1816
g_assert_cmpint(ret, ==, 512);
165
+ if (mutex) {
1817
166
+ qemu_co_mutex_unlock(mutex);
1818
/* Early error: Negative offset */
167
+ }
1819
- ret = bdrv_pwrite(c, -2, buf, sizeof(buf), 0);
168
+
1820
+ ret = bdrv_pwrite(c, -2, sizeof(buf), buf, 0);
169
+ /* There is no race condition here. Other threads will call
1821
g_assert_cmpint(ret, ==, -EIO);
170
+ * aio_co_schedule on our AioContext, which can reenter this
171
+ * coroutine but only after this yield and after the main loop
172
+ * has gone through the next iteration.
173
+ */
174
qemu_coroutine_yield();
175
assert(qemu_in_coroutine());
176
+
177
+ /* TODO: OSv implements wait morphing here, where the wakeup
178
+ * primitive automatically places the woken coroutine on the
179
+ * mutex's queue. This avoids the thundering herd effect.
180
+ */
181
+ if (mutex) {
182
+ qemu_co_mutex_lock(mutex);
183
+ }
1822
}
184
}
1823
185
186
/**
187
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_rdlock(CoRwlock *lock)
188
Coroutine *self = qemu_coroutine_self();
189
190
while (lock->writer) {
191
- qemu_co_queue_wait(&lock->queue);
192
+ qemu_co_queue_wait(&lock->queue, NULL);
193
}
194
lock->reader++;
195
self->locks_held++;
196
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_wrlock(CoRwlock *lock)
197
Coroutine *self = qemu_coroutine_self();
198
199
while (lock->writer || lock->reader) {
200
- qemu_co_queue_wait(&lock->queue);
201
+ qemu_co_queue_wait(&lock->queue, NULL);
202
}
203
lock->writer = true;
204
self->locks_held++;
1824
--
205
--
1825
2.35.3
206
2.9.3
207
208
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
It does not mutate the buffer.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-Id: <20220609152744.3891847-6-afaria@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
include/block/block_int-io.h | 2 +-
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
15
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/block/block_int-io.h
18
+++ b/include/block/block_int-io.h
19
@@ -XXX,XX +XXX,XX @@ static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
20
}
21
22
static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
23
- int64_t offset, unsigned int bytes, void *buf, BdrvRequestFlags flags)
24
+ int64_t offset, unsigned int bytes, const void *buf, BdrvRequestFlags flags)
25
{
26
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
27
IO_CODE();
28
--
29
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
For consistency with other I/O functions, and in preparation to
4
implement bdrv_{pread,pwrite}() using generated_co_wrapper.
5
6
unsigned int fits in int64_t, so all callers remain correct.
7
8
bdrv_check_request32() is called further down the stack and causes -EIO
9
to be returned if 'bytes' is negative or greater than
10
BDRV_REQUEST_MAX_BYTES, which in turns never exceeds SIZE_MAX.
11
12
Signed-off-by: Alberto Faria <afaria@redhat.com>
13
Message-Id: <20220609152744.3891847-7-afaria@redhat.com>
14
Reviewed-by: Eric Blake <eblake@redhat.com>
15
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
16
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
17
---
18
block/coroutines.h | 4 ++--
19
include/block/block_int-io.h | 4 ++--
20
2 files changed, 4 insertions(+), 4 deletions(-)
21
22
diff --git a/block/coroutines.h b/block/coroutines.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/block/coroutines.h
25
+++ b/block/coroutines.h
26
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_do_flush(BlockBackend *blk);
27
*/
28
29
int generated_co_wrapper
30
-bdrv_preadv(BdrvChild *child, int64_t offset, unsigned int bytes,
31
+bdrv_preadv(BdrvChild *child, int64_t offset, int64_t bytes,
32
QEMUIOVector *qiov, BdrvRequestFlags flags);
33
34
int generated_co_wrapper
35
-bdrv_pwritev(BdrvChild *child, int64_t offset, unsigned int bytes,
36
+bdrv_pwritev(BdrvChild *child, int64_t offset, int64_t bytes,
37
QEMUIOVector *qiov, BdrvRequestFlags flags);
38
39
int generated_co_wrapper
40
diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h
41
index XXXXXXX..XXXXXXX 100644
42
--- a/include/block/block_int-io.h
43
+++ b/include/block/block_int-io.h
44
@@ -XXX,XX +XXX,XX @@ int coroutine_fn bdrv_co_pwritev_part(BdrvChild *child,
45
QEMUIOVector *qiov, size_t qiov_offset, BdrvRequestFlags flags);
46
47
static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
48
- int64_t offset, unsigned int bytes, void *buf, BdrvRequestFlags flags)
49
+ int64_t offset, int64_t bytes, void *buf, BdrvRequestFlags flags)
50
{
51
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
52
IO_CODE();
53
@@ -XXX,XX +XXX,XX @@ static inline int coroutine_fn bdrv_co_pread(BdrvChild *child,
54
}
55
56
static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child,
57
- int64_t offset, unsigned int bytes, const void *buf, BdrvRequestFlags flags)
58
+ int64_t offset, int64_t bytes, const void *buf, BdrvRequestFlags flags)
59
{
60
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
61
IO_CODE();
62
--
63
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
Convert uses of bdrv_pwrite_sync() into bdrv_co_pwrite_sync() when the
4
callers are already coroutine_fn.
5
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Vladimir Sementsov-Ogievskiy <v.sementsov-og@mail.ru>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-Id: <20220609152744.3891847-10-afaria@redhat.com>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/parallels.c | 2 +-
14
block/qcow2-snapshot.c | 6 +++---
15
block/qcow2.c | 4 ++--
16
3 files changed, 6 insertions(+), 6 deletions(-)
17
18
diff --git a/block/parallels.c b/block/parallels.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/block/parallels.c
21
+++ b/block/parallels.c
22
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn parallels_co_check(BlockDriverState *bs,
23
24
ret = 0;
25
if (flush_bat) {
26
- ret = bdrv_pwrite_sync(bs->file, 0, s->header_size, s->header, 0);
27
+ ret = bdrv_co_pwrite_sync(bs->file, 0, s->header_size, s->header, 0);
28
if (ret < 0) {
29
res->check_errors++;
30
goto out;
31
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/block/qcow2-snapshot.c
34
+++ b/block/qcow2-snapshot.c
35
@@ -XXX,XX +XXX,XX @@ int coroutine_fn qcow2_check_read_snapshot_table(BlockDriverState *bs,
36
assert(fix & BDRV_FIX_ERRORS);
37
38
snapshot_table_pointer.nb_snapshots = cpu_to_be32(s->nb_snapshots);
39
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
40
- sizeof(snapshot_table_pointer.nb_snapshots),
41
- &snapshot_table_pointer.nb_snapshots, 0);
42
+ ret = bdrv_co_pwrite_sync(bs->file, offsetof(QCowHeader, nb_snapshots),
43
+ sizeof(snapshot_table_pointer.nb_snapshots),
44
+ &snapshot_table_pointer.nb_snapshots, 0);
45
if (ret < 0) {
46
result->check_errors++;
47
fprintf(stderr, "ERROR failed to update the snapshot count in the "
48
diff --git a/block/qcow2.c b/block/qcow2.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/qcow2.c
51
+++ b/block/qcow2.c
52
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow2_co_truncate(BlockDriverState *bs, int64_t offset,
53
54
/* write updated header.size */
55
offset = cpu_to_be64(offset);
56
- ret = bdrv_pwrite_sync(bs->file, offsetof(QCowHeader, size),
57
- sizeof(offset), &offset, 0);
58
+ ret = bdrv_co_pwrite_sync(bs->file, offsetof(QCowHeader, size),
59
+ sizeof(offset), &offset, 0);
60
if (ret < 0) {
61
error_setg_errno(errp, -ret, "Failed to update the image size");
62
goto fail;
63
--
64
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
Use bdrv_pwrite_sync() instead of calling bdrv_pwrite() and bdrv_flush()
4
separately.
5
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Eric Blake <eblake@redhat.com>
8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Message-Id: <20220609152744.3891847-11-afaria@redhat.com>
10
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
12
---
13
block/qcow2.c | 9 +++------
14
1 file changed, 3 insertions(+), 6 deletions(-)
15
16
diff --git a/block/qcow2.c b/block/qcow2.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/block/qcow2.c
19
+++ b/block/qcow2.c
20
@@ -XXX,XX +XXX,XX @@ int qcow2_mark_dirty(BlockDriverState *bs)
21
}
22
23
val = cpu_to_be64(s->incompatible_features | QCOW2_INCOMPAT_DIRTY);
24
- ret = bdrv_pwrite(bs->file, offsetof(QCowHeader, incompatible_features),
25
- sizeof(val), &val, 0);
26
- if (ret < 0) {
27
- return ret;
28
- }
29
- ret = bdrv_flush(bs->file->bs);
30
+ ret = bdrv_pwrite_sync(bs->file,
31
+ offsetof(QCowHeader, incompatible_features),
32
+ sizeof(val), &val, 0);
33
if (ret < 0) {
34
return ret;
35
}
36
--
37
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: John Snow <jsnow@redhat.com>
2
1
3
In certain container environments we may not have FUSE at all, so skip
4
the test in this circumstance too.
5
6
Signed-off-by: John Snow <jsnow@redhat.com>
7
Message-Id: <20220616142659.3184115-3-jsnow@redhat.com>
8
Reviewed-by: Thomas Huth <thuth@redhat.com>
9
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
10
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
11
---
12
tests/qemu-iotests/108 | 5 +++++
13
1 file changed, 5 insertions(+)
14
15
diff --git a/tests/qemu-iotests/108 b/tests/qemu-iotests/108
16
index XXXXXXX..XXXXXXX 100755
17
--- a/tests/qemu-iotests/108
18
+++ b/tests/qemu-iotests/108
19
@@ -XXX,XX +XXX,XX @@ if sudo -n losetup &>/dev/null; then
20
else
21
loopdev=false
22
23
+ # Check for usable FUSE in the host environment:
24
+ if test ! -c "/dev/fuse"; then
25
+ _notrun 'No passwordless sudo nor usable /dev/fuse'
26
+ fi
27
+
28
# QSD --export fuse will either yield "Parameter 'id' is missing"
29
# or "Invalid parameter 'fuse'", depending on whether there is
30
# FUSE support or not.
31
--
32
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
They currently return the value of their 'bytes' parameter on success.
4
5
Make them return 0 instead, for consistency with other I/O functions and
6
in preparation to implement them using generated_co_wrapper. This also
7
makes it clear that short reads/writes are not possible.
8
9
Signed-off-by: Alberto Faria <afaria@redhat.com>
10
Message-Id: <20220705161527.1054072-2-afaria@redhat.com>
11
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
12
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
13
---
14
block.c | 8 +++++---
15
block/block-backend.c | 7 ++-----
16
block/qcow.c | 6 +++---
17
hw/block/m25p80.c | 2 +-
18
hw/misc/mac_via.c | 4 ++--
19
hw/misc/sifive_u_otp.c | 2 +-
20
hw/nvram/eeprom_at24c.c | 8 ++++----
21
hw/nvram/spapr_nvram.c | 14 +++++++-------
22
hw/ppc/pnv_pnor.c | 2 +-
23
qemu-img.c | 25 +++++++++----------------
24
qemu-io-cmds.c | 18 ++++++++++++------
25
tests/unit/test-block-iothread.c | 4 ++--
26
12 files changed, 49 insertions(+), 51 deletions(-)
27
28
diff --git a/block.c b/block.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/block.c
31
+++ b/block.c
32
@@ -XXX,XX +XXX,XX @@ static int find_image_format(BlockBackend *file, const char *filename,
33
return ret;
34
}
35
36
- drv = bdrv_probe_all(buf, ret, filename);
37
+ drv = bdrv_probe_all(buf, sizeof(buf), filename);
38
if (!drv) {
39
error_setg(errp, "Could not determine image format: No compatible "
40
"driver found");
41
- ret = -ENOENT;
42
+ *pdrv = NULL;
43
+ return -ENOENT;
44
}
45
+
46
*pdrv = drv;
47
- return ret;
48
+ return 0;
49
}
50
51
/**
52
diff --git a/block/block-backend.c b/block/block-backend.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/block/block-backend.c
55
+++ b/block/block-backend.c
56
@@ -XXX,XX +XXX,XX @@ int blk_pread(BlockBackend *blk, int64_t offset, void *buf, int bytes)
57
ret = blk_do_preadv(blk, offset, bytes, &qiov, 0);
58
blk_dec_in_flight(blk);
59
60
- return ret < 0 ? ret : bytes;
61
+ return ret;
62
}
63
64
int blk_pwrite(BlockBackend *blk, int64_t offset, const void *buf, int bytes,
65
BdrvRequestFlags flags)
66
{
67
- int ret;
68
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
69
IO_OR_GS_CODE();
70
71
- ret = blk_pwritev_part(blk, offset, bytes, &qiov, 0, flags);
72
-
73
- return ret < 0 ? ret : bytes;
74
+ return blk_pwritev_part(blk, offset, bytes, &qiov, 0, flags);
75
}
76
77
int64_t blk_getlength(BlockBackend *blk)
78
diff --git a/block/qcow.c b/block/qcow.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/block/qcow.c
81
+++ b/block/qcow.c
82
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
83
84
/* write all the data */
85
ret = blk_pwrite(qcow_blk, 0, &header, sizeof(header), 0);
86
- if (ret != sizeof(header)) {
87
+ if (ret < 0) {
88
goto exit;
89
}
90
91
if (qcow_opts->has_backing_file) {
92
ret = blk_pwrite(qcow_blk, sizeof(header),
93
qcow_opts->backing_file, backing_filename_len, 0);
94
- if (ret != backing_filename_len) {
95
+ if (ret < 0) {
96
goto exit;
97
}
98
}
99
@@ -XXX,XX +XXX,XX @@ static int coroutine_fn qcow_co_create(BlockdevCreateOptions *opts,
100
i++) {
101
ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
102
tmp, BDRV_SECTOR_SIZE, 0);
103
- if (ret != BDRV_SECTOR_SIZE) {
104
+ if (ret < 0) {
105
g_free(tmp);
106
goto exit;
107
}
108
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
109
index XXXXXXX..XXXXXXX 100644
110
--- a/hw/block/m25p80.c
111
+++ b/hw/block/m25p80.c
112
@@ -XXX,XX +XXX,XX @@ static void m25p80_realize(SSIPeripheral *ss, Error **errp)
113
trace_m25p80_binding(s);
114
s->storage = blk_blockalign(s->blk, s->size);
115
116
- if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
117
+ if (blk_pread(s->blk, 0, s->storage, s->size) < 0) {
118
error_setg(errp, "failed to read the initial flash content");
119
return;
120
}
121
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/misc/mac_via.c
124
+++ b/hw/misc/mac_via.c
125
@@ -XXX,XX +XXX,XX @@ static void mos6522_q800_via1_realize(DeviceState *dev, Error **errp)
126
return;
127
}
128
129
- len = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM));
130
- if (len != sizeof(v1s->PRAM)) {
131
+ ret = blk_pread(v1s->blk, 0, v1s->PRAM, sizeof(v1s->PRAM));
132
+ if (ret < 0) {
133
error_setg(errp, "can't read PRAM contents");
134
return;
135
}
136
diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/hw/misc/sifive_u_otp.c
139
+++ b/hw/misc/sifive_u_otp.c
140
@@ -XXX,XX +XXX,XX @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
141
return;
142
}
143
144
- if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
145
+ if (blk_pread(s->blk, 0, s->fuse, filesize) < 0) {
146
error_setg(errp, "failed to read the initial flash content");
147
return;
148
}
149
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
150
index XXXXXXX..XXXXXXX 100644
151
--- a/hw/nvram/eeprom_at24c.c
152
+++ b/hw/nvram/eeprom_at24c.c
153
@@ -XXX,XX +XXX,XX @@ int at24c_eeprom_event(I2CSlave *s, enum i2c_event event)
154
case I2C_START_RECV:
155
DPRINTK("clear\n");
156
if (ee->blk && ee->changed) {
157
- int len = blk_pwrite(ee->blk, 0, ee->mem, ee->rsize, 0);
158
- if (len != ee->rsize) {
159
+ int ret = blk_pwrite(ee->blk, 0, ee->mem, ee->rsize, 0);
160
+ if (ret < 0) {
161
ERR(TYPE_AT24C_EE
162
" : failed to write backing file\n");
163
}
164
@@ -XXX,XX +XXX,XX @@ void at24c_eeprom_reset(DeviceState *state)
165
memset(ee->mem, 0, ee->rsize);
166
167
if (ee->blk) {
168
- int len = blk_pread(ee->blk, 0, ee->mem, ee->rsize);
169
+ int ret = blk_pread(ee->blk, 0, ee->mem, ee->rsize);
170
171
- if (len != ee->rsize) {
172
+ if (ret < 0) {
173
ERR(TYPE_AT24C_EE
174
" : Failed initial sync with backing file\n");
175
}
176
diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c
177
index XXXXXXX..XXXXXXX 100644
178
--- a/hw/nvram/spapr_nvram.c
179
+++ b/hw/nvram/spapr_nvram.c
180
@@ -XXX,XX +XXX,XX @@ static void rtas_nvram_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
181
{
182
SpaprNvram *nvram = spapr->nvram;
183
hwaddr offset, buffer, len;
184
- int alen;
185
+ int ret;
186
void *membuf;
187
188
if ((nargs != 3) || (nret != 2)) {
189
@@ -XXX,XX +XXX,XX @@ static void rtas_nvram_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
190
191
membuf = cpu_physical_memory_map(buffer, &len, false);
192
193
- alen = len;
194
+ ret = 0;
195
if (nvram->blk) {
196
- alen = blk_pwrite(nvram->blk, offset, membuf, len, 0);
197
+ ret = blk_pwrite(nvram->blk, offset, membuf, len, 0);
198
}
199
200
assert(nvram->buf);
201
@@ -XXX,XX +XXX,XX @@ static void rtas_nvram_store(PowerPCCPU *cpu, SpaprMachineState *spapr,
202
203
cpu_physical_memory_unmap(membuf, len, 0, len);
204
205
- rtas_st(rets, 0, (alen < len) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS);
206
- rtas_st(rets, 1, (alen < 0) ? 0 : alen);
207
+ rtas_st(rets, 0, (ret < 0) ? RTAS_OUT_HW_ERROR : RTAS_OUT_SUCCESS);
208
+ rtas_st(rets, 1, (ret < 0) ? 0 : len);
209
}
210
211
static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
212
@@ -XXX,XX +XXX,XX @@ static void spapr_nvram_realize(SpaprVioDevice *dev, Error **errp)
213
}
214
215
if (nvram->blk) {
216
- int alen = blk_pread(nvram->blk, 0, nvram->buf, nvram->size);
217
+ ret = blk_pread(nvram->blk, 0, nvram->buf, nvram->size);
218
219
- if (alen != nvram->size) {
220
+ if (ret < 0) {
221
error_setg(errp, "can't read spapr-nvram contents");
222
return;
223
}
224
diff --git a/hw/ppc/pnv_pnor.c b/hw/ppc/pnv_pnor.c
225
index XXXXXXX..XXXXXXX 100644
226
--- a/hw/ppc/pnv_pnor.c
227
+++ b/hw/ppc/pnv_pnor.c
228
@@ -XXX,XX +XXX,XX @@ static void pnv_pnor_realize(DeviceState *dev, Error **errp)
229
230
s->storage = blk_blockalign(s->blk, s->size);
231
232
- if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) {
233
+ if (blk_pread(s->blk, 0, s->storage, s->size) < 0) {
234
error_setg(errp, "failed to read the initial flash content");
235
return;
236
}
237
diff --git a/qemu-img.c b/qemu-img.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/qemu-img.c
240
+++ b/qemu-img.c
241
@@ -XXX,XX +XXX,XX @@ static int img_dd(int argc, char **argv)
242
in.buf = g_new(uint8_t, in.bsz);
243
244
for (out_pos = 0; in_pos < size; block_count++) {
245
- int in_ret, out_ret;
246
+ int bytes = (in_pos + in.bsz > size) ? size - in_pos : in.bsz;
247
248
- if (in_pos + in.bsz > size) {
249
- in_ret = blk_pread(blk1, in_pos, in.buf, size - in_pos);
250
- } else {
251
- in_ret = blk_pread(blk1, in_pos, in.buf, in.bsz);
252
- }
253
- if (in_ret < 0) {
254
+ ret = blk_pread(blk1, in_pos, in.buf, bytes);
255
+ if (ret < 0) {
256
error_report("error while reading from input image file: %s",
257
- strerror(-in_ret));
258
- ret = -1;
259
+ strerror(-ret));
260
goto out;
261
}
262
- in_pos += in_ret;
263
+ in_pos += bytes;
264
265
- out_ret = blk_pwrite(blk2, out_pos, in.buf, in_ret, 0);
266
-
267
- if (out_ret < 0) {
268
+ ret = blk_pwrite(blk2, out_pos, in.buf, bytes, 0);
269
+ if (ret < 0) {
270
error_report("error while writing to output image file: %s",
271
- strerror(-out_ret));
272
- ret = -1;
273
+ strerror(-ret));
274
goto out;
275
}
276
- out_pos += out_ret;
277
+ out_pos += bytes;
278
}
279
280
out:
281
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
282
index XXXXXXX..XXXXXXX 100644
283
--- a/qemu-io-cmds.c
284
+++ b/qemu-io-cmds.c
285
@@ -XXX,XX +XXX,XX @@ fail:
286
static int do_pread(BlockBackend *blk, char *buf, int64_t offset,
287
int64_t bytes, int64_t *total)
288
{
289
+ int ret;
290
+
291
if (bytes > INT_MAX) {
292
return -ERANGE;
293
}
294
295
- *total = blk_pread(blk, offset, (uint8_t *)buf, bytes);
296
- if (*total < 0) {
297
- return *total;
298
+ ret = blk_pread(blk, offset, (uint8_t *)buf, bytes);
299
+ if (ret < 0) {
300
+ return ret;
301
}
302
+ *total = bytes;
303
return 1;
304
}
305
306
static int do_pwrite(BlockBackend *blk, char *buf, int64_t offset,
307
int64_t bytes, int flags, int64_t *total)
308
{
309
+ int ret;
310
+
311
if (bytes > INT_MAX) {
312
return -ERANGE;
313
}
314
315
- *total = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
316
- if (*total < 0) {
317
- return *total;
318
+ ret = blk_pwrite(blk, offset, (uint8_t *)buf, bytes, flags);
319
+ if (ret < 0) {
320
+ return ret;
321
}
322
+ *total = bytes;
323
return 1;
324
}
325
326
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
327
index XXXXXXX..XXXXXXX 100644
328
--- a/tests/unit/test-block-iothread.c
329
+++ b/tests/unit/test-block-iothread.c
330
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pread(BlockBackend *blk)
331
332
/* Success */
333
ret = blk_pread(blk, 0, buf, sizeof(buf));
334
- g_assert_cmpint(ret, ==, 512);
335
+ g_assert_cmpint(ret, ==, 0);
336
337
/* Early error: Negative offset */
338
ret = blk_pread(blk, -2, buf, sizeof(buf));
339
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwrite(BlockBackend *blk)
340
341
/* Success */
342
ret = blk_pwrite(blk, 0, buf, sizeof(buf), 0);
343
- g_assert_cmpint(ret, ==, 512);
344
+ g_assert_cmpint(ret, ==, 0);
345
346
/* Early error: Negative offset */
347
ret = blk_pwrite(blk, -2, buf, sizeof(buf), 0);
348
--
349
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
It does not mutate the buffer.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220705161527.1054072-6-afaria@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/sysemu/block-backend-io.h | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/sysemu/block-backend-io.h
17
+++ b/include/sysemu/block-backend-io.h
18
@@ -XXX,XX +XXX,XX @@ static inline int coroutine_fn blk_co_pread(BlockBackend *blk, int64_t offset,
19
}
20
21
static inline int coroutine_fn blk_co_pwrite(BlockBackend *blk, int64_t offset,
22
- int64_t bytes, void *buf,
23
+ int64_t bytes, const void *buf,
24
BdrvRequestFlags flags)
25
{
26
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
27
--
28
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
We need to add include/sysemu/block-backend-io.h to the inputs of the
4
block-gen.c target defined in block/meson.build.
5
6
Signed-off-by: Alberto Faria <afaria@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220705161527.1054072-7-afaria@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
block/coroutines.h | 4 ----
12
include/sysemu/block-backend-io.h | 10 ++++++----
13
block/block-backend.c | 23 -----------------------
14
block/meson.build | 1 +
15
4 files changed, 7 insertions(+), 31 deletions(-)
16
17
diff --git a/block/coroutines.h b/block/coroutines.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/coroutines.h
20
+++ b/block/coroutines.h
21
@@ -XXX,XX +XXX,XX @@ bdrv_common_block_status_above(BlockDriverState *bs,
22
int generated_co_wrapper
23
nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
24
25
-int generated_co_wrapper
26
-blk_do_preadv(BlockBackend *blk, int64_t offset, int64_t bytes,
27
- QEMUIOVector *qiov, BdrvRequestFlags flags);
28
-
29
int generated_co_wrapper
30
blk_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
31
QEMUIOVector *qiov, size_t qiov_offset,
32
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
33
index XXXXXXX..XXXXXXX 100644
34
--- a/include/sysemu/block-backend-io.h
35
+++ b/include/sysemu/block-backend-io.h
36
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_copy_range(BlockBackend *blk_in, int64_t off_in,
37
* the "I/O or GS" API.
38
*/
39
40
-int blk_pread(BlockBackend *blk, int64_t offset, int64_t bytes, void *buf,
41
- BdrvRequestFlags flags);
42
-int blk_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
43
- const void *buf, BdrvRequestFlags flags);
44
+int generated_co_wrapper blk_pread(BlockBackend *blk, int64_t offset,
45
+ int64_t bytes, void *buf,
46
+ BdrvRequestFlags flags);
47
+int generated_co_wrapper blk_pwrite(BlockBackend *blk, int64_t offset,
48
+ int64_t bytes, const void *buf,
49
+ BdrvRequestFlags flags);
50
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
51
int64_t bytes, QEMUIOVector *qiov,
52
BdrvRequestFlags flags);
53
diff --git a/block/block-backend.c b/block/block-backend.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/block/block-backend.c
56
+++ b/block/block-backend.c
57
@@ -XXX,XX +XXX,XX @@ BlockAIOCB *blk_aio_pwrite_zeroes(BlockBackend *blk, int64_t offset,
58
flags | BDRV_REQ_ZERO_WRITE, cb, opaque);
59
}
60
61
-int blk_pread(BlockBackend *blk, int64_t offset, int64_t bytes, void *buf,
62
- BdrvRequestFlags flags)
63
-{
64
- int ret;
65
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
66
- IO_OR_GS_CODE();
67
-
68
- blk_inc_in_flight(blk);
69
- ret = blk_do_preadv(blk, offset, bytes, &qiov, flags);
70
- blk_dec_in_flight(blk);
71
-
72
- return ret;
73
-}
74
-
75
-int blk_pwrite(BlockBackend *blk, int64_t offset, int64_t bytes,
76
- const void *buf, BdrvRequestFlags flags)
77
-{
78
- QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
79
- IO_OR_GS_CODE();
80
-
81
- return blk_pwritev_part(blk, offset, bytes, &qiov, 0, flags);
82
-}
83
-
84
int64_t blk_getlength(BlockBackend *blk)
85
{
86
IO_CODE();
87
diff --git a/block/meson.build b/block/meson.build
88
index XXXXXXX..XXXXXXX 100644
89
--- a/block/meson.build
90
+++ b/block/meson.build
91
@@ -XXX,XX +XXX,XX @@ block_gen_c = custom_target('block-gen.c',
92
input: files(
93
'../include/block/block-io.h',
94
'../include/block/block-global-state.h',
95
+ '../include/sysemu/block-backend-io.h',
96
'coroutines.h'
97
),
98
command: [wrapper_py, '@OUTPUT@', '@INPUT@'])
99
--
100
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
Implement them using generated_co_wrapper.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220705161527.1054072-8-afaria@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/sysemu/block-backend-io.h | 6 +++++
12
tests/unit/test-block-iothread.c | 42 ++++++++++++++++++++++++++++++-
13
2 files changed, 47 insertions(+), 1 deletion(-)
14
15
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/sysemu/block-backend-io.h
18
+++ b/include/sysemu/block-backend-io.h
19
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_pread(BlockBackend *blk, int64_t offset,
20
int generated_co_wrapper blk_pwrite(BlockBackend *blk, int64_t offset,
21
int64_t bytes, const void *buf,
22
BdrvRequestFlags flags);
23
+int generated_co_wrapper blk_preadv(BlockBackend *blk, int64_t offset,
24
+ int64_t bytes, QEMUIOVector *qiov,
25
+ BdrvRequestFlags flags);
26
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
27
int64_t bytes, QEMUIOVector *qiov,
28
BdrvRequestFlags flags);
29
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
30
int64_t bytes,
31
QEMUIOVector *qiov, size_t qiov_offset,
32
BdrvRequestFlags flags);
33
+int generated_co_wrapper blk_pwritev(BlockBackend *blk, int64_t offset,
34
+ int64_t bytes, QEMUIOVector *qiov,
35
+ BdrvRequestFlags flags);
36
int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
37
int64_t bytes, QEMUIOVector *qiov,
38
BdrvRequestFlags flags);
39
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/tests/unit/test-block-iothread.c
42
+++ b/tests/unit/test-block-iothread.c
43
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwrite(BlockBackend *blk)
44
g_assert_cmpint(ret, ==, -EIO);
45
}
46
47
+static void test_sync_op_blk_preadv(BlockBackend *blk)
48
+{
49
+ uint8_t buf[512];
50
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, sizeof(buf));
51
+ int ret;
52
+
53
+ /* Success */
54
+ ret = blk_preadv(blk, 0, sizeof(buf), &qiov, 0);
55
+ g_assert_cmpint(ret, ==, 0);
56
+
57
+ /* Early error: Negative offset */
58
+ ret = blk_preadv(blk, -2, sizeof(buf), &qiov, 0);
59
+ g_assert_cmpint(ret, ==, -EIO);
60
+}
61
+
62
+static void test_sync_op_blk_pwritev(BlockBackend *blk)
63
+{
64
+ uint8_t buf[512] = { 0 };
65
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, sizeof(buf));
66
+ int ret;
67
+
68
+ /* Success */
69
+ ret = blk_pwritev(blk, 0, sizeof(buf), &qiov, 0);
70
+ g_assert_cmpint(ret, ==, 0);
71
+
72
+ /* Early error: Negative offset */
73
+ ret = blk_pwritev(blk, -2, sizeof(buf), &qiov, 0);
74
+ g_assert_cmpint(ret, ==, -EIO);
75
+}
76
+
77
static void test_sync_op_load_vmstate(BdrvChild *c)
78
{
79
uint8_t buf[512];
80
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
81
.name = "/sync-op/pwrite",
82
.fn = test_sync_op_pwrite,
83
.blkfn = test_sync_op_blk_pwrite,
84
+ }, {
85
+ .name = "/sync-op/preadv",
86
+ .fn = NULL,
87
+ .blkfn = test_sync_op_blk_preadv,
88
+ }, {
89
+ .name = "/sync-op/pwritev",
90
+ .fn = NULL,
91
+ .blkfn = test_sync_op_blk_pwritev,
92
}, {
93
.name = "/sync-op/load_vmstate",
94
.fn = test_sync_op_load_vmstate,
95
@@ -XXX,XX +XXX,XX @@ static void test_sync_op(const void *opaque)
96
97
blk_set_aio_context(blk, ctx, &error_abort);
98
aio_context_acquire(ctx);
99
- t->fn(c);
100
+ if (t->fn) {
101
+ t->fn(c);
102
+ }
103
if (t->blkfn) {
104
t->blkfn(blk);
105
}
106
--
107
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
Also convert it into a generated_co_wrapper.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220705161527.1054072-10-afaria@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
block/coroutines.h | 5 -----
12
include/sysemu/block-backend-io.h | 4 ++++
13
block/block-backend.c | 14 --------------
14
tests/unit/test-block-iothread.c | 19 +++++++++++++++++++
15
4 files changed, 23 insertions(+), 19 deletions(-)
16
17
diff --git a/block/coroutines.h b/block/coroutines.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/block/coroutines.h
20
+++ b/block/coroutines.h
21
@@ -XXX,XX +XXX,XX @@ bdrv_common_block_status_above(BlockDriverState *bs,
22
int generated_co_wrapper
23
nbd_do_establish_connection(BlockDriverState *bs, bool blocking, Error **errp);
24
25
-int generated_co_wrapper
26
-blk_do_pwritev_part(BlockBackend *blk, int64_t offset, int64_t bytes,
27
- QEMUIOVector *qiov, size_t qiov_offset,
28
- BdrvRequestFlags flags);
29
-
30
int generated_co_wrapper
31
blk_do_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
32
33
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/include/sysemu/block-backend-io.h
36
+++ b/include/sysemu/block-backend-io.h
37
@@ -XXX,XX +XXX,XX @@ int generated_co_wrapper blk_preadv(BlockBackend *blk, int64_t offset,
38
int coroutine_fn blk_co_preadv(BlockBackend *blk, int64_t offset,
39
int64_t bytes, QEMUIOVector *qiov,
40
BdrvRequestFlags flags);
41
+int generated_co_wrapper blk_pwritev_part(BlockBackend *blk, int64_t offset,
42
+ int64_t bytes, QEMUIOVector *qiov,
43
+ size_t qiov_offset,
44
+ BdrvRequestFlags flags);
45
int coroutine_fn blk_co_pwritev_part(BlockBackend *blk, int64_t offset,
46
int64_t bytes,
47
QEMUIOVector *qiov, size_t qiov_offset,
48
diff --git a/block/block-backend.c b/block/block-backend.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/block/block-backend.c
51
+++ b/block/block-backend.c
52
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwritev(BlockBackend *blk, int64_t offset,
53
return blk_co_pwritev_part(blk, offset, bytes, qiov, 0, flags);
54
}
55
56
-static int coroutine_fn blk_pwritev_part(BlockBackend *blk, int64_t offset,
57
- int64_t bytes,
58
- QEMUIOVector *qiov, size_t qiov_offset,
59
- BdrvRequestFlags flags)
60
-{
61
- int ret;
62
-
63
- blk_inc_in_flight(blk);
64
- ret = blk_do_pwritev_part(blk, offset, bytes, qiov, qiov_offset, flags);
65
- blk_dec_in_flight(blk);
66
-
67
- return ret;
68
-}
69
-
70
typedef struct BlkRwCo {
71
BlockBackend *blk;
72
int64_t offset;
73
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tests/unit/test-block-iothread.c
76
+++ b/tests/unit/test-block-iothread.c
77
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_preadv_part(BlockBackend *blk)
78
g_assert_cmpint(ret, ==, -EIO);
79
}
80
81
+static void test_sync_op_blk_pwritev_part(BlockBackend *blk)
82
+{
83
+ uint8_t buf[512] = { 0 };
84
+ QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, sizeof(buf));
85
+ int ret;
86
+
87
+ /* Success */
88
+ ret = blk_pwritev_part(blk, 0, sizeof(buf), &qiov, 0, 0);
89
+ g_assert_cmpint(ret, ==, 0);
90
+
91
+ /* Early error: Negative offset */
92
+ ret = blk_pwritev_part(blk, -2, sizeof(buf), &qiov, 0, 0);
93
+ g_assert_cmpint(ret, ==, -EIO);
94
+}
95
+
96
static void test_sync_op_load_vmstate(BdrvChild *c)
97
{
98
uint8_t buf[512];
99
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
100
.name = "/sync-op/preadv_part",
101
.fn = NULL,
102
.blkfn = test_sync_op_blk_preadv_part,
103
+ }, {
104
+ .name = "/sync-op/pwritev_part",
105
+ .fn = NULL,
106
+ .blkfn = test_sync_op_blk_pwritev_part,
107
}, {
108
.name = "/sync-op/load_vmstate",
109
.fn = test_sync_op_load_vmstate,
110
--
111
2.35.3
diff view generated by jsdifflib
Deleted patch
1
From: Alberto Faria <afaria@redhat.com>
2
1
3
Swap 'buf' and 'bytes' around for consistency with other I/O functions.
4
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
8
Message-Id: <20220705161527.1054072-11-afaria@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
11
include/sysemu/block-backend-io.h | 4 ++--
12
block/block-backend.c | 4 ++--
13
qemu-img.c | 2 +-
14
qemu-io-cmds.c | 2 +-
15
4 files changed, 6 insertions(+), 6 deletions(-)
16
17
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/sysemu/block-backend-io.h
20
+++ b/include/sysemu/block-backend-io.h
21
@@ -XXX,XX +XXX,XX @@ int blk_flush(BlockBackend *blk);
22
23
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
24
25
-int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
26
- int64_t bytes);
27
+int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, int64_t bytes,
28
+ const void *buf);
29
int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
30
int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
31
int64_t bytes, BdrvRequestFlags flags);
32
diff --git a/block/block-backend.c b/block/block-backend.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/block/block-backend.c
35
+++ b/block/block-backend.c
36
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
37
flags | BDRV_REQ_ZERO_WRITE);
38
}
39
40
-int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, const void *buf,
41
- int64_t bytes)
42
+int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, int64_t bytes,
43
+ const void *buf)
44
{
45
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
46
IO_OR_GS_CODE();
47
diff --git a/qemu-img.c b/qemu-img.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/qemu-img.c
50
+++ b/qemu-img.c
51
@@ -XXX,XX +XXX,XX @@ static int convert_do_copy(ImgConvertState *s)
52
53
if (s->compressed && !s->ret) {
54
/* signal EOF to align */
55
- ret = blk_pwrite_compressed(s->target, 0, NULL, 0);
56
+ ret = blk_pwrite_compressed(s->target, 0, 0, NULL);
57
if (ret < 0) {
58
return ret;
59
}
60
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/qemu-io-cmds.c
63
+++ b/qemu-io-cmds.c
64
@@ -XXX,XX +XXX,XX @@ static int do_write_compressed(BlockBackend *blk, char *buf, int64_t offset,
65
return -ERANGE;
66
}
67
68
- ret = blk_pwrite_compressed(blk, offset, buf, bytes);
69
+ ret = blk_pwrite_compressed(blk, offset, bytes, buf);
70
if (ret < 0) {
71
return ret;
72
}
73
--
74
2.35.3
diff view generated by jsdifflib
1
From: Alberto Faria <afaria@redhat.com>
1
From: Paolo Bonzini <pbonzini@redhat.com>
2
2
3
Also convert blk_pwrite_compressed() into a generated_co_wrapper.
3
This adds a CoMutex around the existing CoQueue. Because the write-side
4
can just take CoMutex, the old "writer" field is not necessary anymore.
5
Instead of removing it altogether, count the number of pending writers
6
during a read-side critical section and forbid further readers from
7
entering.
4
8
5
Signed-off-by: Alberto Faria <afaria@redhat.com>
9
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
6
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: Fam Zheng <famz@redhat.com>
7
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
11
Message-id: 20170213181244.16297-7-pbonzini@redhat.com
8
Message-Id: <20220705161527.1054072-12-afaria@redhat.com>
12
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
9
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
10
---
13
---
11
include/sysemu/block-backend-io.h | 7 +++++--
14
include/qemu/coroutine.h | 3 ++-
12
block/block-backend.c | 8 ++++----
15
util/qemu-coroutine-lock.c | 35 ++++++++++++++++++++++++-----------
13
tests/unit/test-block-iothread.c | 18 ++++++++++++++++++
16
2 files changed, 26 insertions(+), 12 deletions(-)
14
3 files changed, 27 insertions(+), 6 deletions(-)
15
17
16
diff --git a/include/sysemu/block-backend-io.h b/include/sysemu/block-backend-io.h
18
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
17
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
18
--- a/include/sysemu/block-backend-io.h
20
--- a/include/qemu/coroutine.h
19
+++ b/include/sysemu/block-backend-io.h
21
+++ b/include/qemu/coroutine.h
20
@@ -XXX,XX +XXX,XX @@ int blk_flush(BlockBackend *blk);
22
@@ -XXX,XX +XXX,XX @@ bool qemu_co_queue_empty(CoQueue *queue);
21
23
22
int blk_ioctl(BlockBackend *blk, unsigned long int req, void *buf);
24
23
25
typedef struct CoRwlock {
24
-int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, int64_t bytes,
26
- bool writer;
25
- const void *buf);
27
+ int pending_writer;
26
+int generated_co_wrapper blk_pwrite_compressed(BlockBackend *blk,
28
int reader;
27
+ int64_t offset, int64_t bytes,
29
+ CoMutex mutex;
28
+ const void *buf);
30
CoQueue queue;
29
+int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
31
} CoRwlock;
30
+ int64_t bytes, const void *buf);
32
31
int blk_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes);
33
diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c
32
int blk_pwrite_zeroes(BlockBackend *blk, int64_t offset,
33
int64_t bytes, BdrvRequestFlags flags);
34
diff --git a/block/block-backend.c b/block/block-backend.c
35
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
36
--- a/block/block-backend.c
35
--- a/util/qemu-coroutine-lock.c
37
+++ b/block/block-backend.c
36
+++ b/util/qemu-coroutine-lock.c
38
@@ -XXX,XX +XXX,XX @@ int coroutine_fn blk_co_pwrite_zeroes(BlockBackend *blk, int64_t offset,
37
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_init(CoRwlock *lock)
39
flags | BDRV_REQ_ZERO_WRITE);
38
{
39
memset(lock, 0, sizeof(*lock));
40
qemu_co_queue_init(&lock->queue);
41
+ qemu_co_mutex_init(&lock->mutex);
40
}
42
}
41
43
42
-int blk_pwrite_compressed(BlockBackend *blk, int64_t offset, int64_t bytes,
44
void qemu_co_rwlock_rdlock(CoRwlock *lock)
43
- const void *buf)
44
+int coroutine_fn blk_co_pwrite_compressed(BlockBackend *blk, int64_t offset,
45
+ int64_t bytes, const void *buf)
46
{
45
{
47
QEMUIOVector qiov = QEMU_IOVEC_INIT_BUF(qiov, buf, bytes);
46
Coroutine *self = qemu_coroutine_self();
48
IO_OR_GS_CODE();
47
49
- return blk_pwritev_part(blk, offset, bytes, &qiov, 0,
48
- while (lock->writer) {
50
- BDRV_REQ_WRITE_COMPRESSED);
49
- qemu_co_queue_wait(&lock->queue, NULL);
51
+ return blk_co_pwritev_part(blk, offset, bytes, &qiov, 0,
50
+ qemu_co_mutex_lock(&lock->mutex);
52
+ BDRV_REQ_WRITE_COMPRESSED);
51
+ /* For fairness, wait if a writer is in line. */
52
+ while (lock->pending_writer) {
53
+ qemu_co_queue_wait(&lock->queue, &lock->mutex);
54
}
55
lock->reader++;
56
+ qemu_co_mutex_unlock(&lock->mutex);
57
+
58
+ /* The rest of the read-side critical section is run without the mutex. */
59
self->locks_held++;
53
}
60
}
54
61
55
int blk_truncate(BlockBackend *blk, int64_t offset, bool exact,
62
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
56
diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c
63
Coroutine *self = qemu_coroutine_self();
57
index XXXXXXX..XXXXXXX 100644
64
58
--- a/tests/unit/test-block-iothread.c
65
assert(qemu_in_coroutine());
59
+++ b/tests/unit/test-block-iothread.c
66
- if (lock->writer) {
60
@@ -XXX,XX +XXX,XX @@ static void test_sync_op_blk_pwritev_part(BlockBackend *blk)
67
- lock->writer = false;
61
g_assert_cmpint(ret, ==, -EIO);
68
+ if (!lock->reader) {
69
+ /* The critical section started in qemu_co_rwlock_wrlock. */
70
qemu_co_queue_restart_all(&lock->queue);
71
} else {
72
+ self->locks_held--;
73
+
74
+ qemu_co_mutex_lock(&lock->mutex);
75
lock->reader--;
76
assert(lock->reader >= 0);
77
/* Wakeup only one waiting writer */
78
@@ -XXX,XX +XXX,XX @@ void qemu_co_rwlock_unlock(CoRwlock *lock)
79
qemu_co_queue_next(&lock->queue);
80
}
81
}
82
- self->locks_held--;
83
+ qemu_co_mutex_unlock(&lock->mutex);
62
}
84
}
63
85
64
+static void test_sync_op_blk_pwrite_compressed(BlockBackend *blk)
86
void qemu_co_rwlock_wrlock(CoRwlock *lock)
65
+{
87
{
66
+ uint8_t buf[512] = { 0 };
88
- Coroutine *self = qemu_coroutine_self();
67
+ int ret;
89
-
90
- while (lock->writer || lock->reader) {
91
- qemu_co_queue_wait(&lock->queue, NULL);
92
+ qemu_co_mutex_lock(&lock->mutex);
93
+ lock->pending_writer++;
94
+ while (lock->reader) {
95
+ qemu_co_queue_wait(&lock->queue, &lock->mutex);
96
}
97
- lock->writer = true;
98
- self->locks_held++;
99
+ lock->pending_writer--;
68
+
100
+
69
+ /* Late error: Not supported */
101
+ /* The rest of the write-side critical section is run with
70
+ ret = blk_pwrite_compressed(blk, 0, sizeof(buf), buf);
102
+ * the mutex taken, so that lock->reader remains zero.
71
+ g_assert_cmpint(ret, ==, -ENOTSUP);
103
+ * There is no need to update self->locks_held.
72
+
104
+ */
73
+ /* Early error: Negative offset */
105
}
74
+ ret = blk_pwrite_compressed(blk, -2, sizeof(buf), buf);
75
+ g_assert_cmpint(ret, ==, -EIO);
76
+}
77
+
78
static void test_sync_op_load_vmstate(BdrvChild *c)
79
{
80
uint8_t buf[512];
81
@@ -XXX,XX +XXX,XX @@ const SyncOpTest sync_op_tests[] = {
82
.name = "/sync-op/pwritev_part",
83
.fn = NULL,
84
.blkfn = test_sync_op_blk_pwritev_part,
85
+ }, {
86
+ .name = "/sync-op/pwrite_compressed",
87
+ .fn = NULL,
88
+ .blkfn = test_sync_op_blk_pwrite_compressed,
89
}, {
90
.name = "/sync-op/load_vmstate",
91
.fn = test_sync_op_load_vmstate,
92
--
106
--
93
2.35.3
107
2.9.3
108
109
diff view generated by jsdifflib