block: Move I/O status and error actions into BB
These options are only relevant for the user of a whole BDS tree (like a guest device or a block job) and should thus be moved into the BlockBackend. Signed-off-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
7f0e9da6f1
commit
373340b26c
125
block.c
125
block.c
@ -257,7 +257,6 @@ BlockDriverState *bdrv_new(void)
|
||||
for (i = 0; i < BLOCK_OP_TYPE_MAX; i++) {
|
||||
QLIST_INIT(&bs->op_blockers[i]);
|
||||
}
|
||||
bdrv_iostatus_disable(bs);
|
||||
notifier_list_init(&bs->close_notifiers);
|
||||
notifier_with_return_list_init(&bs->before_write_notifiers);
|
||||
qemu_co_queue_init(&bs->throttled_reqs[0]);
|
||||
@ -2005,14 +2004,6 @@ static void bdrv_move_feature_fields(BlockDriverState *bs_dest,
|
||||
|
||||
bs_dest->enable_write_cache = bs_src->enable_write_cache;
|
||||
|
||||
/* r/w error */
|
||||
bs_dest->on_read_error = bs_src->on_read_error;
|
||||
bs_dest->on_write_error = bs_src->on_write_error;
|
||||
|
||||
/* i/o status */
|
||||
bs_dest->iostatus_enabled = bs_src->iostatus_enabled;
|
||||
bs_dest->iostatus = bs_src->iostatus;
|
||||
|
||||
/* dirty bitmap */
|
||||
bs_dest->dirty_bitmaps = bs_src->dirty_bitmaps;
|
||||
}
|
||||
@ -2499,82 +2490,6 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
|
||||
*nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
|
||||
}
|
||||
|
||||
void bdrv_set_on_error(BlockDriverState *bs, BlockdevOnError on_read_error,
|
||||
BlockdevOnError on_write_error)
|
||||
{
|
||||
bs->on_read_error = on_read_error;
|
||||
bs->on_write_error = on_write_error;
|
||||
}
|
||||
|
||||
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) ?
|
||||
BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
|
||||
case BLOCKDEV_ON_ERROR_STOP:
|
||||
return BLOCK_ERROR_ACTION_STOP;
|
||||
case BLOCKDEV_ON_ERROR_REPORT:
|
||||
return BLOCK_ERROR_ACTION_REPORT;
|
||||
case BLOCKDEV_ON_ERROR_IGNORE:
|
||||
return BLOCK_ERROR_ACTION_IGNORE;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_qmp_error_event(BlockDriverState *bs,
|
||||
BlockErrorAction action,
|
||||
bool is_read, int error)
|
||||
{
|
||||
IoOperationType optype;
|
||||
|
||||
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
||||
qapi_event_send_block_io_error(bdrv_get_device_name(bs), optype, action,
|
||||
bdrv_iostatus_is_enabled(bs),
|
||||
error == ENOSPC, strerror(error),
|
||||
&error_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);
|
||||
|
||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||
/* First set the iostatus, so that "info block" returns an iostatus
|
||||
* that matches the events raised so far (an additional error iostatus
|
||||
* is fine, but not a lost one).
|
||||
*/
|
||||
bdrv_iostatus_set_err(bs, error);
|
||||
|
||||
/* Then raise the request to stop the VM and the event.
|
||||
* qemu_system_vmstop_request_prepare has two effects. First,
|
||||
* it ensures that the STOP event always comes after the
|
||||
* BLOCK_IO_ERROR event. Second, it ensures that even if management
|
||||
* can observe the STOP event and do a "cont" before the STOP
|
||||
* event is issued, the VM will not stop. In this case, vm_start()
|
||||
* also ensures that the STOP/RESUME pair of events is emitted.
|
||||
*/
|
||||
qemu_system_vmstop_request_prepare();
|
||||
send_qmp_error_event(bs, action, is_read, error);
|
||||
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
|
||||
} else {
|
||||
send_qmp_error_event(bs, action, is_read, error);
|
||||
}
|
||||
}
|
||||
|
||||
int bdrv_is_read_only(BlockDriverState *bs)
|
||||
{
|
||||
return bs->read_only;
|
||||
@ -3602,46 +3517,6 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
|
||||
return true;
|
||||
}
|
||||
|
||||
void bdrv_iostatus_enable(BlockDriverState *bs)
|
||||
{
|
||||
bs->iostatus_enabled = true;
|
||||
bs->iostatus = BLOCK_DEVICE_IO_STATUS_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_enabled &&
|
||||
(bs->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
|
||||
bs->on_write_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
bs->on_read_error == BLOCKDEV_ON_ERROR_STOP));
|
||||
}
|
||||
|
||||
void bdrv_iostatus_disable(BlockDriverState *bs)
|
||||
{
|
||||
bs->iostatus_enabled = false;
|
||||
}
|
||||
|
||||
void bdrv_iostatus_reset(BlockDriverState *bs)
|
||||
{
|
||||
if (bdrv_iostatus_is_enabled(bs)) {
|
||||
bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
if (bs->job) {
|
||||
block_job_iostatus_reset(bs->job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_iostatus_set_err(BlockDriverState *bs, int error)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void bdrv_img_create(const char *filename, const char *fmt,
|
||||
const char *base_filename, const char *base_fmt,
|
||||
char *options, uint64_t img_size, int flags,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "block/blockjob.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
#define BACKUP_CLUSTER_BITS 16
|
||||
#define BACKUP_CLUSTER_SIZE (1 << BACKUP_CLUSTER_BITS)
|
||||
@ -215,7 +216,9 @@ static void backup_iostatus_reset(BlockJob *job)
|
||||
{
|
||||
BackupBlockJob *s = container_of(job, BackupBlockJob, common);
|
||||
|
||||
bdrv_iostatus_reset(s->target);
|
||||
if (s->target->blk) {
|
||||
blk_iostatus_reset(s->target->blk);
|
||||
}
|
||||
}
|
||||
|
||||
static const BlockJobDriver backup_job_driver = {
|
||||
@ -360,8 +363,10 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
job->bitmap = hbitmap_alloc(end, 0);
|
||||
|
||||
bdrv_set_enable_write_cache(target, true);
|
||||
bdrv_set_on_error(target, on_target_error, on_target_error);
|
||||
bdrv_iostatus_enable(target);
|
||||
if (target->blk) {
|
||||
blk_set_on_error(target->blk, on_target_error, on_target_error);
|
||||
blk_iostatus_enable(target->blk);
|
||||
}
|
||||
|
||||
bdrv_add_before_write_notifier(bs, &before_write);
|
||||
|
||||
@ -451,7 +456,9 @@ static void coroutine_fn backup_run(void *opaque)
|
||||
}
|
||||
hbitmap_free(job->bitmap);
|
||||
|
||||
bdrv_iostatus_disable(target);
|
||||
if (target->blk) {
|
||||
blk_iostatus_disable(target->blk);
|
||||
}
|
||||
bdrv_op_unblock_all(target, job->common.blocker);
|
||||
|
||||
data = g_malloc(sizeof(*data));
|
||||
@ -480,7 +487,7 @@ void backup_start(BlockDriverState *bs, BlockDriverState *target,
|
||||
|
||||
if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||
!bdrv_iostatus_is_enabled(bs)) {
|
||||
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "on-source-error");
|
||||
return;
|
||||
}
|
||||
|
@ -12,7 +12,9 @@
|
||||
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi-event.h"
|
||||
|
||||
/* Number of coroutines to reserve per attached device model */
|
||||
@ -37,6 +39,10 @@ struct BlockBackend {
|
||||
|
||||
/* I/O stats (display with "info blockstats"). */
|
||||
BlockAcctStats stats;
|
||||
|
||||
BlockdevOnError on_read_error, on_write_error;
|
||||
bool iostatus_enabled;
|
||||
BlockDeviceIoStatus iostatus;
|
||||
};
|
||||
|
||||
typedef struct BlockBackendAIOCB {
|
||||
@ -330,7 +336,7 @@ int blk_attach_dev(BlockBackend *blk, void *dev)
|
||||
}
|
||||
blk_ref(blk);
|
||||
blk->dev = dev;
|
||||
bdrv_iostatus_reset(blk->bs);
|
||||
blk_iostatus_reset(blk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -462,7 +468,47 @@ void blk_dev_resize_cb(BlockBackend *blk)
|
||||
|
||||
void blk_iostatus_enable(BlockBackend *blk)
|
||||
{
|
||||
bdrv_iostatus_enable(blk->bs);
|
||||
blk->iostatus_enabled = true;
|
||||
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
}
|
||||
|
||||
/* The I/O status is only enabled if the drive explicitly
|
||||
* enables it _and_ the VM is configured to stop on errors */
|
||||
bool blk_iostatus_is_enabled(const BlockBackend *blk)
|
||||
{
|
||||
return (blk->iostatus_enabled &&
|
||||
(blk->on_write_error == BLOCKDEV_ON_ERROR_ENOSPC ||
|
||||
blk->on_write_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
blk->on_read_error == BLOCKDEV_ON_ERROR_STOP));
|
||||
}
|
||||
|
||||
BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk)
|
||||
{
|
||||
return blk->iostatus;
|
||||
}
|
||||
|
||||
void blk_iostatus_disable(BlockBackend *blk)
|
||||
{
|
||||
blk->iostatus_enabled = false;
|
||||
}
|
||||
|
||||
void blk_iostatus_reset(BlockBackend *blk)
|
||||
{
|
||||
if (blk_iostatus_is_enabled(blk)) {
|
||||
blk->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
|
||||
if (blk->bs && blk->bs->job) {
|
||||
block_job_iostatus_reset(blk->bs->job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void blk_iostatus_set_err(BlockBackend *blk, int error)
|
||||
{
|
||||
assert(blk_iostatus_is_enabled(blk));
|
||||
if (blk->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
|
||||
blk->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
|
||||
BLOCK_DEVICE_IO_STATUS_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static int blk_check_byte_request(BlockBackend *blk, int64_t offset,
|
||||
@ -738,21 +784,81 @@ void blk_drain_all(void)
|
||||
bdrv_drain_all();
|
||||
}
|
||||
|
||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
||||
BlockdevOnError on_write_error)
|
||||
{
|
||||
blk->on_read_error = on_read_error;
|
||||
blk->on_write_error = on_write_error;
|
||||
}
|
||||
|
||||
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read)
|
||||
{
|
||||
return bdrv_get_on_error(blk->bs, is_read);
|
||||
return is_read ? blk->on_read_error : blk->on_write_error;
|
||||
}
|
||||
|
||||
BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
||||
int error)
|
||||
{
|
||||
return bdrv_get_error_action(blk->bs, is_read, error);
|
||||
BlockdevOnError on_err = blk_get_on_error(blk, is_read);
|
||||
|
||||
switch (on_err) {
|
||||
case BLOCKDEV_ON_ERROR_ENOSPC:
|
||||
return (error == ENOSPC) ?
|
||||
BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT;
|
||||
case BLOCKDEV_ON_ERROR_STOP:
|
||||
return BLOCK_ERROR_ACTION_STOP;
|
||||
case BLOCKDEV_ON_ERROR_REPORT:
|
||||
return BLOCK_ERROR_ACTION_REPORT;
|
||||
case BLOCKDEV_ON_ERROR_IGNORE:
|
||||
return BLOCK_ERROR_ACTION_IGNORE;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void send_qmp_error_event(BlockBackend *blk,
|
||||
BlockErrorAction action,
|
||||
bool is_read, int error)
|
||||
{
|
||||
IoOperationType optype;
|
||||
|
||||
optype = is_read ? IO_OPERATION_TYPE_READ : IO_OPERATION_TYPE_WRITE;
|
||||
qapi_event_send_block_io_error(blk_name(blk), optype, action,
|
||||
blk_iostatus_is_enabled(blk),
|
||||
error == ENOSPC, strerror(error),
|
||||
&error_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 blk_error_action(BlockBackend *blk, BlockErrorAction action,
|
||||
bool is_read, int error)
|
||||
{
|
||||
bdrv_error_action(blk->bs, action, is_read, error);
|
||||
assert(error >= 0);
|
||||
|
||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||
/* First set the iostatus, so that "info block" returns an iostatus
|
||||
* that matches the events raised so far (an additional error iostatus
|
||||
* is fine, but not a lost one).
|
||||
*/
|
||||
blk_iostatus_set_err(blk, error);
|
||||
|
||||
/* Then raise the request to stop the VM and the event.
|
||||
* qemu_system_vmstop_request_prepare has two effects. First,
|
||||
* it ensures that the STOP event always comes after the
|
||||
* BLOCK_IO_ERROR event. Second, it ensures that even if management
|
||||
* can observe the STOP event and do a "cont" before the STOP
|
||||
* event is issued, the VM will not stop. In this case, vm_start()
|
||||
* also ensures that the STOP/RESUME pair of events is emitted.
|
||||
*/
|
||||
qemu_system_vmstop_request_prepare();
|
||||
send_qmp_error_event(blk, action, is_read, error);
|
||||
qemu_system_vmstop_request(RUN_STATE_IO_ERROR);
|
||||
} else {
|
||||
send_qmp_error_event(blk, action, is_read, error);
|
||||
}
|
||||
}
|
||||
|
||||
int blk_is_read_only(BlockBackend *blk)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "block/blockjob.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
enum {
|
||||
/*
|
||||
@ -213,7 +214,7 @@ void commit_start(BlockDriverState *bs, BlockDriverState *base,
|
||||
|
||||
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||
!bdrv_iostatus_is_enabled(bs)) {
|
||||
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
|
||||
error_setg(errp, "Invalid parameter combination");
|
||||
return;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "trace.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/block_int.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
#include "qemu/bitmap.h"
|
||||
@ -599,7 +600,9 @@ immediate_exit:
|
||||
g_free(s->cow_bitmap);
|
||||
g_free(s->in_flight_bitmap);
|
||||
bdrv_release_dirty_bitmap(bs, s->dirty_bitmap);
|
||||
bdrv_iostatus_disable(s->target);
|
||||
if (s->target->blk) {
|
||||
blk_iostatus_disable(s->target->blk);
|
||||
}
|
||||
|
||||
data = g_malloc(sizeof(*data));
|
||||
data->ret = ret;
|
||||
@ -621,7 +624,9 @@ static void mirror_iostatus_reset(BlockJob *job)
|
||||
{
|
||||
MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
|
||||
|
||||
bdrv_iostatus_reset(s->target);
|
||||
if (s->target->blk) {
|
||||
blk_iostatus_reset(s->target->blk);
|
||||
}
|
||||
}
|
||||
|
||||
static void mirror_complete(BlockJob *job, Error **errp)
|
||||
@ -704,7 +709,7 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
||||
|
||||
if ((on_source_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
on_source_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||
!bdrv_iostatus_is_enabled(bs)) {
|
||||
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "on-source-error");
|
||||
return;
|
||||
}
|
||||
@ -740,8 +745,10 @@ static void mirror_start_job(BlockDriverState *bs, BlockDriverState *target,
|
||||
return;
|
||||
}
|
||||
bdrv_set_enable_write_cache(s->target, true);
|
||||
bdrv_set_on_error(s->target, on_target_error, on_target_error);
|
||||
bdrv_iostatus_enable(s->target);
|
||||
if (s->target->blk) {
|
||||
blk_set_on_error(s->target->blk, on_target_error, on_target_error);
|
||||
blk_iostatus_enable(s->target->blk);
|
||||
}
|
||||
s->common.co = qemu_coroutine_create(mirror_run);
|
||||
trace_mirror_start(bs, s, s->common.co, opaque);
|
||||
qemu_coroutine_enter(s->common.co, s);
|
||||
|
@ -301,9 +301,9 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,
|
||||
info->tray_open = blk_dev_is_tray_open(blk);
|
||||
}
|
||||
|
||||
if (bdrv_iostatus_is_enabled(bs)) {
|
||||
if (blk_iostatus_is_enabled(blk)) {
|
||||
info->has_io_status = true;
|
||||
info->io_status = bs->iostatus;
|
||||
info->io_status = blk_iostatus(blk);
|
||||
}
|
||||
|
||||
if (!QLIST_EMPTY(&bs->dirty_bitmaps)) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "block/blockjob.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/ratelimit.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
enum {
|
||||
/*
|
||||
@ -222,7 +223,7 @@ void stream_start(BlockDriverState *bs, BlockDriverState *base,
|
||||
|
||||
if ((on_error == BLOCKDEV_ON_ERROR_STOP ||
|
||||
on_error == BLOCKDEV_ON_ERROR_ENOSPC) &&
|
||||
!bdrv_iostatus_is_enabled(bs)) {
|
||||
(!bs->blk || !blk_iostatus_is_enabled(bs->blk))) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "on-error");
|
||||
return;
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
|
||||
|
||||
bs->detect_zeroes = detect_zeroes;
|
||||
|
||||
bdrv_set_on_error(bs, on_read_error, on_write_error);
|
||||
blk_set_on_error(blk, on_read_error, on_write_error);
|
||||
|
||||
/* disk I/O throttling */
|
||||
if (throttle_enabled(&cfg)) {
|
||||
@ -2168,8 +2168,8 @@ void hmp_drive_del(Monitor *mon, const QDict *qdict)
|
||||
if (blk_get_attached_dev(blk)) {
|
||||
blk_hide_on_behalf_of_hmp_drive_del(blk);
|
||||
/* Further I/O must not pause the guest */
|
||||
bdrv_set_on_error(bs, BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT);
|
||||
blk_set_on_error(blk, BLOCKDEV_ON_ERROR_REPORT,
|
||||
BLOCKDEV_ON_ERROR_REPORT);
|
||||
} else {
|
||||
blk_unref(blk);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "block/block.h"
|
||||
#include "block/blockjob.h"
|
||||
#include "block/block_int.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qemu/coroutine.h"
|
||||
@ -354,8 +355,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
|
||||
job->user_paused = true;
|
||||
block_job_pause(job);
|
||||
block_job_iostatus_set_err(job, error);
|
||||
if (bs != job->bs) {
|
||||
bdrv_iostatus_set_err(bs, error);
|
||||
if (bs->blk && bs != job->bs) {
|
||||
blk_iostatus_set_err(bs->blk, error);
|
||||
}
|
||||
}
|
||||
return action;
|
||||
|
@ -174,11 +174,6 @@ typedef enum BlockOpType {
|
||||
BLOCK_OP_TYPE_MAX,
|
||||
} BlockOpType;
|
||||
|
||||
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_info_print(Monitor *mon, const QObject *data);
|
||||
void bdrv_info(Monitor *mon, QObject **ret_data);
|
||||
void bdrv_stats_print(Monitor *mon, const QObject *data);
|
||||
@ -389,12 +384,6 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
int bdrv_is_allocated_above(BlockDriverState *top, BlockDriverState *base,
|
||||
int64_t sector_num, int nb_sectors, int *pnum);
|
||||
|
||||
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);
|
||||
|
@ -414,12 +414,6 @@ struct BlockDriverState {
|
||||
/* do we need to tell the quest if we have a volatile write cache? */
|
||||
int enable_write_cache;
|
||||
|
||||
/* NOTE: the following infos are only hints for real hardware
|
||||
drivers. They are not used by the block driver */
|
||||
BlockdevOnError on_read_error, on_write_error;
|
||||
bool iostatus_enabled;
|
||||
BlockDeviceIoStatus iostatus;
|
||||
|
||||
/* the following member gives a name to every node on the bs graph. */
|
||||
char node_name[32];
|
||||
/* element of the list of named nodes building the graph */
|
||||
|
@ -76,6 +76,11 @@ BlockDriverState *blk_bs(BlockBackend *blk);
|
||||
void blk_hide_on_behalf_of_hmp_drive_del(BlockBackend *blk);
|
||||
|
||||
void blk_iostatus_enable(BlockBackend *blk);
|
||||
bool blk_iostatus_is_enabled(const BlockBackend *blk);
|
||||
BlockDeviceIoStatus blk_iostatus(const BlockBackend *blk);
|
||||
void blk_iostatus_disable(BlockBackend *blk);
|
||||
void blk_iostatus_reset(BlockBackend *blk);
|
||||
void blk_iostatus_set_err(BlockBackend *blk, int error);
|
||||
int blk_attach_dev(BlockBackend *blk, void *dev);
|
||||
void blk_attach_dev_nofail(BlockBackend *blk, void *dev);
|
||||
void blk_detach_dev(BlockBackend *blk, void *dev);
|
||||
@ -120,6 +125,8 @@ int blk_flush(BlockBackend *blk);
|
||||
int blk_flush_all(void);
|
||||
void blk_drain(BlockBackend *blk);
|
||||
void blk_drain_all(void);
|
||||
void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error,
|
||||
BlockdevOnError on_write_error);
|
||||
BlockdevOnError blk_get_on_error(BlockBackend *blk, bool is_read);
|
||||
BlockErrorAction blk_get_error_action(BlockBackend *blk, bool is_read,
|
||||
int error);
|
||||
|
6
qmp.c
6
qmp.c
@ -24,6 +24,7 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
@ -170,6 +171,7 @@ SpiceInfo *qmp_query_spice(Error **errp)
|
||||
void qmp_cont(Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
BlockBackend *blk;
|
||||
BlockDriverState *bs;
|
||||
|
||||
if (runstate_needs_reset()) {
|
||||
@ -179,8 +181,8 @@ void qmp_cont(Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
|
||||
bdrv_iostatus_reset(bs);
|
||||
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
|
||||
blk_iostatus_reset(blk);
|
||||
}
|
||||
for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
|
||||
bdrv_add_key(bs, NULL, &local_err);
|
||||
|
Loading…
Reference in New Issue
Block a user