]> git.proxmox.com Git - pve-qemu.git/blob - debian/patches/extra/0011-ide-avoid-potential-deadlock-when-draining-during-tr.patch
add patch to avoid potential deadlock with trim for IDE/SATA and draining
[pve-qemu.git] / debian / patches / extra / 0011-ide-avoid-potential-deadlock-when-draining-during-tr.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Fiona Ebner <f.ebner@proxmox.com>
3 Date: Tue, 7 Mar 2023 15:03:02 +0100
4 Subject: [PATCH] ide: avoid potential deadlock when draining during trim
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 The deadlock can happen as follows:
10 1. ide_issue_trim is called, and increments the in_flight counter.
11 2. ide_issue_trim_cb calls blk_aio_pdiscard.
12 3. Somebody else starts draining (e.g. backup to insert the cbw node).
13 4. ide_issue_trim_cb is called as the completion callback for
14 blk_aio_pdiscard.
15 5. ide_issue_trim_cb issues yet another blk_aio_pdiscard request.
16 6. The request is added to the wait queue via blk_wait_while_drained,
17 because draining has been started.
18 7. Nobody ever decrements the in_flight counter and draining can't
19 finish. This would be done by ide_trim_bh_cb, which is called after
20 ide_issue_trim_cb has issued its last request, but
21 ide_issue_trim_cb is not called anymore, because it's the
22 completion callback of blk_aio_pdiscard, which waits on draining.
23
24 Quoting Hanna Czenczek:
25 > The point of 7e5cdb345f was that we need any in-flight count to
26 > accompany a set s->bus->dma->aiocb. While blk_aio_pdiscard() is
27 > happening, we don’t necessarily need another count. But we do need
28 > it while there is no blk_aio_pdiscard().
29 > ide_issue_trim_cb() returns in two cases (and, recursively through
30 > its callers, leaves s->bus->dma->aiocb set):
31 > 1. After calling blk_aio_pdiscard(), which will keep an in-flight
32 > count,
33 > 2. After calling replay_bh_schedule_event() (i.e.
34 > qemu_bh_schedule()), which does not keep an in-flight count.
35
36 Thus, even after moving the blk_inc_in_flight to above the
37 replay_bh_schedule_event call, the invariant "ide_issue_trim_cb
38 returns with an accompanying in-flight count" is still satisfied.
39
40 Fixes: 7e5cdb345f ("ide: Increment BB in-flight counter for TRIM BH")
41 Suggested-by: Hanna Czenczek <hreitz@redhat.com>
42 Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
43 ---
44 hw/ide/core.c | 7 +++----
45 1 file changed, 3 insertions(+), 4 deletions(-)
46
47 diff --git a/hw/ide/core.c b/hw/ide/core.c
48 index 39afdc0006..6474522bc9 100644
49 --- a/hw/ide/core.c
50 +++ b/hw/ide/core.c
51 @@ -443,7 +443,7 @@ static void ide_trim_bh_cb(void *opaque)
52 iocb->bh = NULL;
53 qemu_aio_unref(iocb);
54
55 - /* Paired with an increment in ide_issue_trim() */
56 + /* Paired with an increment in ide_issue_trim_cb() */
57 blk_dec_in_flight(blk);
58 }
59
60 @@ -503,6 +503,8 @@ static void ide_issue_trim_cb(void *opaque, int ret)
61 done:
62 iocb->aiocb = NULL;
63 if (iocb->bh) {
64 + /* Paired with a decrement in ide_trim_bh_cb() */
65 + blk_inc_in_flight(s->blk);
66 replay_bh_schedule_event(iocb->bh);
67 }
68 }
69 @@ -514,9 +516,6 @@ BlockAIOCB *ide_issue_trim(
70 IDEState *s = opaque;
71 TrimAIOCB *iocb;
72
73 - /* Paired with a decrement in ide_trim_bh_cb() */
74 - blk_inc_in_flight(s->blk);
75 -
76 iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
77 iocb->s = s;
78 iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);