From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [6388] Stop VM on ENOSPC error.
Date: Wed, 21 Jan 2009 18:59:05 +0000 [thread overview]
Message-ID: <E1LPiI5-0004LB-5o@cvs.savannah.gnu.org> (raw)
Revision: 6388
http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6388
Author: aliguori
Date: 2009-01-21 18:59:04 +0000 (Wed, 21 Jan 2009)
Log Message:
-----------
Stop VM on ENOSPC error. (Gleb Natapov)
This version of the patch adds new option "werror" to -drive flag.
Possible values are:
report - report errors to a guest as IO errors
ignore - continue as if nothing happened
stop - stop VM on any error and retry last command on resume
enospc - stop vm on ENOSPC error and retry last command on resume
all other errors are reported to a guest.
Default is "report" to maintain current behaviour.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Modified Paths:
--------------
trunk/hw/ide.c
trunk/sysemu.h
trunk/vl.c
Modified: trunk/hw/ide.c
===================================================================
--- trunk/hw/ide.c 2009-01-21 18:58:51 UTC (rev 6387)
+++ trunk/hw/ide.c 2009-01-21 18:59:04 UTC (rev 6388)
@@ -457,6 +457,8 @@
#define BM_STATUS_DMAING 0x01
#define BM_STATUS_ERROR 0x02
#define BM_STATUS_INT 0x04
+#define BM_STATUS_DMA_RETRY 0x08
+#define BM_STATUS_PIO_RETRY 0x10
#define BM_CMD_START 0x01
#define BM_CMD_READ 0x08
@@ -488,6 +490,8 @@
IDEState *ide_if;
BlockDriverCompletionFunc *dma_cb;
BlockDriverAIOCB *aiocb;
+ int64_t sector_num;
+ uint32_t nsector;
} BMDMAState;
typedef struct PCIIDEState {
@@ -498,6 +502,7 @@
} PCIIDEState;
static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
+static void ide_dma_restart(IDEState *s);
static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
static void padstr(char *str, const char *src, int len)
@@ -865,6 +870,28 @@
ide_set_irq(s);
}
+static int ide_handle_write_error(IDEState *s, int error, int op)
+{
+ BlockInterfaceErrorAction action = drive_get_onerror(s->bs);
+
+ if (action == BLOCK_ERR_IGNORE)
+ return 0;
+
+ if ((error == ENOSPC && action == BLOCK_ERR_STOP_ENOSPC)
+ || action == BLOCK_ERR_STOP_ANY) {
+ s->bmdma->ide_if = s;
+ s->bmdma->status |= op;
+ vm_stop(0);
+ } else {
+ if (op == BM_STATUS_DMA_RETRY)
+ ide_dma_error(s);
+ else
+ ide_rw_error(s);
+ }
+
+ return 1;
+}
+
/* return 0 if buffer completed */
static int dma_buf_rw(BMDMAState *bm, int is_write)
{
@@ -990,9 +1017,10 @@
if (n > s->req_nb_sectors)
n = s->req_nb_sectors;
ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+
if (ret != 0) {
- ide_rw_error(s);
- return;
+ if (ide_handle_write_error(s, -ret, BM_STATUS_PIO_RETRY))
+ return;
}
s->nsector -= n;
@@ -1024,6 +1052,20 @@
}
}
+static void ide_dma_restart_cb(void *opaque, int running)
+{
+ BMDMAState *bm = opaque;
+ if (!running)
+ return;
+ if (bm->status & BM_STATUS_DMA_RETRY) {
+ bm->status &= ~BM_STATUS_DMA_RETRY;
+ ide_dma_restart(bm->ide_if);
+ } else if (bm->status & BM_STATUS_PIO_RETRY) {
+ bm->status &= ~BM_STATUS_PIO_RETRY;
+ ide_sector_write(bm->ide_if);
+ }
+}
+
static void ide_write_dma_cb(void *opaque, int ret)
{
BMDMAState *bm = opaque;
@@ -1032,8 +1074,8 @@
int64_t sector_num;
if (ret < 0) {
- ide_dma_error(s);
- return;
+ if (ide_handle_write_error(s, -ret, BM_STATUS_DMA_RETRY))
+ return;
}
n = s->io_buffer_size >> 9;
@@ -2849,11 +2891,25 @@
bm->cur_prd_last = 0;
bm->cur_prd_addr = 0;
bm->cur_prd_len = 0;
+ bm->sector_num = ide_get_sector(s);
+ bm->nsector = s->nsector;
if (bm->status & BM_STATUS_DMAING) {
bm->dma_cb(bm, 0);
}
}
+static void ide_dma_restart(IDEState *s)
+{
+ BMDMAState *bm = s->bmdma;
+ ide_set_sector(s, bm->sector_num);
+ s->io_buffer_index = 0;
+ s->io_buffer_size = 0;
+ s->nsector = bm->nsector;
+ bm->cur_addr = bm->addr;
+ bm->dma_cb = ide_write_dma_cb;
+ ide_dma_start(s, bm->dma_cb);
+}
+
static void ide_dma_cancel(BMDMAState *bm)
{
if (bm->status & BM_STATUS_DMAING) {
@@ -3043,6 +3099,7 @@
d->ide_if[2 * i].bmdma = bm;
d->ide_if[2 * i + 1].bmdma = bm;
bm->pci_dev = (PCIIDEState *)pci_dev;
+ qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm);
register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
@@ -3068,9 +3125,14 @@
for(i = 0; i < 2; i++) {
BMDMAState *bm = &d->bmdma[i];
+ uint8_t ifidx;
qemu_put_8s(f, &bm->cmd);
qemu_put_8s(f, &bm->status);
qemu_put_be32s(f, &bm->addr);
+ qemu_put_sbe64s(f, &bm->sector_num);
+ qemu_put_be32s(f, &bm->nsector);
+ ifidx = bm->ide_if ? bm->ide_if - d->ide_if : 0;
+ qemu_put_8s(f, &ifidx);
/* XXX: if a transfer is pending, we do not save it yet */
}
@@ -3094,7 +3156,7 @@
PCIIDEState *d = opaque;
int ret, i;
- if (version_id != 1)
+ if (version_id != 2)
return -EINVAL;
ret = pci_device_load(&d->dev, f);
if (ret < 0)
@@ -3102,9 +3164,14 @@
for(i = 0; i < 2; i++) {
BMDMAState *bm = &d->bmdma[i];
+ uint8_t ifidx;
qemu_get_8s(f, &bm->cmd);
qemu_get_8s(f, &bm->status);
qemu_get_be32s(f, &bm->addr);
+ qemu_get_sbe64s(f, &bm->sector_num);
+ qemu_get_be32s(f, &bm->nsector);
+ qemu_get_8s(f, &ifidx);
+ bm->ide_if = &d->ide_if[ifidx];
/* XXX: if a transfer is pending, we do not save it yet */
}
@@ -3212,7 +3279,7 @@
ide_init2(&d->ide_if[0], hd_table[0], hd_table[1], irq[0]);
ide_init2(&d->ide_if[2], hd_table[2], hd_table[3], irq[1]);
- register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+ register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
qemu_register_reset(cmd646_reset, d);
cmd646_reset(d);
}
@@ -3269,7 +3336,7 @@
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
- register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+ register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
}
/* hd_table must contain 4 block drivers */
@@ -3308,7 +3375,7 @@
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
- register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
+ register_savevm("ide", 0, 2, pci_ide_save, pci_ide_load, d);
}
/***********************************************************/
Modified: trunk/sysemu.h
===================================================================
--- trunk/sysemu.h 2009-01-21 18:58:51 UTC (rev 6387)
+++ trunk/sysemu.h 2009-01-21 18:59:04 UTC (rev 6388)
@@ -128,11 +128,17 @@
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO
} BlockInterfaceType;
+typedef enum {
+ BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
+ BLOCK_ERR_STOP_ANY
+} BlockInterfaceErrorAction;
+
typedef struct DriveInfo {
BlockDriverState *bdrv;
BlockInterfaceType type;
int bus;
int unit;
+ BlockInterfaceErrorAction onerror;
char serial[21];
} DriveInfo;
@@ -146,6 +152,7 @@
extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
extern int drive_get_max_bus(BlockInterfaceType type);
extern const char *drive_get_serial(BlockDriverState *bdrv);
+extern BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv);
/* serial ports */
Modified: trunk/vl.c
===================================================================
--- trunk/vl.c 2009-01-21 18:58:51 UTC (rev 6387)
+++ trunk/vl.c 2009-01-21 18:59:04 UTC (rev 6388)
@@ -2200,6 +2200,17 @@
return "\0";
}
+BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
+{
+ int index;
+
+ for (index = 0; index < nb_drives; index++)
+ if (drives_table[index].bdrv == bdrv)
+ return drives_table[index].onerror;
+
+ return BLOCK_ERR_REPORT;
+}
+
static void bdrv_format_print(void *opaque, const char *name)
{
fprintf(stderr, " %s", name);
@@ -2222,12 +2233,13 @@
int max_devs;
int index;
int cache;
- int bdrv_flags;
+ int bdrv_flags, onerror;
char *str = arg->opt;
static const char * const params[] = { "bus", "unit", "if", "index",
"cyls", "heads", "secs", "trans",
"media", "snapshot", "file",
- "cache", "format", "serial", NULL };
+ "cache", "format", "serial", "werror",
+ NULL };
if (check_params(buf, sizeof(buf), params, str) < 0) {
fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
@@ -2417,6 +2429,26 @@
if (!get_param_value(serial, sizeof(serial), "serial", str))
memset(serial, 0, sizeof(serial));
+ onerror = BLOCK_ERR_REPORT;
+ if (get_param_value(buf, sizeof(serial), "werror", str)) {
+ if (type != IF_IDE) {
+ fprintf(stderr, "werror is supported only by IDE\n");
+ return -1;
+ }
+ if (!strcmp(buf, "ignore"))
+ onerror = BLOCK_ERR_IGNORE;
+ else if (!strcmp(buf, "enospc"))
+ onerror = BLOCK_ERR_STOP_ENOSPC;
+ else if (!strcmp(buf, "stop"))
+ onerror = BLOCK_ERR_STOP_ANY;
+ else if (!strcmp(buf, "report"))
+ onerror = BLOCK_ERR_REPORT;
+ else {
+ fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
+ return -1;
+ }
+ }
+
/* compute bus and unit according index */
if (index != -1) {
@@ -2480,6 +2512,7 @@
drives_table[nb_drives].type = type;
drives_table[nb_drives].bus = bus_id;
drives_table[nb_drives].unit = unit_id;
+ drives_table[nb_drives].onerror = onerror;
strncpy(drives_table[nb_drives].serial, serial, sizeof(serial));
nb_drives++;
next reply other threads:[~2009-01-21 18:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-21 18:59 Anthony Liguori [this message]
2009-02-25 16:55 ` [Qemu-devel] [6388] Stop VM on ENOSPC error Anthony Liguori
2009-02-25 17:04 ` Gleb Natapov
2009-02-25 17:25 ` Avi Kivity
2009-02-25 17:38 ` Jamie Lokier
2009-02-26 9:20 ` Avi Kivity
2009-02-26 9:24 ` Gleb Natapov
2009-02-25 17:34 ` Daniel P. Berrange
2009-02-25 18:31 ` Anthony Liguori
2009-02-25 18:48 ` Jamie Lokier
2009-02-25 19:29 ` Anthony Liguori
2009-02-25 18:36 ` Jamie Lokier
2009-02-25 17:11 ` Avi Kivity
2009-02-25 18:26 ` Anthony Liguori
2009-02-26 9:17 ` Avi Kivity
2009-02-25 17:20 ` Daniel P. Berrange
2009-02-25 18:08 ` [Qemu-devel] " Jan Kiszka
2009-02-25 18:27 ` [Qemu-devel] " Anthony Liguori
2009-02-25 18:51 ` Jamie Lokier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=E1LPiI5-0004LB-5o@cvs.savannah.gnu.org \
--to=anthony@codemonkey.ws \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.