Commit c1c71a7e16 for qemu.org
commit c1c71a7e167fdabaa9827d00c0be3aeafebdd921
Author: Kevin Wolf <kwolf@redhat.com>
Date: Tue Apr 21 18:11:30 2026 +0200
ide: Clean up ide_trim_co_entry() to be idiomatic coroutine code
The previous commit did a minimal conversion of the callback based state
machine for TRIM to a coroutine in order to fix a bug. Refactor it to
actually look like normal coroutine based code, which improves its
readability.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20260421161132.99878-6-kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 48359c934c..f78b00220b 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -420,18 +420,15 @@ typedef struct TrimAIOCB {
QEMUBH *bh;
int ret;
QEMUIOVector *qiov;
- int i, j;
+ bool canceled;
} TrimAIOCB;
static void trim_aio_cancel(BlockAIOCB *acb)
{
TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
- /* Exit the loop so ide_issue_trim_cb will not continue */
- iocb->j = iocb->qiov->niov - 1;
- iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
-
- iocb->ret = -ECANCELED;
+ /* Exit the loop so ide_trim_co_entry will not continue */
+ iocb->canceled = true;
}
static const AIOCBInfo trim_aiocb_info = {
@@ -458,60 +455,55 @@ static void coroutine_fn ide_trim_co_entry(void *opaque)
{
TrimAIOCB *iocb = opaque;
IDEState *s = iocb->s;
- int ret = 0;
+ int i, j;
+ int ret;
/* Paired with blk_end_request in ide_trim_bh_cb() */
blk_co_start_request(s->blk);
-loop:
- if (iocb->i >= 0) {
- if (ret >= 0) {
- block_acct_done(blk_get_stats(s->blk), &s->acct);
- } else {
- block_acct_failed(blk_get_stats(s->blk), &s->acct);
- }
- }
+ for (j = 0; j < iocb->qiov->niov; j++) {
+ for (i = 0; i < iocb->qiov->iov[j].iov_len / 8; i++) {
+ uint64_t *buffer = iocb->qiov->iov[j].iov_base;
- if (ret >= 0) {
- while (iocb->j < iocb->qiov->niov) {
- int j = iocb->j;
- while (++iocb->i < iocb->qiov->iov[j].iov_len / 8) {
- int i = iocb->i;
- uint64_t *buffer = iocb->qiov->iov[j].iov_base;
+ /* 6-byte LBA + 2-byte range per entry */
+ uint64_t entry = le64_to_cpu(buffer[i]);
+ uint64_t sector = entry & 0x0000ffffffffffffULL;
+ uint16_t count = entry >> 48;
- /* 6-byte LBA + 2-byte range per entry */
- uint64_t entry = le64_to_cpu(buffer[i]);
- uint64_t sector = entry & 0x0000ffffffffffffULL;
- uint16_t count = entry >> 48;
+ if (count == 0) {
+ continue;
+ }
- if (count == 0) {
- continue;
- }
+ if (iocb->canceled) {
+ iocb->ret = -ECANCELED;
+ goto done;
+ }
- if (!ide_sect_range_ok(s, sector, count)) {
- block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
- iocb->ret = -EINVAL;
- goto done;
- }
+ if (!ide_sect_range_ok(s, sector, count)) {
+ block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
+ iocb->ret = -EINVAL;
+ goto done;
+ }
- block_acct_start(blk_get_stats(s->blk), &s->acct,
- count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
+ block_acct_start(blk_get_stats(s->blk), &s->acct,
+ count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
- /* Got an entry! Submit and exit. */
- ret = blk_co_pdiscard(s->blk,
- sector << BDRV_SECTOR_BITS,
- count << BDRV_SECTOR_BITS,
- BDRV_REQ_NO_QUEUE);
- goto loop;
+ /* Got an entry! Submit and exit. */
+ ret = blk_co_pdiscard(s->blk,
+ sector << BDRV_SECTOR_BITS,
+ count << BDRV_SECTOR_BITS,
+ BDRV_REQ_NO_QUEUE);
+ if (ret >= 0) {
+ block_acct_done(blk_get_stats(s->blk), &s->acct);
+ } else {
+ iocb->ret = ret;
+ block_acct_failed(blk_get_stats(s->blk), &s->acct);
+ goto done;
}
-
- iocb->j++;
- iocb->i = -1;
}
- } else {
- iocb->ret = ret;
}
+ iocb->ret = 0;
done:
if (iocb->bh) {
replay_bh_schedule_event(iocb->bh);
@@ -533,8 +525,7 @@ BlockAIOCB *ide_issue_trim(
&DEVICE(dev)->mem_reentrancy_guard);
iocb->ret = 0;
iocb->qiov = qiov;
- iocb->i = -1;
- iocb->j = 0;
+ iocb->canceled = false;
co = qemu_coroutine_create(ide_trim_co_entry, iocb);
aio_co_enter(qemu_get_current_aio_context(), co);