@samitouri / QOSamiQemu / commits / c1c71a7e16

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>

Kevin Wolf committed Apr 21, 2026 at 18:11 UTC c1c71a7e167fdabaa9827d00c0be3aeafebdd921
1 file changed +39 -48
hw/ide/core.c
+39 -48
@@ -420,18 +420,15 @@ typedef struct TrimAIOCB {
420 QEMUBH *bh;
421 int ret;
422 QEMUIOVector *qiov;
423 - int i, j;
423 + bool canceled;
424 } TrimAIOCB;
425
426 static void trim_aio_cancel(BlockAIOCB *acb)
427 {
428 TrimAIOCB *iocb = container_of(acb, TrimAIOCB, common);
429
430 - /* Exit the loop so ide_issue_trim_cb will not continue */
431 - iocb->j = iocb->qiov->niov - 1;
432 - iocb->i = (iocb->qiov->iov[iocb->j].iov_len / 8) - 1;
433 -
434 - iocb->ret = -ECANCELED;
430 + /* Exit the loop so ide_trim_co_entry will not continue */
431 + iocb->canceled = true;
432 }
433
434 static const AIOCBInfo trim_aiocb_info = {
@@ -458,60 +455,55 @@ static void coroutine_fn ide_trim_co_entry(void *opaque)
455 {
456 TrimAIOCB *iocb = opaque;
457 IDEState *s = iocb->s;
461 - int ret = 0;
458 + int i, j;
459 + int ret;
460
461 /* Paired with blk_end_request in ide_trim_bh_cb() */
462 blk_co_start_request(s->blk);
463
466 -loop:
467 - if (iocb->i >= 0) {
468 - if (ret >= 0) {
469 - block_acct_done(blk_get_stats(s->blk), &s->acct);
470 - } else {
471 - block_acct_failed(blk_get_stats(s->blk), &s->acct);
472 - }
473 - }
464 + for (j = 0; j < iocb->qiov->niov; j++) {
465 + for (i = 0; i < iocb->qiov->iov[j].iov_len / 8; i++) {
466 + uint64_t *buffer = iocb->qiov->iov[j].iov_base;
467
475 - if (ret >= 0) {
476 - while (iocb->j < iocb->qiov->niov) {
477 - int j = iocb->j;
478 - while (++iocb->i < iocb->qiov->iov[j].iov_len / 8) {
479 - int i = iocb->i;
480 - uint64_t *buffer = iocb->qiov->iov[j].iov_base;
468 + /* 6-byte LBA + 2-byte range per entry */
469 + uint64_t entry = le64_to_cpu(buffer[i]);
470 + uint64_t sector = entry & 0x0000ffffffffffffULL;
471 + uint16_t count = entry >> 48;
472
482 - /* 6-byte LBA + 2-byte range per entry */
483 - uint64_t entry = le64_to_cpu(buffer[i]);
484 - uint64_t sector = entry & 0x0000ffffffffffffULL;
485 - uint16_t count = entry >> 48;
473 + if (count == 0) {
474 + continue;
475 + }
476
487 - if (count == 0) {
488 - continue;
489 - }
477 + if (iocb->canceled) {
478 + iocb->ret = -ECANCELED;
479 + goto done;
480 + }
481
491 - if (!ide_sect_range_ok(s, sector, count)) {
492 - block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
493 - iocb->ret = -EINVAL;
494 - goto done;
495 - }
482 + if (!ide_sect_range_ok(s, sector, count)) {
483 + block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_UNMAP);
484 + iocb->ret = -EINVAL;
485 + goto done;
486 + }
487
497 - block_acct_start(blk_get_stats(s->blk), &s->acct,
498 - count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
488 + block_acct_start(blk_get_stats(s->blk), &s->acct,
489 + count << BDRV_SECTOR_BITS, BLOCK_ACCT_UNMAP);
490
500 - /* Got an entry! Submit and exit. */
501 - ret = blk_co_pdiscard(s->blk,
502 - sector << BDRV_SECTOR_BITS,
503 - count << BDRV_SECTOR_BITS,
504 - BDRV_REQ_NO_QUEUE);
505 - goto loop;
491 + /* Got an entry! Submit and exit. */
492 + ret = blk_co_pdiscard(s->blk,
493 + sector << BDRV_SECTOR_BITS,
494 + count << BDRV_SECTOR_BITS,
495 + BDRV_REQ_NO_QUEUE);
496 + if (ret >= 0) {
497 + block_acct_done(blk_get_stats(s->blk), &s->acct);
498 + } else {
499 + iocb->ret = ret;
500 + block_acct_failed(blk_get_stats(s->blk), &s->acct);
501 + goto done;
502 }
507 -
508 - iocb->j++;
509 - iocb->i = -1;
503 }
511 - } else {
512 - iocb->ret = ret;
504 }
505
506 + iocb->ret = 0;
507 done:
508 if (iocb->bh) {
509 replay_bh_schedule_event(iocb->bh);
@@ -533,8 +525,7 @@ BlockAIOCB *ide_issue_trim(
525 &DEVICE(dev)->mem_reentrancy_guard);
526 iocb->ret = 0;
527 iocb->qiov = qiov;
536 - iocb->i = -1;
537 - iocb->j = 0;
528 + iocb->canceled = false;
529
530 co = qemu_coroutine_create(ide_trim_co_entry, iocb);
531 aio_co_enter(qemu_get_current_aio_context(), co);