qemu/block
Sergio Lopez e091f0e905 block/linux-aio: acquire AioContext before qemu_laio_process_completions
In qemu_laio_process_completions_and_submit, the AioContext is acquired
before the ioq_submit iteration and after qemu_laio_process_completions,
but the latter is not thread safe either.

This change avoids a number of random crashes when the Main Thread and
an IO Thread collide processing completions for the same AioContext.
This is an example of such crash:

 - The IO Thread is trying to acquire the AioContext at aio_co_enter,
   which evidences that it didn't lock it before:

Thread 3 (Thread 0x7fdfd8bd8700 (LWP 36743)):
 #0  0x00007fdfe0dd542d in __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
 #1  0x00007fdfe0dd0de6 in _L_lock_870 () at /lib64/libpthread.so.0
 #2  0x00007fdfe0dd0cdf in __GI___pthread_mutex_lock (mutex=mutex@entry=0x5631fde0e6c0)
    at ../nptl/pthread_mutex_lock.c:114
 #3  0x00005631fc0603a7 in qemu_mutex_lock_impl (mutex=0x5631fde0e6c0, file=0x5631fc23520f "util/async.c", line=511) at util/qemu-thread-posix.c:66
 #4  0x00005631fc05b558 in aio_co_enter (ctx=0x5631fde0e660, co=0x7fdfcc0c2b40) at util/async.c:493
 #5  0x00005631fc05b5ac in aio_co_wake (co=<optimized out>) at util/async.c:478
 #6  0x00005631fbfc51ad in qemu_laio_process_completion (laiocb=<optimized out>) at block/linux-aio.c:104
 #7  0x00005631fbfc523c in qemu_laio_process_completions (s=s@entry=0x7fdfc0297670)
    at block/linux-aio.c:222
 #8  0x00005631fbfc5499 in qemu_laio_process_completions_and_submit (s=0x7fdfc0297670)
    at block/linux-aio.c:237
 #9  0x00005631fc05d978 in aio_dispatch_handlers (ctx=ctx@entry=0x5631fde0e660) at util/aio-posix.c:406
 #10 0x00005631fc05e3ea in aio_poll (ctx=0x5631fde0e660, blocking=blocking@entry=true)
    at util/aio-posix.c:693
 #11 0x00005631fbd7ad96 in iothread_run (opaque=0x5631fde0e1c0) at iothread.c:64
 #12 0x00007fdfe0dcee25 in start_thread (arg=0x7fdfd8bd8700) at pthread_create.c:308
 #13 0x00007fdfe0afc34d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113

 - The Main Thread is also processing completions from the same
   AioContext, and crashes due to failed assertion at util/iov.c:78:

