1 | The following changes since commit 063833a6ec2a6747e27c5f9866bb44c7e8de1265: | 1 | The following changes since commit ed8ad9728a9c0eec34db9dff61dfa2f1dd625637: |
---|---|---|---|
2 | 2 | ||
3 | Merge remote-tracking branch 'remotes/mcayland/tags/qemu-sparc-signed' into staging (2017-10-19 18:42:51 +0100) | 3 | Merge tag 'pull-tpm-2023-07-14-1' of https://github.com/stefanberger/qemu-tpm into staging (2023-07-15 14:54:04 +0100) |
4 | 4 | ||
5 | are available in the git repository at: | 5 | are available in the Git repository at: |
6 | 6 | ||
7 | git://github.com/stefanha/qemu.git tags/block-pull-request | 7 | https://gitlab.com/stefanha/qemu.git tags/block-pull-request |
8 | 8 | ||
9 | for you to fetch changes up to e947d47da0b16e80d237c510e9d2e80799578c7f: | 9 | for you to fetch changes up to 66547f416a61e0cb711dc76821890242432ba193: |
10 | 10 | ||
11 | oslib-posix: Fix compiler warning and some data types (2017-10-20 11:16:27 +0200) | 11 | block/nvme: invoke blk_io_plug_call() outside q->lock (2023-07-17 09:17:41 -0400) |
12 | |||
13 | ---------------------------------------------------------------- | ||
14 | Pull request | ||
15 | |||
16 | Fix the hang in the nvme:// block driver during startup. | ||
12 | 17 | ||
13 | ---------------------------------------------------------------- | 18 | ---------------------------------------------------------------- |
14 | 19 | ||
15 | ---------------------------------------------------------------- | 20 | Stefan Hajnoczi (1): |
21 | block/nvme: invoke blk_io_plug_call() outside q->lock | ||
16 | 22 | ||
17 | Stefan Weil (1): | 23 | block/nvme.c | 3 ++- |
18 | oslib-posix: Fix compiler warning and some data types | 24 | 1 file changed, 2 insertions(+), 1 deletion(-) |
19 | |||
20 | util/oslib-posix.c | 15 ++++++++------- | ||
21 | 1 file changed, 8 insertions(+), 7 deletions(-) | ||
22 | 25 | ||
23 | -- | 26 | -- |
24 | 2.13.6 | 27 | 2.40.1 |
25 | |||
26 | diff view generated by jsdifflib |
1 | From: Stefan Weil <sw@weilnetz.de> | 1 | blk_io_plug_call() is invoked outside a blk_io_plug()/blk_io_unplug() |
---|---|---|---|
2 | section while opening the NVMe drive from: | ||
2 | 3 | ||
3 | gcc warning: | 4 | nvme_file_open() -> |
5 | nvme_init() -> | ||
6 | nvme_identify() -> | ||
7 | nvme_admin_cmd_sync() -> | ||
8 | nvme_submit_command() -> | ||
9 | blk_io_plug_call() | ||
4 | 10 | ||
5 | /qemu/util/oslib-posix.c:304:11: error: | 11 | blk_io_plug_call() immediately invokes the given callback when the |
6 | variable ‘addr’ might be clobbered by ‘longjmp’ or ‘vfork’ | 12 | current thread is not plugged, as is the case during nvme_file_open(). |
7 | [-Werror=clobbered] | ||
8 | 13 | ||
9 | Fix also some related data types: | 14 | Unfortunately, nvme_submit_command() calls blk_io_plug_call() with |
15 | q->lock still held: | ||
10 | 16 | ||
11 | numpages, hpagesize are used as pointer offset. | 17 | ... |
12 | Always use size_t for them and also for the derived | 18 | q->sq.tail = (q->sq.tail + 1) % NVME_QUEUE_SIZE; |
13 | numpages_per_thread and size_per_thread. | 19 | q->need_kick++; |
20 | blk_io_plug_call(nvme_unplug_fn, q); | ||
21 | qemu_mutex_unlock(&q->lock); | ||
22 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
14 | 23 | ||
15 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> | 24 | nvme_unplug_fn() deadlocks trying to acquire q->lock because the lock is |
16 | Signed-off-by: Stefan Weil <sw@weilnetz.de> | 25 | already acquired by the same thread. The symptom is that QEMU hangs |
17 | Message-id: 20171016202912.1117-1-sw@weilnetz.de | 26 | during startup while opening the NVMe drive. |
27 | |||
28 | Fix this by moving the blk_io_plug_call() outside q->lock. This is safe | ||
29 | because no other thread runs code related to this queue and | ||
30 | blk_io_plug_call()'s internal state is immune to thread safety issues | ||
31 | since it is thread-local. | ||
32 | |||
33 | Reported-by: Lukáš Doktor <ldoktor@redhat.com> | ||
34 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
35 | Tested-by: Lukas Doktor <ldoktor@redhat.com> | ||
36 | Message-id: 20230712191628.252806-1-stefanha@redhat.com | ||
37 | Fixes: f2e590002bd6 ("block/nvme: convert to blk_io_plug_call() API") | ||
18 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | 38 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> |
19 | --- | 39 | --- |
20 | util/oslib-posix.c | 15 ++++++++------- | 40 | block/nvme.c | 3 ++- |
21 | 1 file changed, 8 insertions(+), 7 deletions(-) | 41 | 1 file changed, 2 insertions(+), 1 deletion(-) |
22 | 42 | ||
23 | diff --git a/util/oslib-posix.c b/util/oslib-posix.c | 43 | diff --git a/block/nvme.c b/block/nvme.c |
24 | index XXXXXXX..XXXXXXX 100644 | 44 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/util/oslib-posix.c | 45 | --- a/block/nvme.c |
26 | +++ b/util/oslib-posix.c | 46 | +++ b/block/nvme.c |
27 | @@ -XXX,XX +XXX,XX @@ | 47 | @@ -XXX,XX +XXX,XX @@ static void nvme_submit_command(NVMeQueuePair *q, NVMeRequest *req, |
28 | 48 | q->sq.tail * NVME_SQ_ENTRY_BYTES, cmd, sizeof(*cmd)); | |
29 | struct MemsetThread { | 49 | q->sq.tail = (q->sq.tail + 1) % NVME_QUEUE_SIZE; |
30 | char *addr; | 50 | q->need_kick++; |
31 | - uint64_t numpages; | 51 | + qemu_mutex_unlock(&q->lock); |
32 | - uint64_t hpagesize; | 52 | + |
33 | + size_t numpages; | 53 | blk_io_plug_call(nvme_unplug_fn, q); |
34 | + size_t hpagesize; | 54 | - qemu_mutex_unlock(&q->lock); |
35 | QemuThread pgthread; | 55 | } |
36 | sigjmp_buf env; | 56 | |
37 | }; | 57 | static void nvme_admin_cmd_sync_cb(void *opaque, int ret) |
38 | @@ -XXX,XX +XXX,XX @@ static void sigbus_handler(int signal) | ||
39 | static void *do_touch_pages(void *arg) | ||
40 | { | ||
41 | MemsetThread *memset_args = (MemsetThread *)arg; | ||
42 | - char *addr = memset_args->addr; | ||
43 | - uint64_t numpages = memset_args->numpages; | ||
44 | - uint64_t hpagesize = memset_args->hpagesize; | ||
45 | sigset_t set, oldset; | ||
46 | - int i = 0; | ||
47 | |||
48 | /* unblock SIGBUS */ | ||
49 | sigemptyset(&set); | ||
50 | @@ -XXX,XX +XXX,XX @@ static void *do_touch_pages(void *arg) | ||
51 | if (sigsetjmp(memset_args->env, 1)) { | ||
52 | memset_thread_failed = true; | ||
53 | } else { | ||
54 | + char *addr = memset_args->addr; | ||
55 | + size_t numpages = memset_args->numpages; | ||
56 | + size_t hpagesize = memset_args->hpagesize; | ||
57 | + size_t i; | ||
58 | for (i = 0; i < numpages; i++) { | ||
59 | /* | ||
60 | * Read & write back the same value, so we don't | ||
61 | @@ -XXX,XX +XXX,XX @@ static inline int get_memset_num_threads(int smp_cpus) | ||
62 | static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, | ||
63 | int smp_cpus) | ||
64 | { | ||
65 | - uint64_t numpages_per_thread, size_per_thread; | ||
66 | + size_t numpages_per_thread; | ||
67 | + size_t size_per_thread; | ||
68 | char *addr = area; | ||
69 | int i = 0; | ||
70 | |||
71 | -- | 58 | -- |
72 | 2.13.6 | 59 | 2.40.1 |
73 | 60 | ||
74 | 61 | diff view generated by jsdifflib |