From 3bd0ed364f053a889b5914917369bd93637cc592 Mon Sep 17 00:00:00 2001 From: Kevin Wolf <kwolf@redhat.com> Date: Tue, 24 Nov 2009 19:43:07 -0200 Subject: [PATCH 07/11] ide: Stop VM on read errors RH-Author: Kevin Wolf <kwolf@redhat.com> Message-id: <1258367498-9527-3-git-send-email-kwolf@redhat.com> Patchwork-id: 3723 O-Subject: [RHEL-5.5 KVM PATCH v2 2/2] ide: Stop VM on read errors Bugzilla: 531827 533390 RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Gleb Natapov <gleb@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> Bugzilla: 531827 Upstream status: Needs to be solved differently (changes semantics of werror) The VM should not only be stopped on write errors but also on read errors as they can confuse the guest as well (e.g. remounting the root file system read-only during a host NFS outage when the disk image is on NFS). Signed-off-by: Kevin Wolf <kwolf@redhat.com> --- qemu/hw/ide.c | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 36 insertions(+), 15 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/hw/ide.c | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 36 insertions(+), 15 deletions(-) diff --git a/qemu/hw/ide.c b/qemu/hw/ide.c index 4f98428..abc6b10 100644 --- a/qemu/hw/ide.c +++ b/qemu/hw/ide.c @@ -463,6 +463,7 @@ static inline int media_is_cd(IDEState *s) #define BM_STATUS_INT 0x04 #define BM_STATUS_DMA_RETRY 0x08 #define BM_STATUS_PIO_RETRY 0x10 +#define BM_STATUS_RETRY_READ 0x20 #define BM_CMD_START 0x01 #define BM_CMD_READ 0x08 @@ -507,8 +508,9 @@ typedef struct PCIIDEState { } PCIIDEState; static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb); -static void ide_dma_restart(IDEState *s); +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 padstr(char *str, const char *src, int len) { @@ -857,8 +859,11 @@ static void ide_sector_read(IDEState *s) n = s->req_nb_sectors; ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); if (ret != 0) { - ide_rw_error(s); - return; + if (ide_handle_rw_error(s, -ret, + BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ)) + { + return; + } } ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); ide_set_irq(s); @@ -875,7 +880,7 @@ static void ide_dma_error(IDEState *s) ide_set_irq(s); } -static int ide_handle_write_error(IDEState *s, int error, int op) +static int ide_handle_rw_error(IDEState *s, int error, int op) { BlockInterfaceErrorAction action = drive_get_onerror(s->bs); @@ -892,7 +897,7 @@ static int ide_handle_write_error(IDEState *s, int error, int op) bdrv_get_device_name(s->bs), strerror(error)); term_printf_async(VMSTOP_ASYNC_EVENT, "%s\n", vm_stop_reason); } else { - if (op == BM_STATUS_DMA_RETRY) + if (op & BM_STATUS_DMA_RETRY) ide_dma_error(s); else ide_rw_error(s); @@ -957,8 +962,11 @@ static void ide_read_dma_cb(void *opaque, int ret) int64_t sector_num; if (ret < 0) { - ide_dma_error(s); - return; + if (ide_handle_rw_error(s, -ret, + BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ)) + { + return; + } } n = s->io_buffer_size >> 9; @@ -1028,7 +1036,7 @@ static void ide_sector_write(IDEState *s) ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); if (ret != 0) { - if (ide_handle_write_error(s, -ret, BM_STATUS_PIO_RETRY)) + if (ide_handle_rw_error(s, -ret, BM_STATUS_PIO_RETRY)) return; } @@ -1064,16 +1072,23 @@ static void ide_sector_write(IDEState *s) static void ide_dma_restart_bh(void *opaque) { BMDMAState *bm = opaque; + int is_read; qemu_bh_delete(bm->bh); bm->bh = NULL; + is_read = !!(bm->status & BM_STATUS_RETRY_READ); + if (bm->status & BM_STATUS_DMA_RETRY) { - bm->status &= ~BM_STATUS_DMA_RETRY; - ide_dma_restart(bm->ide_if); + bm->status &= ~(BM_STATUS_DMA_RETRY | BM_STATUS_RETRY_READ); + ide_dma_restart(bm->ide_if, is_read); } else if (bm->status & BM_STATUS_PIO_RETRY) { - bm->status &= ~BM_STATUS_PIO_RETRY; - ide_sector_write(bm->ide_if); + bm->status &= ~(BM_STATUS_PIO_RETRY | BM_STATUS_RETRY_READ); + if (is_read) { + ide_sector_read(bm->ide_if); + } else { + ide_sector_write(bm->ide_if); + } } } @@ -1098,7 +1113,7 @@ static void ide_write_dma_cb(void *opaque, int ret) int64_t sector_num; if (ret < 0) { - if (ide_handle_write_error(s, -ret, BM_STATUS_DMA_RETRY)) + if (ide_handle_rw_error(s, -ret, BM_STATUS_DMA_RETRY)) return; } @@ -2942,7 +2957,7 @@ static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb) } } -static void ide_dma_restart(IDEState *s) +static void ide_dma_restart(IDEState *s, int is_read) { BMDMAState *bm = s->bmdma; ide_set_sector(s, bm->sector_num); @@ -2950,7 +2965,13 @@ static void ide_dma_restart(IDEState *s) s->io_buffer_size = 0; s->nsector = bm->nsector; bm->cur_addr = bm->addr; - bm->dma_cb = ide_write_dma_cb; + + if (is_read) { + bm->dma_cb = ide_read_dma_cb; + } else { + bm->dma_cb = ide_write_dma_cb; + } + ide_dma_start(s, bm->dma_cb); } -- 1.6.3.rc4.29.g8146