Thread 1 (Thread 0x7fdfeb5eac80 (LWP 36740)):
 #0  0x00007fdfe0a391f7 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
 #1  0x00007fdfe0a3a8e8 in __GI_abort () at abort.c:90
 #2  0x00007fdfe0a32266 in __assert_fail_base (fmt=0x7fdfe0b84e68 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x5631fc238ccb "offset == 0", file=file@entry=0x5631fc23698e "util/iov.c", line=line@entry=78, function=function@entry=0x5631fc236adc <__PRETTY_FUNCTION__.15220> "iov_memset")
    at assert.c:92
 #3  0x00007fdfe0a32312 in __GI___assert_fail (assertion=assertion@entry=0x5631fc238ccb "offset == 0", file=file@entry=0x5631fc23698e "util/iov.c", line=line@entry=78, function=function@entry=0x5631fc236adc <__PRETTY_FUNCTION__.15220> "iov_memset") at assert.c:101
 #4  0x00005631fc065287 in iov_memset (iov=<optimized out>, iov_cnt=<optimized out>, offset=<optimized out>, offset@entry=65536, fillc=fillc@entry=0, bytes=15515191315812405248) at util/iov.c:78
 #5  0x00005631fc065a63 in qemu_iovec_memset (qiov=<optimized out>, offset=offset@entry=65536, fillc=fillc@entry=0, bytes=<optimized out>) at util/iov.c:410
 #6  0x00005631fbfc5178 in qemu_laio_process_completion (laiocb=0x7fdd920df630) at block/linux-aio.c:88
 #7  0x00005631fbfc523c in qemu_laio_process_completions (s=s@entry=0x7fdfc0297670)
    at block/linux-aio.c:222
 #8  0x00005631fbfc5499 in qemu_laio_process_completions_and_submit (s=0x7fdfc0297670)
    at block/linux-aio.c:237
 #9  0x00005631fbfc54ed in qemu_laio_poll_cb (opaque=<optimized out>) at block/linux-aio.c:272
 #10 0x00005631fc05d85e in run_poll_handlers_once (ctx=ctx@entry=0x5631fde0e660) at util/aio-posix.c:497
 #11 0x00005631fc05e2ca in aio_poll (blocking=false, ctx=0x5631fde0e660) at util/aio-posix.c:574
 #12 0x00005631fc05e2ca in aio_poll (ctx=0x5631fde0e660, blocking=blocking@entry=false)
    at util/aio-posix.c:604
 #13 0x00005631fbfcb8a3 in bdrv_do_drained_begin (ignore_parent=<optimized out>, recursive=<optimized out>, bs=<optimized out>) at block/io.c:273
 #14 0x00005631fbfcb8a3 in bdrv_do_drained_begin (bs=0x5631fe8b6200, recursive=<optimized out>, parent=0x0, ignore_bds_parents=<optimized out>, poll=<optimized out>) at block/io.c:390
 #15 0x00005631fbfbcd2e in blk_drain (blk=0x5631fe83ac80) at block/block-backend.c:1590
 #16 0x00005631fbfbe138 in blk_remove_bs (blk=blk@entry=0x5631fe83ac80) at block/block-backend.c:774
 #17 0x00005631fbfbe3d6 in blk_unref (blk=0x5631fe83ac80) at block/block-backend.c:401
 #18 0x00005631fbfbe3d6 in blk_unref (blk=0x5631fe83ac80) at block/block-backend.c:449
 #19 0x00005631fbfc9a69 in commit_complete (job=0x5631fe8b94b0, opaque=0x7fdfcc1bb080)
    at block/commit.c:92
 #20 0x00005631fbf7d662 in job_defer_to_main_loop_bh (opaque=0x7fdfcc1b4560) at job.c:973
 #21 0x00005631fc05ad41 in aio_bh_poll (bh=0x7fdfcc01ad90) at util/async.c:90
 #22 0x00005631fc05ad41 in aio_bh_poll (ctx=ctx@entry=0x5631fddffdb0) at util/async.c:118
 #23 0x00005631fc05e210 in aio_dispatch (ctx=0x5631fddffdb0) at util/aio-posix.c:436
 #24 0x00005631fc05ac1e in aio_ctx_dispatch (source=<optimized out>, callback=<optimized out>, user_data=<optimized out>) at util/async.c:261
 #25 0x00007fdfeaae44c9 in g_main_context_dispatch (context=0x5631fde00140) at gmain.c:3201
 #26 0x00007fdfeaae44c9 in g_main_context_dispatch (context=context@entry=0x5631fde00140) at gmain.c:3854
 #27 0x00005631fc05d503 in main_loop_wait () at util/main-loop.c:215
 #28 0x00005631fc05d503 in main_loop_wait (timeout=<optimized out>) at util/main-loop.c:238
 #29 0x00005631fc05d503 in main_loop_wait (nonblocking=nonblocking@entry=0) at util/main-loop.c:497
 #30 0x00005631fbd81412 in main_loop () at vl.c:1866
 #31 0x00005631fbc18ff3 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)
    at vl.c:4647

 - A closer examination shows that s->io_q.in_flight appears to have
   gone backwards:

(gdb) frame 7
 #7  0x00005631fbfc523c in qemu_laio_process_completions (s=s@entry=0x7fdfc0297670)
    at block/linux-aio.c:222
222	            qemu_laio_process_completion(laiocb);
(gdb) p s
$2 = (LinuxAioState *) 0x7fdfc0297670
(gdb) p *s
$3 = {aio_context = 0x5631fde0e660, ctx = 0x7fdfeb43b000, e = {rfd = 33, wfd = 33}, io_q = {plugged = 0,
    in_queue = 0, in_flight = 4294967280, blocked = false, pending = {sqh_first = 0x0,
      sqh_last = 0x7fdfc0297698}}, completion_bh = 0x7fdfc0280ef0, event_idx = 21, event_max = 241}
