summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qemu-config.c3
-rw-r--r--sysemu.h1
-rw-r--r--vl.c59
3 files changed, 44 insertions, 19 deletions
diff --git a/qemu-config.c b/qemu-config.c
index 590fc052fc..92b5363ecf 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -65,6 +65,9 @@ QemuOptsList qemu_drive_opts = {
.name = "serial",
.type = QEMU_OPT_STRING,
},{
+ .name = "rerror",
+ .type = QEMU_OPT_STRING,
+ },{
.name = "werror",
.type = QEMU_OPT_STRING,
},{
diff --git a/sysemu.h b/sysemu.h
index c79a019e73..efed771d0f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -180,6 +180,7 @@ typedef struct DriveInfo {
int bus;
int unit;
QemuOpts *opts;
+ BlockInterfaceErrorAction on_read_error;
BlockInterfaceErrorAction on_write_error;
char serial[BLOCK_SERIAL_STRLEN + 1];
QTAILQ_ENTRY(DriveInfo) next;
diff --git a/vl.c b/vl.c
index b0a2e883d4..3d64fc6534 100644
--- a/vl.c
+++ b/vl.c
@@ -1964,16 +1964,12 @@ BlockInterfaceErrorAction drive_get_on_error(
{
DriveInfo *dinfo;
- if (is_read) {
- return BLOCK_ERR_REPORT;
- }
-
QTAILQ_FOREACH(dinfo, &drives, next) {
if (dinfo->bdrv == bdrv)
- return dinfo->on_write_error;
+ return is_read ? dinfo->on_read_error : dinfo->on_write_error;
}
- return BLOCK_ERR_STOP_ENOSPC;
+ return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
}
static void bdrv_format_print(void *opaque, const char *name)
@@ -1989,6 +1985,23 @@ void drive_uninit(DriveInfo *dinfo)
qemu_free(dinfo);
}
+static int parse_block_error_action(const char *buf, int is_read)
+{
+ if (!strcmp(buf, "ignore")) {
+ return BLOCK_ERR_IGNORE;
+ } else if (!is_read && !strcmp(buf, "enospc")) {
+ return BLOCK_ERR_STOP_ENOSPC;
+ } else if (!strcmp(buf, "stop")) {
+ return BLOCK_ERR_STOP_ANY;
+ } else if (!strcmp(buf, "report")) {
+ return BLOCK_ERR_REPORT;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid %s error action\n",
+ buf, is_read ? "read" : "write");
+ return -1;
+ }
+}
+
DriveInfo *drive_init(QemuOpts *opts, void *opaque,
int *fatal_error)
{
@@ -2008,7 +2021,8 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
int cache;
int aio = 0;
int ro = 0;
- int bdrv_flags, onerror;
+ int bdrv_flags;
+ int on_read_error, on_write_error;
const char *devaddr;
DriveInfo *dinfo;
int snapshot = 0;
@@ -2169,22 +2183,28 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
}
}
- onerror = BLOCK_ERR_STOP_ENOSPC;
+ on_write_error = BLOCK_ERR_STOP_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
fprintf(stderr, "werror is no supported by this format\n");
return NULL;
}
- 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);
+
+ on_write_error = parse_block_error_action(buf, 0);
+ if (on_write_error < 0) {
+ return NULL;
+ }
+ }
+
+ on_read_error = BLOCK_ERR_REPORT;
+ if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
+ if (1) {
+ fprintf(stderr, "rerror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_read_error = parse_block_error_action(buf, 1);
+ if (on_read_error < 0) {
return NULL;
}
}
@@ -2268,7 +2288,8 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
- dinfo->on_write_error = onerror;
+ dinfo->on_read_error = on_read_error;
+ dinfo->on_write_error = on_write_error;
dinfo->opts = opts;
if (serial)
strncpy(dinfo->serial, serial, sizeof(serial));