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 <[email protected]> Message-ID: <[email protected]> Signed-off-by: Kevin Wolf <[email protected]> --- hw/ide/core.c | 87 +++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 48 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 48359c934c1..f78b00220b8 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); -- 2.54.0
