Blame SOURCES/kvm-ide-Increment-BB-in-flight-counter-for-TRIM-BH.patch

0727d3
From eaade87072e903cf550dfdb8ed1480dddc6bb0e3 Mon Sep 17 00:00:00 2001
0727d3
From: Hanna Reitz <hreitz@redhat.com>
0727d3
Date: Thu, 20 Jan 2022 15:22:59 +0100
0727d3
Subject: [PATCH 21/24] ide: Increment BB in-flight counter for TRIM BH
0727d3
MIME-Version: 1.0
0727d3
Content-Type: text/plain; charset=UTF-8
0727d3
Content-Transfer-Encoding: 8bit
0727d3
0727d3
RH-Author: Hanna Reitz <hreitz@redhat.com>
0727d3
RH-MergeRequest: 188: ide: Increment BB in-flight counter for TRIM BH
0727d3
RH-Commit: [1/1] 1e702e735ff63f2b8b69c20cac1b309dd085cd62
0727d3
RH-Bugzilla: 2029980
0727d3
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
0727d3
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
0727d3
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
0727d3
0727d3
When we still have an AIOCB registered for DMA operations, we try to
0727d3
settle the respective operation by draining the BlockBackend associated
0727d3
with the IDE device.
0727d3
0727d3
However, this assumes that every DMA operation is associated with an
0727d3
increment of the BlockBackend’s in-flight counter (e.g. through some
0727d3
ongoing I/O operation), so that draining the BB until its in-flight
0727d3
counter reaches 0 will settle all DMA operations.  That is not the case:
0727d3
For TRIM, the guest can issue a zero-length operation that will not
0727d3
result in any I/O operation forwarded to the BlockBackend, and also not
0727d3
increment the in-flight counter in any other way.  In such a case,
0727d3
blk_drain() will be a no-op if no other operations are in flight.
0727d3
0727d3
It is clear that if blk_drain() is a no-op, the value of
0727d3
s->bus->dma->aiocb will not change between checking it in the `if`
0727d3
condition and asserting that it is NULL after blk_drain().
0727d3
0727d3
The particular problem is that ide_issue_trim() creates a BH
0727d3
(ide_trim_bh_cb()) to settle the TRIM request: iocb->common.cb() is
0727d3
ide_dma_cb(), which will either create a new request, or find the
0727d3
transfer to be done and call ide_set_inactive(), which clears
0727d3
s->bus->dma->aiocb.  Therefore, the blk_drain() must wait for
0727d3
ide_trim_bh_cb() to run, which currently it will not always do.
0727d3
0727d3
To fix this issue, we increment the BlockBackend's in-flight counter
0727d3
when the TRIM operation begins (in ide_issue_trim(), when the
0727d3
ide_trim_bh_cb() BH is created) and decrement it when ide_trim_bh_cb()
0727d3
is done.
0727d3
0727d3
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2029980
0727d3
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
0727d3
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
0727d3
Message-Id: <20220120142259.120189-1-hreitz@redhat.com>
0727d3
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
0727d3
Reviewed-by: John Snow <jsnow@redhat.com>
0727d3
Tested-by: John Snow <jsnow@redhat.com>
0727d3
(cherry picked from commit 7e5cdb345f77d76cb4877fe6230c4e17a7d0d0ca)
0727d3
Signed-off-by: Hanna Reitz <hreitz@redhat.com>
0727d3
---
0727d3
 hw/ide/core.c | 7 +++++++
0727d3
 1 file changed, 7 insertions(+)
0727d3
0727d3
diff --git a/hw/ide/core.c b/hw/ide/core.c
0727d3
index e28f8aad61..15138225be 100644
0727d3
--- a/hw/ide/core.c
0727d3
+++ b/hw/ide/core.c
0727d3
@@ -433,12 +433,16 @@ static const AIOCBInfo trim_aiocb_info = {
0727d3
 static void ide_trim_bh_cb(void *opaque)
0727d3
 {
0727d3
     TrimAIOCB *iocb = opaque;
0727d3
+    BlockBackend *blk = iocb->s->blk;
0727d3
 
0727d3
     iocb->common.cb(iocb->common.opaque, iocb->ret);
0727d3
 
0727d3
     qemu_bh_delete(iocb->bh);
0727d3
     iocb->bh = NULL;
0727d3
     qemu_aio_unref(iocb);
0727d3
+
0727d3
+    /* Paired with an increment in ide_issue_trim() */
0727d3
+    blk_dec_in_flight(blk);
0727d3
 }
0727d3
 
0727d3
 static void ide_issue_trim_cb(void *opaque, int ret)
0727d3
@@ -508,6 +512,9 @@ BlockAIOCB *ide_issue_trim(
0727d3
     IDEState *s = opaque;
0727d3
     TrimAIOCB *iocb;
0727d3
 
0727d3
+    /* Paired with a decrement in ide_trim_bh_cb() */
0727d3
+    blk_inc_in_flight(s->blk);
0727d3
+
0727d3
     iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque);
0727d3
     iocb->s = s;
0727d3
     iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb);
0727d3
-- 
0727d3
2.35.3
0727d3