qemu/include/block
Kevin Wolf d8fbf9aa85 block/export: Fix graph locking in blk_get_geometry() call
blk_get_geometry() eventually calls bdrv_nb_sectors(), which is a
co_wrapper_mixed_bdrv_rdlock. This means that when it is called from
coroutine context, it already assume to have the graph locked.

However, virtio_blk_sect_range_ok() in block/export/virtio-blk-handler.c
(used by vhost-user-blk and VDUSE exports) runs in a coroutine, but
doesn't take the graph lock - blk_*() functions are generally expected
to do that internally. This causes an assertion failure when accessing
an export for the first time if it runs in an iothread.

This is an example of the crash:

  $ ./storage-daemon/qemu-storage-daemon --object iothread,id=th0 --blockdev file,filename=/home/kwolf/images/hd.img,node-name=disk --export vhost-user-blk,addr.type=unix,addr.path=/tmp/vhost.sock,node-name=disk,id=exp0,iothread=th0
  qemu-storage-daemon: ../block/graph-lock.c:268: void assert_bdrv_graph_readable(void): Assertion `qemu_in_main_thread() || reader_count()' failed.

  (gdb) bt
  #0  0x00007ffff6eafe5c in __pthread_kill_implementation () from /lib64/libc.so.6
  #1  0x00007ffff6e5fa76 in raise () from /lib64/libc.so.6
  #2  0x00007ffff6e497fc in abort () from /lib64/libc.so.6
  #3  0x00007ffff6e4971b in __assert_fail_base.cold () from /lib64/libc.so.6
  #4  0x00007ffff6e58656 in __assert_fail () from /lib64/libc.so.6
  #5  0x00005555556337a3 in assert_bdrv_graph_readable () at ../block/graph-lock.c:268
  #6  0x00005555555fd5a2 in bdrv_co_nb_sectors (bs=0x5555564c5ef0) at ../block.c:5847
  #7  0x00005555555ee949 in bdrv_nb_sectors (bs=0x5555564c5ef0) at block/block-gen.c:256
  #8  0x00005555555fd6b9 in bdrv_get_geometry (bs=0x5555564c5ef0, nb_sectors_ptr=0x7fffef7fedd0) at ../block.c:5884
  #9  0x000055555562ad6d in blk_get_geometry (blk=0x5555564cb200, nb_sectors_ptr=0x7fffef7fedd0) at ../block/block-backend.c:1624
  #10 0x00005555555ddb74 in virtio_blk_sect_range_ok (blk=0x5555564cb200, block_size=512, sector=0, size=512) at ../block/export/virtio-blk-handler.c:44
  #11 0x00005555555dd80d in virtio_blk_process_req (handler=0x5555564cbb98, in_iov=0x7fffe8003830, out_iov=0x7fffe8003860, in_num=1, out_num=0) at ../block/export/virtio-blk-handler.c:189
  #12 0x00005555555dd546 in vu_blk_virtio_process_req (opaque=0x7fffe8003800) at ../block/export/vhost-user-blk-server.c:66
  #13 0x00005555557bf4a1 in coroutine_trampoline (i0=-402635264, i1=32767) at ../util/coroutine-ucontext.c:177
  #14 0x00007ffff6e75c20 in ?? () from /lib64/libc.so.6
  #15 0x00007fffefffa870 in ?? ()
  #16 0x0000000000000000 in ?? ()

Fix this by creating a new blk_co_get_geometry() that takes the lock,
and changing blk_get_geometry() to be a co_wrapper_mixed around it.

To make the resulting code cleaner, virtio-blk-handler.c can directly
call the coroutine version now (though that wouldn't be necessary for
fixing the bug, taking the lock in blk_co_get_geometry() is what fixes
it).

Fixes: 8ab8140a04
Reported-by: Lukáš Doktor <ldoktor@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20230327113959.60071-1-kwolf@redhat.com>
Reviewed-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2023-03-27 15:16:05 +02:00
..
accounting.h block: pass OnOffAuto instead of bool to block_acct_setup() 2022-09-30 18:02:30 +02:00
aio_task.h coroutine: Move coroutine_fn to qemu/osdep.h, trim includes 2023-01-19 10:18:28 +01:00
aio-wait.h aio-wait: switch to smp_mb__after_rmw() 2023-03-07 12:39:50 +01:00
aio.h aio: make aio_set_fd_poll() static to aio-posix.c 2023-03-13 15:23:37 +04:00
block_backup.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
block_int-common.h block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK 2023-02-23 19:49:33 +01:00
block_int-global-state.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
block_int-io.h block: Mark bdrv_co_refresh_total_sectors() and callers GRAPH_RDLOCK 2023-02-23 19:49:33 +01:00
block_int.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
block-common.h block-coroutine-wrapper: Introduce no_co_wrapper 2023-02-17 11:22:19 +01:00
block-copy.h block: Mark bdrv_co_block_status() and callers GRAPH_RDLOCK 2023-02-23 19:49:07 +01:00
block-global-state.h block: Mark bdrv_co_create() and callers GRAPH_RDLOCK 2023-02-23 19:49:23 +01:00
block-hmp-cmds.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
block-io.h block/export: Fix graph locking in blk_get_geometry() call 2023-03-27 15:16:05 +02:00
block.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
blockjob_int.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
blockjob.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
dirty-bitmap.h block: Mark bdrv_*_dirty_bitmap() and callers GRAPH_RDLOCK 2023-02-23 19:49:32 +01:00
export.h block/export: Move blk to BlockExport 2020-10-02 15:46:40 +02:00
fuse.h fuse: Allow exporting BDSs via FUSE 2020-12-11 17:52:39 +01:00
graph-lock.h block: Clean up includes 2023-02-08 07:28:05 +01:00
nbd.h block/nbd: Add missing <qemu/bswap.h> include 2023-02-01 16:52:32 +01:00
nvme.h hw/nvme: flexible data placement emulation 2023-03-06 15:28:02 +01:00
qapi.h qemu-img: Change info key names for protocol nodes 2023-02-01 16:52:33 +01:00
qdict.h include: move qdict_{crumple,flatten} declarations 2022-04-21 17:03:51 +04:00
raw-aio.h coroutine: Clean up superfluous inclusion of qemu/coroutine.h 2023-01-19 10:18:28 +01:00
replication.h replication: move include out of root directory 2021-05-26 14:49:46 +02:00
reqlist.h block/reqlist: add reqlist_wait_all() 2022-03-07 09:33:30 +01:00
snapshot.h include/block/snapshot: global state API + assertions 2022-03-04 18:18:25 +01:00
thread-pool.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
throttle-groups.h include/block: Untangle inclusion loops 2023-01-20 07:24:28 +01:00
write-threshold.h block: Clean up includes 2023-02-08 07:28:05 +01:00