Blame SOURCES/kvm-atapi-migration-Throw-recoverable-error-to-avoid-rec.patch

9ae3a8
From e44bfb41173183a85bb6fa94a6f48486ac4ab0a2 Mon Sep 17 00:00:00 2001
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
Date: Tue, 10 Feb 2015 11:45:36 +0100
9ae3a8
Subject: [PATCH 10/16] atapi migration: Throw recoverable error to avoid
9ae3a8
 recovery
9ae3a8
9ae3a8
Message-id: <1423568736-19538-3-git-send-email-dgilbert@redhat.com>
9ae3a8
Patchwork-id: 63779
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH 2/2] atapi migration: Throw recoverable error to avoid recovery
9ae3a8
Bugzilla: 892258
9ae3a8
RH-Acked-by: Juan Quintela <quintela@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: John Snow <jsnow@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
9ae3a8
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
9ae3a8
9ae3a8
(With the previous atapi_dma flag recovery)
9ae3a8
If migration happens between the ATAPI command being written and the
9ae3a8
bmdma being started, the DMA is dropped.  Eventually the guest times
9ae3a8
out and recovers, but that can take many seconds.
9ae3a8
(This is rare, on a pingpong reading the CD continuously I hit
9ae3a8
this about ~1/30-1/50 migrates)
9ae3a8
9ae3a8
I don't think we've got enough state to be able to recover safely
9ae3a8
at this point, so I throw a 'medium error, no seek complete'
9ae3a8
that I'm assuming guests will try and recover from an apparently
9ae3a8
dirty CD.
9ae3a8
9ae3a8
OK, it's a hack, the real solution is probably to push a lot of
9ae3a8
ATAPI state into the migration stream, but this is a fix that
9ae3a8
works with no stream changes. Tested only on Linux (both RHEL5
9ae3a8
(pre-libata) and RHEL7).
9ae3a8
9ae3a8
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
Reviewed-by: John Snow <jsnow@redhat.com>
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit a71754e5b03fd3b8b8c6d3bc2a39f75bead729de)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/ide/atapi.c    | 17 +++++++++++++++++
9ae3a8
 hw/ide/internal.h |  2 ++
9ae3a8
 hw/ide/pci.c      | 11 +++++++++++
9ae3a8
 3 files changed, 30 insertions(+)
9ae3a8
9ae3a8
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
9ae3a8
index 05e60b1..46a2c26 100644
9ae3a8
--- a/hw/ide/atapi.c
9ae3a8
+++ b/hw/ide/atapi.c
9ae3a8
@@ -393,6 +393,23 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
9ae3a8
     }
9ae3a8
 }
9ae3a8
 
9ae3a8
+
9ae3a8
+/* Called by *_restart_bh when the transfer function points
9ae3a8
+ * to ide_atapi_cmd
9ae3a8
+ */
9ae3a8
+void ide_atapi_dma_restart(IDEState *s)
9ae3a8
+{
9ae3a8
+    /*
9ae3a8
+     * I'm not sure we have enough stored to restart the command
9ae3a8
+     * safely, so give the guest an error it should recover from.
9ae3a8
+     * I'm assuming most guests will try to recover from something
9ae3a8
+     * listed as a medium error on a CD; it seems to work on Linux.
9ae3a8
+     * This would be more of a problem if we did any other type of
9ae3a8
+     * DMA operation.
9ae3a8
+     */
9ae3a8
+    ide_atapi_cmd_error(s, MEDIUM_ERROR, ASC_NO_SEEK_COMPLETE);
9ae3a8
+}
9ae3a8
+
9ae3a8
 static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
9ae3a8
                                             uint16_t profile)
9ae3a8
 {
9ae3a8
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
9ae3a8
index 048a052..0a2d6bc 100644
9ae3a8
--- a/hw/ide/internal.h
9ae3a8
+++ b/hw/ide/internal.h
9ae3a8
@@ -289,6 +289,7 @@ typedef struct IDEDMAOps IDEDMAOps;
9ae3a8
 #define ATAPI_INT_REASON_TAG            0xf8
9ae3a8
 
9ae3a8
 /* same constants as bochs */
9ae3a8
+#define ASC_NO_SEEK_COMPLETE                 0x02
9ae3a8
 #define ASC_ILLEGAL_OPCODE                   0x20
9ae3a8
 #define ASC_LOGICAL_BLOCK_OOR                0x21
9ae3a8
 #define ASC_INV_FIELD_IN_CMD_PACKET          0x24
9ae3a8
@@ -536,6 +537,7 @@ void ide_dma_error(IDEState *s);
9ae3a8
 
9ae3a8
 void ide_atapi_cmd_ok(IDEState *s);
9ae3a8
 void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc);
9ae3a8
+void ide_atapi_dma_restart(IDEState *s);
9ae3a8
 void ide_atapi_io_error(IDEState *s, int ret);
9ae3a8
 
9ae3a8
 void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val);
9ae3a8
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
9ae3a8
index 635a364..cf7acb0 100644
9ae3a8
--- a/hw/ide/pci.c
9ae3a8
+++ b/hw/ide/pci.c
9ae3a8
@@ -220,6 +220,17 @@ static void bmdma_restart_bh(void *opaque)
9ae3a8
         }
9ae3a8
     } else if (error_status & BM_STATUS_RETRY_FLUSH) {
9ae3a8
         ide_flush_cache(bmdma_active_if(bm));
9ae3a8
+    } else {
9ae3a8
+        IDEState *s = bmdma_active_if(bm);
9ae3a8
+
9ae3a8
+        /*
9ae3a8
+         * We've not got any bits to tell us about ATAPI - but
9ae3a8
+         * we do have the end_transfer_func that tells us what
9ae3a8
+         * we're trying to do.
9ae3a8
+         */
9ae3a8
+        if (s->end_transfer_func == ide_atapi_cmd) {
9ae3a8
+            ide_atapi_dma_restart(s);
9ae3a8
+        }
9ae3a8
     }
9ae3a8
 }
9ae3a8
 
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8