[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 13/45] iostatus: reorganize io error code
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [PATCH v2 13/45] iostatus: reorganize io error code |
Date: |
Wed, 26 Sep 2012 17:56:19 +0200 |
Move the common part of IDE/SCSI/virtio error handling to the block
layer. The new function bdrv_error_action subsumes all three of
bdrv_emit_qmp_error_event, vm_stop, bdrv_iostatus_set_err.
The same scheme will be used for errors in block jobs.
Signed-off-by: Paolo Bonzini <address@hidden>
---
block.c | 46 ++++++++++++++++++++++++++++++++++++++--------
block.h | 5 +++--
hw/ide/core.c | 20 +++++---------------
hw/scsi-disk.c | 23 +++++++----------------
hw/virtio-blk.c | 19 +++++--------------
qemu-tool.c | 6 ++++++
6 file modificati, 64 inserzioni(+), 55 rimozioni(-)
diff --git a/block.c b/block.c
index 85114c5..b7b04aa 100644
--- a/block.c
+++ b/block.c
@@ -29,6 +29,7 @@
#include "blockjob.h"
#include "module.h"
#include "qjson.h"
+#include "sysemu.h"
#include "qemu-coroutine.h"
#include "qmp-commands.h"
#include "qemu-timer.h"
@@ -1386,8 +1387,8 @@ void bdrv_set_dev_ops(BlockDriverState *bs, const
BlockDevOps *ops,
}
}
-void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
- BlockErrorAction action, bool is_read)
+static void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
+ BlockErrorAction action, bool is_read)
{
QObject *data;
const char *action_str;
@@ -2343,6 +2344,39 @@ BlockdevOnError bdrv_get_on_error(BlockDriverState *bs,
bool is_read)
return is_read ? bs->on_read_error : bs->on_write_error;
}
+BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int
error)
+{
+ BlockdevOnError on_err = is_read ? bs->on_read_error : bs->on_write_error;
+
+ switch (on_err) {
+ case BLOCKDEV_ON_ERROR_ENOSPC:
+ return (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
+ case BLOCKDEV_ON_ERROR_STOP:
+ return BDRV_ACTION_STOP;
+ case BLOCKDEV_ON_ERROR_REPORT:
+ return BDRV_ACTION_REPORT;
+ case BLOCKDEV_ON_ERROR_IGNORE:
+ return BDRV_ACTION_IGNORE;
+ default:
+ abort();
+ }
+}
+
+/* This is done by device models because, while the block layer knows
+ * about the error, it does not know whether an operation comes from
+ * the device or the block layer (from a job, for example).
+ */
+void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
+ bool is_read, int error)
+{
+ assert(error >= 0);
+ bdrv_emit_qmp_error_event(bs, action, is_read);
+ if (action == BDRV_ACTION_STOP) {
+ vm_stop(RUN_STATE_IO_ERROR);
+ bdrv_iostatus_set_err(bs, error);
+ }
+}
+
int bdrv_is_read_only(BlockDriverState *bs)
{
return bs->read_only;
@@ -4067,14 +4101,10 @@ void bdrv_iostatus_reset(BlockDriverState *bs)
}
}
-/* XXX: Today this is set by device models because it makes the implementation
- quite simple. However, the block layer knows about the error, so it's
- possible to implement this without device models being involved */
void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
{
- if (bdrv_iostatus_is_enabled(bs) &&
- bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
- assert(error >= 0);
+ assert(bdrv_iostatus_is_enabled(bs));
+ if (bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
BLOCK_DEVICE_IO_STATUS_FAILED;
}
diff --git a/block.h b/block.h
index 433721d..7db23b8 100644
--- a/block.h
+++ b/block.h
@@ -108,8 +108,6 @@ void bdrv_iostatus_reset(BlockDriverState *bs);
void bdrv_iostatus_disable(BlockDriverState *bs);
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs);
void bdrv_iostatus_set_err(BlockDriverState *bs, int error);
-void bdrv_emit_qmp_error_event(const BlockDriverState *bdrv,
- BlockErrorAction action, bool is_read);
void bdrv_info_print(Monitor *mon, const QObject *data);
void bdrv_info(Monitor *mon, QObject **ret_data);
void bdrv_stats_print(Monitor *mon, const QObject *data);
@@ -277,6 +275,9 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t
sector_num, int nb_sectors,
void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
BlockdevOnError on_write_error);
BlockdevOnError bdrv_get_on_error(BlockDriverState *bs, bool is_read);
+BlockErrorAction bdrv_get_error_action(BlockDriverState *bs, bool is_read, int
error);
+void bdrv_error_action(BlockDriverState *bs, BlockErrorAction action,
+ bool is_read, int error);
int bdrv_is_read_only(BlockDriverState *bs);
int bdrv_is_sg(BlockDriverState *bs);
int bdrv_enable_write_cache(BlockDriverState *bs);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c03db4a..d683a8c 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -557,31 +557,21 @@ void ide_dma_error(IDEState *s)
static int ide_handle_rw_error(IDEState *s, int error, int op)
{
bool is_read = (op & BM_STATUS_RETRY_READ) != 0;
- BlockdevOnError action = bdrv_get_on_error(s->bs, is_read);
+ BlockErrorAction action = bdrv_get_error_action(s->bs, is_read, error);
- if (action == BLOCKDEV_ON_ERROR_IGNORE) {
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read);
- return 0;
- }
-
- if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC)
- || action == BLOCKDEV_ON_ERROR_STOP) {
+ if (action == BDRV_ACTION_STOP) {
s->bus->dma->ops->set_unit(s->bus->dma, s->unit);
s->bus->error_status = op;
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read);
- vm_stop(RUN_STATE_IO_ERROR);
- bdrv_iostatus_set_err(s->bs, error);
- } else {
+ } else if (action == BDRV_ACTION_REPORT) {
if (op & BM_STATUS_DMA_RETRY) {
dma_buf_commit(s);
ide_dma_error(s);
} else {
ide_rw_error(s);
}
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read);
}
-
- return 1;
+ bdrv_error_action(s->bs, action, is_read, error);
+ return action != BDRV_ACTION_IGNORE;
}
void ide_dma_cb(void *opaque, int ret)
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 2dd99a9..99bb02e 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -388,21 +388,9 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
{
bool is_read = (r->req.cmd.xfer == SCSI_XFER_FROM_DEV);
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
- BlockdevOnError action = bdrv_get_on_error(s->qdev.conf.bs, is_read);
+ BlockErrorAction action = bdrv_get_error_action(s->qdev.conf.bs, is_read,
error);
- if (action == BLOCKDEV_ON_ERROR_IGNORE) {
- bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_IGNORE,
is_read);
- return 0;
- }
-
- if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC)
- || action == BLOCKDEV_ON_ERROR_STOP) {
-
- bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_STOP, is_read);
- vm_stop(RUN_STATE_IO_ERROR);
- bdrv_iostatus_set_err(s->qdev.conf.bs, error);
- scsi_req_retry(&r->req);
- } else {
+ if (action == BDRV_ACTION_REPORT) {
switch (error) {
case ENOMEDIUM:
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
@@ -417,9 +405,12 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error)
scsi_check_condition(r, SENSE_CODE(IO_ERROR));
break;
}
- bdrv_emit_qmp_error_event(s->qdev.conf.bs, BDRV_ACTION_REPORT,
is_read);
}
- return 1;
+ bdrv_error_action(s->qdev.conf.bs, action, is_read, error);
+ if (action == BDRV_ACTION_STOP) {
+ scsi_req_retry(&r->req);
+ }
+ return action != BDRV_ACTION_IGNORE;
}
static void scsi_write_complete(void * opaque, int ret)
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 1ac2483..e25cc96 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -66,29 +66,20 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req,
int status)
static int virtio_blk_handle_rw_error(VirtIOBlockReq *req, int error,
bool is_read)
{
- BlockdevOnError action = bdrv_get_on_error(req->dev->bs, is_read);
+ BlockErrorAction action = bdrv_get_error_action(req->dev->bs, is_read,
error);
VirtIOBlock *s = req->dev;
- if (action == BLOCKDEV_ON_ERROR_IGNORE) {
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_IGNORE, is_read);
- return 0;
- }
-
- if ((error == ENOSPC && action == BLOCKDEV_ON_ERROR_ENOSPC)
- || action == BLOCKDEV_ON_ERROR_STOP) {
+ if (action == BDRV_ACTION_STOP) {
req->next = s->rq;
s->rq = req;
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_STOP, is_read);
- vm_stop(RUN_STATE_IO_ERROR);
- bdrv_iostatus_set_err(s->bs, error);
- } else {
+ } else if (action == BDRV_ACTION_REPORT) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
bdrv_acct_done(s->bs, &req->acct);
g_free(req);
- bdrv_emit_qmp_error_event(s->bs, BDRV_ACTION_REPORT, is_read);
}
- return 1;
+ bdrv_error_action(s->bs, action, is_read, error);
+ return action != BDRV_ACTION_IGNORE;
}
static void virtio_blk_rw_complete(void *opaque, int ret)
diff --git a/qemu-tool.c b/qemu-tool.c
index 18205ba..f2f9813 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -19,6 +19,7 @@
#include "qemu-log.h"
#include "migration.h"
#include "main-loop.h"
+#include "sysemu.h"
#include "qemu_socket.h"
#include "slirp/libslirp.h"
@@ -37,6 +38,11 @@ const char *qemu_get_vm_name(void)
Monitor *cur_mon;
+void vm_stop(RunState state)
+{
+ abort();
+}
+
int monitor_cur_is_qmp(void)
{
return 0;
--
1.7.12
- Re: [Qemu-devel] [PATCH v2 06/45] block: add support for job pause/resume, (continued)
- [Qemu-devel] [PATCH v2 07/45] qmp: add block-job-pause and block-job-resume, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 08/45] qemu-iotests: add test for pausing a streaming operation, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 09/45] block: rename block_job_complete to block_job_completed, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 11/45] iostatus: move BlockdevOnError declaration to QAPI, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 13/45] iostatus: reorganize io error code,
Paolo Bonzini <=
- [Qemu-devel] [PATCH v2 10/45] iostatus: rename BlockErrorAction, BlockQMPEventAction, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 12/45] iostatus: change is_read to a bool, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 14/45] block: introduce block job error, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 16/45] blkdebug: process all set_state rules in the old state, Paolo Bonzini, 2012/09/26
- [Qemu-devel] [PATCH v2 17/45] qemu-iotests: map underscore to dash in QMP argument names, Paolo Bonzini, 2012/09/26