(gdb) p/x s->io_q.in_flight
$4 = 0xfffffff0

Signed-off-by: Sergio Lopez <slp@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2018-09-25 15:50:15 +02:00
..
accounting.c block/accounting: introduce latency histogram 2018-03-19 14:58:37 -05:00
backup.c block/backup: make function variables consistently named 2018-08-31 16:28:33 +02:00
blkdebug.c qstring: Move qstring_from_substr()'s @end one to the right 2018-07-28 09:09:58 +02:00
blklogwrites.c block: Use BdrvChild to discard 2018-07-10 16:01:52 +02:00
blkreplay.c block: drop empty .bdrv_close handlers 2018-08-15 12:50:39 +02:00
blkverify.c qstring: Move qstring_from_substr()'s @end one to the right 2018-07-28 09:09:58 +02:00
block-backend.c qapi: Drop qapi_event_send_FOO()'s Error ** argument 2018-08-28 18:21:38 +02:00
bochs.c block: Deprecate bdrv_set_read_only() and users 2017-11-17 13:35:59 +01:00
cloop.c block: Deprecate bdrv_set_read_only() and users 2017-11-17 13:35:59 +01:00
commit.c block/commit: refactor commit to use job callbacks 2018-09-25 15:31:15 +02:00
copy-on-read.c block: drop empty .bdrv_close handlers 2018-08-15 12:50:39 +02:00
create.c jobs: utilize job_exit shim 2018-08-31 16:28:33 +02:00
crypto.c luks: Allow share-rw=on 2018-08-15 12:50:39 +02:00
crypto.h block/crypto: Simplify block_crypto_{open,create}_opts_init() 2018-06-29 14:20:56 +02:00
curl.c curl: Make sslverify=off disable host as well as peer verification. 2018-09-24 23:46:05 -04:00
dirty-bitmap.c dirty-bitmap: fix double lock on bitmap enabling 2018-07-04 02:12:49 -04:00
dmg-bz2.c dmg: Move libbz2 code to dmg-bz2.so 2016-10-07 14:14:06 +02:00
dmg.c block: Deprecate bdrv_set_read_only() and users 2017-11-17 13:35:59 +01:00
dmg.h block: remove "qemu/osdep.h" from header file 2017-12-18 17:07:02 +03:00
file-posix.c file-posix: Fix write_zeroes with unmap on block devices 2018-07-30 15:35:37 +02:00
file-win32.c block: Prefix file driver trace points with "file_" 2018-07-10 16:01:51 +02:00
gluster.c block: Fix typos in comments (found by codespell) 2018-07-23 16:50:43 +02:00
io.c block: Use common write req handling in truncate 2018-07-10 16:46:22 +02:00
iscsi-opts.c Move include qemu/option.h from qemu-common.h to actual users 2018-02-09 13:52:16 +01:00
iscsi.c block: Add copy offloading trace points 2018-07-10 16:01:52 +02:00
linux-aio.c block/linux-aio: acquire AioContext before qemu_laio_process_completions 2018-09-25 15:50:15 +02:00
Makefile.objs block: Add blklogwrites 2018-07-05 10:29:19 +02:00
mirror.c block/mirror: conservative mirror_exit refactor 2018-09-25 15:31:15 +02:00
nbd-client.c nbd/client: Add x-dirty-bitmap to query bitmap from server 2018-07-02 15:27:38 -05:00
nbd-client.h nbd/client: Add x-dirty-bitmap to query bitmap from server 2018-07-02 15:27:38 -05:00
nbd.c qstring: Move qstring_from_substr()'s @end one to the right 2018-07-28 09:09:58 +02:00
nfs.c block: Convert .bdrv_truncate callback to coroutine_fn 2018-06-29 14:20:56 +02:00
null.c block: drop empty .bdrv_close handlers 2018-08-15 12:50:39 +02:00
nvme.c nvme: simplify plug/unplug 2018-08-15 10:12:35 +08:00
parallels.c parallels: Switch to byte-based calls 2018-06-29 14:20:56 +02:00
parallels.h Clean up includes 2018-02-09 05:05:11 +01:00
qapi.c block/qapi: Fix memory leak in qmp_query_blockstats() 2018-08-15 12:50:39 +02:00
qcow2-bitmap.c qcow2: add overlap check for bitmap directory 2018-07-09 19:43:24 +02:00
qcow2-cache.c qcow2: Allow configuring the L2 slice size 2018-02-13 17:00:00 +01:00
qcow2-cluster.c qcow2: Free allocated clusters on write error 2018-06-29 14:20:56 +02:00
qcow2-refcount.c Block layer patches: 2018-07-10 17:28:29 +01:00
qcow2-snapshot.c block: use local path for local headers 2018-05-31 04:16:06 +03:00
qcow2.c qapi: Drop qapi_event_send_FOO()'s Error ** argument 2018-08-28 18:21:38 +02:00
qcow2.h qcow2: add overlap check for bitmap directory 2018-07-09 19:43:24 +02:00
qcow.c qcow: fix a reference leak 2018-07-30 15:35:37 +02:00
qed-check.c block: convert bdrv_check callback to coroutine_fn 2018-03-09 15:17:47 +01:00
qed-cluster.c qed: protect table cache with CoMutex 2017-07-17 11:34:11 +08:00
qed-l2-cache.c qed: protect table cache with CoMutex 2017-07-17 11:34:11 +08:00
qed-table.c block: convert bdrv_check callback to coroutine_fn 2018-03-09 15:17:47 +01:00
qed.c block: Convert .bdrv_truncate callback to coroutine_fn 2018-06-29 14:20:56 +02:00
qed.h qed: protect table cache with CoMutex 2017-07-17 11:34:11 +08:00
quorum.c qapi: Drop qapi_event_send_FOO()'s Error ** argument 2018-08-28 18:21:38 +02:00
raw-format.c block: drop empty .bdrv_close handlers 2018-08-15 12:50:39 +02:00
rbd.c block/rbd: Attempt to parse legacy filenames 2018-09-24 23:46:05 -04:00
replication.c replication: Switch to byte-based calls 2018-06-29 14:20:56 +02:00
sheepdog.c block: Convert .bdrv_truncate callback to coroutine_fn 2018-06-29 14:20:56 +02:00
snapshot.c block: make .bdrv_close optional 2018-08-15 12:50:39 +02:00
ssh.c block: Convert .bdrv_truncate callback to coroutine_fn 2018-06-29 14:20:56 +02:00
stream.c block/stream: refactor stream to use job callbacks 2018-09-25 15:31:15 +02:00
throttle-groups.c throttle-groups: Don't allow timers without throttled requests 2018-08-15 12:50:39 +02:00
throttle.c block: Use BdrvChild to discard 2018-07-10 16:01:52 +02:00
trace-events block: Add copy offloading trace points 2018-07-10 16:01:52 +02:00
vdi.c vdi: Use definitions from "qemu/units.h" 2018-07-02 14:45:23 +02:00
vhdx-endian.c block: use local path for local headers 2018-05-31 04:16:06 +03:00
vhdx-log.c block: use local path for local headers 2018-05-31 04:16:06 +03:00
vhdx.c block: Fix typos in comments (found by codespell) 2018-07-23 16:50:43 +02:00
vhdx.h block: vhdx - update PAYLOAD_BLOCK_UNMAPPED value to match 1.00 spec 2014-12-12 15:42:22 +00:00
vmdk.c vmdk: Fix possible segfault with non-VMDK backing 2018-07-09 19:43:24 +02:00
vpc.c block: Factor out qobject_input_visitor_new_flat_confused() 2018-06-15 14:49:44 +02:00
vvfat.c block/vvfat: Disable debug message by default 2018-07-23 16:50:43 +02:00
vxhs.c block: Add block-specific QDict header 2018-06-15 14:49:44 +02:00
win32-aio.c file-win32: Switch to byte-based callbacks 2018-05-15 16:11:41 +02:00
write-threshold.c qapi: Drop qapi_event_send_FOO()'s Error ** argument 2018-08-28 18:21:38 +02:00