diff options
Diffstat (limited to 'hw/ide/core.c')
-rw-r--r-- | hw/ide/core.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/hw/ide/core.c b/hw/ide/core.c index 27226bfd51..5be72d41dc 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -400,6 +400,7 @@ typedef struct TrimAIOCB { QEMUIOVector *qiov; BlockAIOCB *aiocb; int i, j; + bool is_invalid; } TrimAIOCB; static void trim_aio_cancel(BlockAIOCB *acb) @@ -427,8 +428,11 @@ static void ide_trim_bh_cb(void *opaque) { TrimAIOCB *iocb = opaque; - iocb->common.cb(iocb->common.opaque, iocb->ret); - + if (iocb->is_invalid) { + ide_dma_error(iocb->s); + } else { + iocb->common.cb(iocb->common.opaque, iocb->ret); + } qemu_bh_delete(iocb->bh); iocb->bh = NULL; qemu_aio_unref(iocb); @@ -455,6 +459,11 @@ static void ide_issue_trim_cb(void *opaque, int ret) continue; } + if (!ide_sect_range_ok(s, sector, count)) { + iocb->is_invalid = true; + goto done; + } + /* Got an entry! Submit and exit. */ iocb->aiocb = blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, @@ -470,6 +479,7 @@ static void ide_issue_trim_cb(void *opaque, int ret) iocb->ret = ret; } +done: iocb->aiocb = NULL; if (iocb->bh) { qemu_bh_schedule(iocb->bh); @@ -490,6 +500,7 @@ BlockAIOCB *ide_issue_trim( iocb->qiov = qiov; iocb->i = -1; iocb->j = 0; + iocb->is_invalid = false; ide_issue_trim_cb(iocb, 0); return &iocb->common; } |