sim-card
/
qemu
Archived
10
0
Fork 0

block: Keep track of devices' I/O status

This commit adds support to the BlockDriverState type to keep track
of devices' I/O status.

There are three possible status: BDRV_IOS_OK (no error), BDRV_IOS_ENOSPC
(no space error) and BDRV_IOS_FAILED (any other error). The distinction
between no space and other errors is important because a management
application may want to watch for no space in order to extend the
space assigned to the VM and put it to run again.

Qemu devices supporting the I/O status feature have to enable it
explicitly by calling bdrv_iostatus_enable() _and_ have to be
configured to stop the VM on errors (ie. werror=stop|enospc or
rerror=stop).

In case of multiple errors being triggered in sequence only the first
one is stored. The I/O status is always reset to BDRV_IOS_OK when the
'cont' command is issued.

Next commits will add support to some devices and extend the
query-block/info block commands to return the I/O status information.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Luiz Capitulino 2011-09-26 17:43:50 -03:00 committed by Kevin Wolf
parent 449c184ed2
commit 28a7282a5d
4 changed files with 57 additions and 0 deletions

40
block.c
View File

@ -221,6 +221,7 @@ BlockDriverState *bdrv_new(const char *device_name)
if (device_name[0] != '\0') {
QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
}
bdrv_iostatus_disable(bs);
return bs;
}
@ -772,6 +773,7 @@ int bdrv_attach_dev(BlockDriverState *bs, void *dev)
return -EBUSY;
}
bs->dev = dev;
bdrv_iostatus_reset(bs);
return 0;
}
@ -3183,6 +3185,44 @@ int bdrv_in_use(BlockDriverState *bs)
return bs->in_use;
}
void bdrv_iostatus_enable(BlockDriverState *bs)
{
bs->iostatus = BDRV_IOS_OK;
}
/* The I/O status is only enabled if the drive explicitly
* enables it _and_ the VM is configured to stop on errors */
bool bdrv_iostatus_is_enabled(const BlockDriverState *bs)
{
return (bs->iostatus != BDRV_IOS_INVAL &&
(bs->on_write_error == BLOCK_ERR_STOP_ENOSPC ||
bs->on_write_error == BLOCK_ERR_STOP_ANY ||
bs->on_read_error == BLOCK_ERR_STOP_ANY));
}
void bdrv_iostatus_disable(BlockDriverState *bs)
{
bs->iostatus = BDRV_IOS_INVAL;
}
void bdrv_iostatus_reset(BlockDriverState *bs)
{
if (bdrv_iostatus_is_enabled(bs)) {
bs->iostatus = BDRV_IOS_OK;
}
}
/* 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 == BDRV_IOS_OK) {
assert(error >= 0);
bs->iostatus = error == ENOSPC ? BDRV_IOS_ENOSPC : BDRV_IOS_FAILED;
}
}
void
bdrv_acct_start(BlockDriverState *bs, BlockAcctCookie *cookie, int64_t bytes,
enum BlockAcctType type)

10
block.h
View File

@ -77,6 +77,16 @@ typedef enum {
BDRV_ACTION_REPORT, BDRV_ACTION_IGNORE, BDRV_ACTION_STOP
} BlockMonEventAction;
typedef enum {
BDRV_IOS_INVAL, BDRV_IOS_OK, BDRV_IOS_FAILED, BDRV_IOS_ENOSPC,
BDRV_IOS_MAX
} BlockIOStatus;
void bdrv_iostatus_enable(BlockDriverState *bs);
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_mon_event(const BlockDriverState *bdrv,
BlockMonEventAction action, int is_read);
void bdrv_info_print(Monitor *mon, const QObject *data);

View File

@ -199,6 +199,7 @@ struct BlockDriverState {
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
BlockErrorAction on_read_error, on_write_error;
BlockIOStatus iostatus;
char device_name[32];
unsigned long *dirty_bitmap;
int64_t dirty_count;

View File

@ -1221,6 +1221,11 @@ struct bdrv_iterate_context {
int err;
};
static void iostatus_bdrv_it(void *opaque, BlockDriverState *bs)
{
bdrv_iostatus_reset(bs);
}
/**
* do_cont(): Resume emulation.
*/
@ -1237,6 +1242,7 @@ static int do_cont(Monitor *mon, const QDict *qdict, QObject **ret_data)
return -1;
}
bdrv_iterate(iostatus_bdrv_it, NULL);
bdrv_iterate(encrypted_bdrv_it, &context);
/* only resume the vm if all keys are set and valid */
if (!context.err) {