From aed5e907c7e325b24f48c9c9fe31a3d7e995d20f Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Paolo Bonzini Date: Mon, 27 Aug 2012 13:42:08 +0200 Subject: [PATCH 05/10] scsi: add support for FUA on writes RH-Author: Paolo Bonzini Message-id: <1346074931-12083-5-git-send-email-pbonzini@redhat.com> Patchwork-id: 41328 O-Subject: [RHEL 6.4 qemu-kvm PATCH 4/7] scsi: add support for FUA on writes Bugzilla: 814084 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Markus Armbruster RH-Acked-by: Orit Wasserman Bugzilla: 814084 To force unit access, add a flush operation after the actual write. WRITE AND VERIFY commands always flush according to SBC, so do it even though we do not perform the reread. Signed-off-by: Paolo Bonzini (cherry picked from commit 7e8c49c56154ab5c45d4f07edf0c22728735da35) --- hw/scsi-disk.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file modificato, 47 inserzioni(+), 2 rimozioni(-) Signed-off-by: Michal Novotny --- hw/scsi-disk.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 05ee81a..69e511a 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -171,6 +171,45 @@ done: } } +static bool scsi_is_cmd_fua(SCSICommand *cmd) +{ + switch (cmd->buf[0]) { + case READ_10: + case READ_12: + case READ_16: + case WRITE_10: + case WRITE_12: + case WRITE_16: + return (cmd->buf[1] & 8) != 0; + + case WRITE_VERIFY_10: + case WRITE_VERIFY_12: + case WRITE_VERIFY_16: + return true; + + case READ_6: + case WRITE_6: + default: + return false; + } +} + +static void scsi_write_do_fua(SCSIDiskReq *r) +{ + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + + if (scsi_is_cmd_fua(&r->req.cmd)) { + bdrv_acct_start(s->qdev.conf.bs, &r->acct, 0, BDRV_ACCT_FLUSH); + r->req.aiocb = bdrv_aio_flush(s->qdev.conf.bs, scsi_flush_complete, r); + return; + } + + scsi_req_complete(&r->req, GOOD); + if (!r->req.io_canceled) { + scsi_req_unref(&r->req); + } +} + static void scsi_dma_complete(void *opaque, int ret) { SCSIDiskReq *r = (SCSIDiskReq *)opaque; @@ -186,7 +225,12 @@ static void scsi_dma_complete(void *opaque, int ret) r->sector += r->sector_count; r->sector_count = 0; - scsi_req_complete(&r->req, GOOD); + if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { + scsi_write_do_fua(r); + return; + } else { + scsi_req_complete(&r->req, GOOD); + } done: if (!r->req.io_canceled) { @@ -342,7 +386,8 @@ static void scsi_write_complete(void * opaque, int ret) r->sector += n; r->sector_count -= n; if (r->sector_count == 0) { - scsi_req_complete(&r->req, GOOD); + scsi_write_do_fua(r); + return; } else { scsi_init_iovec(r, SCSI_DMA_BUF_SIZE); DPRINTF("Write complete tag=0x%x more=%d\n", r->req.tag, r->qiov.size); -- 1.7.11.4