From ef0e64a9838c0a20b5cb8a0bd2dcbcc59b0b812d Mon Sep 17 00:00:00 2001 From: Anton Nefedov Date: Fri, 8 Dec 2017 15:10:32 +0300 Subject: [PATCH 1/4] ide: pass IDEState to trim AIO callback It will be needed to handle invalid requests Signed-off-by: Anton Nefedov Message-id: 1512735034-35327-2-git-send-email-anton.nefedov@virtuozzo.com Signed-off-by: John Snow --- hw/ide/core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 1ea5812b7e..875f7b442d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -382,7 +382,7 @@ static void ide_set_signature(IDEState *s) typedef struct TrimAIOCB { BlockAIOCB common; - BlockBackend *blk; + IDEState *s; QEMUBH *bh; int ret; QEMUIOVector *qiov; @@ -425,6 +425,8 @@ static void ide_trim_bh_cb(void *opaque) static void ide_issue_trim_cb(void *opaque, int ret) { TrimAIOCB *iocb = opaque; + IDEState *s = iocb->s; + if (ret >= 0) { while (iocb->j < iocb->qiov->niov) { int j = iocb->j; @@ -442,7 +444,7 @@ static void ide_issue_trim_cb(void *opaque, int ret) } /* Got an entry! Submit and exit. */ - iocb->aiocb = blk_aio_pdiscard(iocb->blk, + iocb->aiocb = blk_aio_pdiscard(s->blk, sector << BDRV_SECTOR_BITS, count << BDRV_SECTOR_BITS, ide_issue_trim_cb, opaque); @@ -466,11 +468,11 @@ BlockAIOCB *ide_issue_trim( int64_t offset, QEMUIOVector *qiov, BlockCompletionFunc *cb, void *cb_opaque, void *opaque) { - BlockBackend *blk = opaque; + IDEState *s = opaque; TrimAIOCB *iocb; - iocb = blk_aio_get(&trim_aiocb_info, blk, cb, cb_opaque); - iocb->blk = blk; + iocb = blk_aio_get(&trim_aiocb_info, s->blk, cb, cb_opaque); + iocb->s = s; iocb->bh = qemu_bh_new(ide_trim_bh_cb, iocb); iocb->ret = 0; iocb->qiov = qiov; @@ -900,7 +902,7 @@ static void ide_dma_cb(void *opaque, int ret) case IDE_DMA_TRIM: s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk), &s->sg, offset, BDRV_SECTOR_SIZE, - ide_issue_trim, s->blk, ide_dma_cb, s, + ide_issue_trim, s, ide_dma_cb, s, DMA_DIRECTION_TO_DEVICE); break; default: From d8b070fed2e94b3747a74a28709d0300404c0d05 Mon Sep 17 00:00:00 2001 From: Anton Nefedov Date: Fri, 8 Dec 2017 15:10:33 +0300 Subject: [PATCH 2/4] ide: move ide_sect_range_ok() up to use it without a forward declaration in the commit to follow Signed-off-by: Anton Nefedov Message-id: 1512735034-35327-3-git-send-email-anton.nefedov@virtuozzo.com Signed-off-by: John Snow --- hw/ide/core.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index 875f7b442d..27226bfd51 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -380,6 +380,18 @@ static void ide_set_signature(IDEState *s) } } +static bool ide_sect_range_ok(IDEState *s, + uint64_t sector, uint64_t nb_sectors) +{ + uint64_t total_sectors; + + blk_get_geometry(s->blk, &total_sectors); + if (sector > total_sectors || nb_sectors > total_sectors - sector) { + return false; + } + return true; +} + typedef struct TrimAIOCB { BlockAIOCB common; IDEState *s; @@ -603,18 +615,6 @@ static void ide_rw_error(IDEState *s) { ide_set_irq(s->bus); } -static bool ide_sect_range_ok(IDEState *s, - uint64_t sector, uint64_t nb_sectors) -{ - uint64_t total_sectors; - - blk_get_geometry(s->blk, &total_sectors); - if (sector > total_sectors || nb_sectors > total_sectors - sector) { - return false; - } - return true; -} - static void ide_buffered_readv_cb(void *opaque, int ret) { IDEBufferedRequest *req = opaque; From 947858b0ba97f4ec097de667e45eff99212867c3 Mon Sep 17 00:00:00 2001 From: Anton Nefedov Date: Fri, 8 Dec 2017 15:10:34 +0300 Subject: [PATCH 3/4] ide: abort TRIM operation for invalid range ATA8-ACS3, 7.9 DATA SET MANAGEMENT - 06h, DMA 7.9.5 Error Outputs If the Trim bit is set to one and: a) the device detects an invalid LBA Range Entry; or b) count is greater than IDENTIFY DEVICE data word 105 (see 7.16.7.55), then the device shall return command aborted. A device may trim one or more LBA Range Entries before it returns command aborted. See table 209. This check is not in the common ide_dma_cb() as the range for TRIM is harder to reach: it is not in LBA/count registers and the buffer has to be parsed first. Signed-off-by: Anton Nefedov Message-id: 1512735034-35327-4-git-send-email-anton.nefedov@virtuozzo.com Signed-off-by: John Snow --- hw/ide/core.c | 15 +++++++++++++-- 1 file 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; } From 3161906df88a471b09c38fff9a618ff83beea0c3 Mon Sep 17 00:00:00 2001 From: John Snow Date: Fri, 8 Dec 2017 15:04:02 -0500 Subject: [PATCH 4/4] hw/ide: Remove duplicated definitions from ahci_internal.h The same definitions can also be found in include/hw/ide/ahci.h so let's remove these #defines from ahci_internal.h. Signed-off-by: Thomas Huth Message-id: 1512457825-3847-1-git-send-email-thuth@redhat.com [Maintainer edit: publicize object names, privatize object macros.] Signed-off-by: John Snow --- hw/ide/ahci_internal.h | 4 ---- include/hw/ide/ahci.h | 6 ------ 2 files changed, 10 deletions(-) diff --git a/hw/ide/ahci_internal.h b/hw/ide/ahci_internal.h index ce2e818c8c..8c755d4ca1 100644 --- a/hw/ide/ahci_internal.h +++ b/hw/ide/ahci_internal.h @@ -311,8 +311,6 @@ struct AHCIPCIState { AHCIState ahci; }; -#define TYPE_ICH9_AHCI "ich9-ahci" - #define ICH_AHCI(obj) \ OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) @@ -375,10 +373,8 @@ void ahci_uninit(AHCIState *s); void ahci_reset(AHCIState *s); -#define TYPE_SYSBUS_AHCI "sysbus-ahci" #define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) -#define TYPE_ALLWINNER_AHCI "allwinner-ahci" #define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ TYPE_ALLWINNER_AHCI) diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h index 5a06537e6b..b7bb2b02d6 100644 --- a/include/hw/ide/ahci.h +++ b/include/hw/ide/ahci.h @@ -54,14 +54,10 @@ typedef struct AHCIPCIState AHCIPCIState; #define TYPE_ICH9_AHCI "ich9-ahci" -#define ICH_AHCI(obj) \ - OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) - int32_t ahci_get_num_ports(PCIDevice *dev); void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); #define TYPE_SYSBUS_AHCI "sysbus-ahci" -#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) typedef struct SysbusAHCIState { /*< private >*/ @@ -73,8 +69,6 @@ typedef struct SysbusAHCIState { } SysbusAHCIState; #define TYPE_ALLWINNER_AHCI "allwinner-ahci" -#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ - TYPE_ALLWINNER_AHCI) #define ALLWINNER_AHCI_MMIO_OFF 0x80 #define ALLWINNER_AHCI_MMIO_SIZE 0x80