diff --git a/qemu-config.c b/qemu-config.c index 590fc052fc..92b5363ecf 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -64,6 +64,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));