|
|
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 |
|