aboutsummaryrefslogtreecommitdiff
path: root/hw/ide/core.c
diff options
context:
space:
mode:
authorKevin Wolf <kwolf@redhat.com>2010-10-18 17:13:05 +0200
committerKevin Wolf <kwolf@redhat.com>2010-10-22 14:49:35 +0200
commite2bcadadc35673223c1445152445d0c9b6887b9e (patch)
tree3fcc3dd3ada74393b30c57fa7bd236fb22dd1a20 /hw/ide/core.c
parent6bcb1a79a31563f2c414e1bd35d044d6ab385011 (diff)
ide: Handle flush failure
Instead of always assuming success for bdrv_aio_flush, actually do something with the error. This respects the werror option and accordingly ignores the error, reports it to the guest or stops the VM and retries after cont. Ignoring the error is trivial, obviously. For stopping the VM and retrying later old code can be reused, but we need to introduce a new status for "retry a flush". For reporting to the guest, fortunately the same action is required as for a failed read/write (status = DRDY | ERR, error = ABRT), so this code can be reused as well. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/ide/core.c')
-rw-r--r--hw/ide/core.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 6d8606e897..bc3e91658a 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -65,6 +65,7 @@ static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
static void ide_dma_restart(IDEState *s, int is_read);
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
static int ide_handle_rw_error(IDEState *s, int error, int op);
+static void ide_flush_cache(IDEState *s);
static void padstr(char *str, const char *src, int len)
{
@@ -688,6 +689,8 @@ static void ide_dma_restart_bh(void *opaque)
} else {
ide_sector_write(bmdma_active_if(bm));
}
+ } else if (bm->status & BM_STATUS_RETRY_FLUSH) {
+ ide_flush_cache(bmdma_active_if(bm));
}
}
@@ -795,7 +798,12 @@ static void ide_flush_cb(void *opaque, int ret)
{
IDEState *s = opaque;
- /* XXX: how do we signal I/O errors here? */
+ if (ret < 0) {
+ /* XXX: What sector number to set here? */
+ if (ide_handle_rw_error(s, -ret, BM_STATUS_RETRY_FLUSH)) {
+ return;
+ }
+ }
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s->bus);