#include "monitor.h"
#include "block_int.h"
#include "module.h"
-#include "qemu-objects.h"
+#include "qjson.h"
#include "qemu-coroutine.h"
+#include "qmp-commands.h"
#ifdef CONFIG_BSD
#include <sys/types.h>
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
-static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque);
-static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque);
static int coroutine_fn bdrv_co_readv_em(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
QEMUIOVector *iov);
static int coroutine_fn bdrv_co_writev_em(BlockDriverState *bs,
int64_t sector_num, int nb_sectors,
QEMUIOVector *iov);
-static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs);
static int coroutine_fn bdrv_co_do_readv(BlockDriverState *bs,
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
static int coroutine_fn bdrv_co_do_writev(BlockDriverState *bs,
}
}
- if (!bdrv->bdrv_aio_flush)
- bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
-
QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
}
bs->total_sectors = 0;
bs->encrypted = 0;
bs->valid_key = 0;
+ bs->sg = 0;
bs->open_flags = flags;
+ bs->growable = 0;
bs->buffer_alignment = 512;
pstrcpy(bs->filename, sizeof(bs->filename), filename);
+ bs->backing_file[0] = '\0';
if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
return -ENOTSUP;
bs->drv = drv;
bs->opaque = g_malloc0(drv->instance_size);
- if (flags & BDRV_O_CACHE_WB)
- bs->enable_write_cache = 1;
+ bs->enable_write_cache = !!(flags & BDRV_O_CACHE_WB);
/*
* Clear flags that are internal to the block layer before opening the
open_flags |= BDRV_O_RDWR;
}
+ bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
+
/* Open the image, either directly or using a protocol */
if (drv->bdrv_file_open) {
ret = drv->bdrv_file_open(bs, filename, open_flags);
goto free_and_fail;
}
- bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
-
ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
goto free_and_fail;
BlockDriver *drv)
{
int ret;
+ char tmp_filename[PATH_MAX];
if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1;
int is_protocol = 0;
BlockDriver *bdrv_qcow2;
QEMUOptionParameter *options;
- char tmp_filename[PATH_MAX];
char backing_filename[PATH_MAX];
/* if snapshot, we create a temporary backing file and open it
nb_sectors * BDRV_SECTOR_SIZE);
}
-static inline bool bdrv_has_async_flush(BlockDriver *drv)
-{
- return drv->bdrv_aio_flush != bdrv_aio_flush_em;
-}
-
typedef struct RwCo {
BlockDriverState *bs;
int64_t sector_num;
return bs->device_name;
}
-int bdrv_flush(BlockDriverState *bs)
-{
- if (bs->open_flags & BDRV_O_NO_FLUSH) {
- return 0;
- }
-
- if (bs->drv && bdrv_has_async_flush(bs->drv) && qemu_in_coroutine()) {
- return bdrv_co_flush_em(bs);
- }
-
- if (bs->drv && bs->drv->bdrv_flush) {
- return bs->drv->bdrv_flush(bs);
- }
-
- /*
- * Some block drivers always operate in either writethrough or unsafe mode
- * and don't support bdrv_flush therefore. Usually qemu doesn't know how
- * the server works (because the behaviour is hardcoded or depends on
- * server-side configuration), so we can't ensure that everything is safe
- * on disk. Returning an error doesn't work because that would break guests
- * even if the server operates in writethrough mode.
- *
- * Let's hope the user knows what he's doing.
- */
- return 0;
-}
-
void bdrv_flush_all(void)
{
BlockDriverState *bs;
return 1;
}
-int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
-{
- if (!bs->drv) {
- return -ENOMEDIUM;
- }
- if (!bs->drv->bdrv_discard) {
- return 0;
- }
- return bs->drv->bdrv_discard(bs, sector_num, nb_sectors);
-}
-
/*
* Returns true iff the specified sector is present in the disk image. Drivers
* not implementing the functionality are assumed to not support backing files,
qobject_decref(data);
}
-static void bdrv_print_dict(QObject *obj, void *opaque)
-{
- QDict *bs_dict;
- Monitor *mon = opaque;
-
- bs_dict = qobject_to_qdict(obj);
-
- monitor_printf(mon, "%s: removable=%d",
- qdict_get_str(bs_dict, "device"),
- qdict_get_bool(bs_dict, "removable"));
-
- if (qdict_get_bool(bs_dict, "removable")) {
- monitor_printf(mon, " locked=%d", qdict_get_bool(bs_dict, "locked"));
- monitor_printf(mon, " tray-open=%d",
- qdict_get_bool(bs_dict, "tray-open"));
- }
-
- if (qdict_haskey(bs_dict, "io-status")) {
- monitor_printf(mon, " io-status=%s", qdict_get_str(bs_dict, "io-status"));
- }
-
- if (qdict_haskey(bs_dict, "inserted")) {
- QDict *qdict = qobject_to_qdict(qdict_get(bs_dict, "inserted"));
-
- monitor_printf(mon, " file=");
- monitor_print_filename(mon, qdict_get_str(qdict, "file"));
- if (qdict_haskey(qdict, "backing_file")) {
- monitor_printf(mon, " backing_file=");
- monitor_print_filename(mon, qdict_get_str(qdict, "backing_file"));
- }
- monitor_printf(mon, " ro=%d drv=%s encrypted=%d",
- qdict_get_bool(qdict, "ro"),
- qdict_get_str(qdict, "drv"),
- qdict_get_bool(qdict, "encrypted"));
- } else {
- monitor_printf(mon, " [not inserted]");
- }
-
- monitor_printf(mon, "\n");
-}
-
-void bdrv_info_print(Monitor *mon, const QObject *data)
+BlockInfoList *qmp_query_block(Error **errp)
{
- qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
-}
-
-static const char *const io_status_name[BDRV_IOS_MAX] = {
- [BDRV_IOS_OK] = "ok",
- [BDRV_IOS_FAILED] = "failed",
- [BDRV_IOS_ENOSPC] = "nospace",
-};
-
-void bdrv_info(Monitor *mon, QObject **ret_data)
-{
- QList *bs_list;
+ BlockInfoList *head = NULL, *cur_item = NULL;
BlockDriverState *bs;
- bs_list = qlist_new();
-
QTAILQ_FOREACH(bs, &bdrv_states, list) {
- QObject *bs_obj;
- QDict *bs_dict;
+ BlockInfoList *info = g_malloc0(sizeof(*info));
- bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', "
- "'removable': %i, 'locked': %i }",
- bs->device_name,
- bdrv_dev_has_removable_media(bs),
- bdrv_dev_is_medium_locked(bs));
- bs_dict = qobject_to_qdict(bs_obj);
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->device = g_strdup(bs->device_name);
+ info->value->type = g_strdup("unknown");
+ info->value->locked = bdrv_dev_is_medium_locked(bs);
+ info->value->removable = bdrv_dev_has_removable_media(bs);
if (bdrv_dev_has_removable_media(bs)) {
- qdict_put(bs_dict, "tray-open",
- qbool_from_int(bdrv_dev_is_tray_open(bs)));
+ info->value->has_tray_open = true;
+ info->value->tray_open = bdrv_dev_is_tray_open(bs);
}
if (bdrv_iostatus_is_enabled(bs)) {
- qdict_put(bs_dict, "io-status",
- qstring_from_str(io_status_name[bs->iostatus]));
+ info->value->has_io_status = true;
+ info->value->io_status = bs->iostatus;
}
if (bs->drv) {
- QObject *obj;
-
- obj = qobject_from_jsonf("{ 'file': %s, 'ro': %i, 'drv': %s, "
- "'encrypted': %i }",
- bs->filename, bs->read_only,
- bs->drv->format_name,
- bdrv_is_encrypted(bs));
- if (bs->backing_file[0] != '\0') {
- QDict *qdict = qobject_to_qdict(obj);
- qdict_put(qdict, "backing_file",
- qstring_from_str(bs->backing_file));
+ info->value->has_inserted = true;
+ info->value->inserted = g_malloc0(sizeof(*info->value->inserted));
+ info->value->inserted->file = g_strdup(bs->filename);
+ info->value->inserted->ro = bs->read_only;
+ info->value->inserted->drv = g_strdup(bs->drv->format_name);
+ info->value->inserted->encrypted = bs->encrypted;
+ if (bs->backing_file[0]) {
+ info->value->inserted->has_backing_file = true;
+ info->value->inserted->backing_file = g_strdup(bs->backing_file);
}
+ }
- qdict_put_obj(bs_dict, "inserted", obj);
+ /* XXX: waiting for the qapi to support GSList */
+ if (!cur_item) {
+ head = cur_item = info;
+ } else {
+ cur_item->next = info;
+ cur_item = info;
}
- qlist_append_obj(bs_list, bs_obj);
}
- *ret_data = QOBJECT(bs_list);
+ return head;
}
-static void bdrv_stats_iter(QObject *data, void *opaque)
+/* Consider exposing this as a full fledged QMP command */
+static BlockStats *qmp_query_blockstat(const BlockDriverState *bs, Error **errp)
{
- QDict *qdict;
- Monitor *mon = opaque;
-
- qdict = qobject_to_qdict(data);
- monitor_printf(mon, "%s:", qdict_get_str(qdict, "device"));
-
- qdict = qobject_to_qdict(qdict_get(qdict, "stats"));
- monitor_printf(mon, " rd_bytes=%" PRId64
- " wr_bytes=%" PRId64
- " rd_operations=%" PRId64
- " wr_operations=%" PRId64
- " flush_operations=%" PRId64
- " wr_total_time_ns=%" PRId64
- " rd_total_time_ns=%" PRId64
- " flush_total_time_ns=%" PRId64
- "\n",
- qdict_get_int(qdict, "rd_bytes"),
- qdict_get_int(qdict, "wr_bytes"),
- qdict_get_int(qdict, "rd_operations"),
- qdict_get_int(qdict, "wr_operations"),
- qdict_get_int(qdict, "flush_operations"),
- qdict_get_int(qdict, "wr_total_time_ns"),
- qdict_get_int(qdict, "rd_total_time_ns"),
- qdict_get_int(qdict, "flush_total_time_ns"));
-}
+ BlockStats *s;
-void bdrv_stats_print(Monitor *mon, const QObject *data)
-{
- qlist_iter(qobject_to_qlist(data), bdrv_stats_iter, mon);
-}
+ s = g_malloc0(sizeof(*s));
-static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
-{
- QObject *res;
- QDict *dict;
-
- res = qobject_from_jsonf("{ 'stats': {"
- "'rd_bytes': %" PRId64 ","
- "'wr_bytes': %" PRId64 ","
- "'rd_operations': %" PRId64 ","
- "'wr_operations': %" PRId64 ","
- "'wr_highest_offset': %" PRId64 ","
- "'flush_operations': %" PRId64 ","
- "'wr_total_time_ns': %" PRId64 ","
- "'rd_total_time_ns': %" PRId64 ","
- "'flush_total_time_ns': %" PRId64
- "} }",
- bs->nr_bytes[BDRV_ACCT_READ],
- bs->nr_bytes[BDRV_ACCT_WRITE],
- bs->nr_ops[BDRV_ACCT_READ],
- bs->nr_ops[BDRV_ACCT_WRITE],
- bs->wr_highest_sector *
- (uint64_t)BDRV_SECTOR_SIZE,
- bs->nr_ops[BDRV_ACCT_FLUSH],
- bs->total_time_ns[BDRV_ACCT_WRITE],
- bs->total_time_ns[BDRV_ACCT_READ],
- bs->total_time_ns[BDRV_ACCT_FLUSH]);
- dict = qobject_to_qdict(res);
-
- if (*bs->device_name) {
- qdict_put(dict, "device", qstring_from_str(bs->device_name));
+ if (bs->device_name[0]) {
+ s->has_device = true;
+ s->device = g_strdup(bs->device_name);
}
+ s->stats = g_malloc0(sizeof(*s->stats));
+ s->stats->rd_bytes = bs->nr_bytes[BDRV_ACCT_READ];
+ s->stats->wr_bytes = bs->nr_bytes[BDRV_ACCT_WRITE];
+ s->stats->rd_operations = bs->nr_ops[BDRV_ACCT_READ];
+ s->stats->wr_operations = bs->nr_ops[BDRV_ACCT_WRITE];
+ s->stats->wr_highest_offset = bs->wr_highest_sector * BDRV_SECTOR_SIZE;
+ s->stats->flush_operations = bs->nr_ops[BDRV_ACCT_FLUSH];
+ s->stats->wr_total_time_ns = bs->total_time_ns[BDRV_ACCT_WRITE];
+ s->stats->rd_total_time_ns = bs->total_time_ns[BDRV_ACCT_READ];
+ s->stats->flush_total_time_ns = bs->total_time_ns[BDRV_ACCT_FLUSH];
+
if (bs->file) {
- QObject *parent = bdrv_info_stats_bs(bs->file);
- qdict_put_obj(dict, "parent", parent);
+ s->has_parent = true;
+ s->parent = qmp_query_blockstat(bs->file, NULL);
}
- return res;
+ return s;
}
-void bdrv_info_stats(Monitor *mon, QObject **ret_data)
+BlockStatsList *qmp_query_blockstats(Error **errp)
{
- QObject *obj;
- QList *devices;
+ BlockStatsList *head = NULL, *cur_item = NULL;
BlockDriverState *bs;
- devices = qlist_new();
-
QTAILQ_FOREACH(bs, &bdrv_states, list) {
- obj = bdrv_info_stats_bs(bs);
- qlist_append_obj(devices, obj);
+ BlockStatsList *info = g_malloc0(sizeof(*info));
+ info->value = qmp_query_blockstat(bs, NULL);
+
+ /* XXX: waiting for the qapi to support GSList */
+ if (!cur_item) {
+ head = cur_item = info;
+ } else {
+ cur_item->next = info;
+ cur_item = info;
+ }
}
- *ret_data = QOBJECT(devices);
+ return head;
}
const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
- if (!bs->backing_file) {
- pstrcpy(filename, filename_size, "");
- } else {
- pstrcpy(filename, filename_size, bs->backing_file);
- }
+ pstrcpy(filename, filename_size, bs->backing_file);
}
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
return -1;
}
-BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
- BlockDriverCompletionFunc *cb, void *opaque)
-{
- BlockDriver *drv = bs->drv;
-
- trace_bdrv_aio_flush(bs, opaque);
-
- if (bs->open_flags & BDRV_O_NO_FLUSH) {
- return bdrv_aio_noop_em(bs, cb, opaque);
- }
-
- if (!drv)
- return NULL;
- return drv->bdrv_aio_flush(bs, cb, opaque);
-}
-
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
{
acb->pool->cancel(acb);
.cancel = bdrv_aio_co_cancel_em,
};
-static void bdrv_co_rw_bh(void *opaque)
+static void bdrv_co_em_bh(void *opaque)
{
BlockDriverAIOCBCoroutine *acb = opaque;
acb->req.nb_sectors, acb->req.qiov);
}
- acb->bh = qemu_bh_new(bdrv_co_rw_bh, acb);
+ acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
qemu_bh_schedule(acb->bh);
}
return &acb->common;
}
-static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
+static void coroutine_fn bdrv_aio_flush_co_entry(void *opaque)
+{
+ BlockDriverAIOCBCoroutine *acb = opaque;
+ BlockDriverState *bs = acb->common.bs;
+
+ acb->req.error = bdrv_co_flush(bs);
+ acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
+ qemu_bh_schedule(acb->bh);
+}
+
+BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque)
{
- BlockDriverAIOCBSync *acb;
+ trace_bdrv_aio_flush(bs, opaque);
- acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
- acb->is_write = 1; /* don't bounce in the completion hadler */
- acb->qiov = NULL;
- acb->bounce = NULL;
- acb->ret = 0;
+ Coroutine *co;
+ BlockDriverAIOCBCoroutine *acb;
- if (!acb->bh)
- acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+ acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+ co = qemu_coroutine_create(bdrv_aio_flush_co_entry);
+ qemu_coroutine_enter(co, acb);
- bdrv_flush(bs);
- qemu_bh_schedule(acb->bh);
return &acb->common;
}
-static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
+static void coroutine_fn bdrv_aio_discard_co_entry(void *opaque)
+{
+ BlockDriverAIOCBCoroutine *acb = opaque;
+ BlockDriverState *bs = acb->common.bs;
+
+ acb->req.error = bdrv_co_discard(bs, acb->req.sector, acb->req.nb_sectors);
+ acb->bh = qemu_bh_new(bdrv_co_em_bh, acb);
+ qemu_bh_schedule(acb->bh);
+}
+
+BlockDriverAIOCB *bdrv_aio_discard(BlockDriverState *bs,
+ int64_t sector_num, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque)
{
- BlockDriverAIOCBSync *acb;
+ Coroutine *co;
+ BlockDriverAIOCBCoroutine *acb;
- acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
- acb->is_write = 1; /* don't bounce in the completion handler */
- acb->qiov = NULL;
- acb->bounce = NULL;
- acb->ret = 0;
+ trace_bdrv_aio_discard(bs, sector_num, nb_sectors, opaque);
- if (!acb->bh) {
- acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
- }
+ acb = qemu_aio_get(&bdrv_em_co_aio_pool, bs, cb, opaque);
+ acb->req.sector = sector_num;
+ acb->req.nb_sectors = nb_sectors;
+ co = qemu_coroutine_create(bdrv_aio_discard_co_entry);
+ qemu_coroutine_enter(co, acb);
- qemu_bh_schedule(acb->bh);
return &acb->common;
}
return bdrv_co_io_em(bs, sector_num, nb_sectors, iov, true);
}
-static int coroutine_fn bdrv_co_flush_em(BlockDriverState *bs)
+static void coroutine_fn bdrv_flush_co_entry(void *opaque)
{
- CoroutineIOCompletion co = {
- .coroutine = qemu_coroutine_self(),
+ RwCo *rwco = opaque;
+
+ rwco->ret = bdrv_co_flush(rwco->bs);
+}
+
+int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
+{
+ if (bs->open_flags & BDRV_O_NO_FLUSH) {
+ return 0;
+ } else if (!bs->drv) {
+ return 0;
+ } else if (bs->drv->bdrv_co_flush) {
+ return bs->drv->bdrv_co_flush(bs);
+ } else if (bs->drv->bdrv_aio_flush) {
+ BlockDriverAIOCB *acb;
+ CoroutineIOCompletion co = {
+ .coroutine = qemu_coroutine_self(),
+ };
+
+ acb = bs->drv->bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co);
+ if (acb == NULL) {
+ return -EIO;
+ } else {
+ qemu_coroutine_yield();
+ return co.ret;
+ }
+ } else {
+ /*
+ * Some block drivers always operate in either writethrough or unsafe
+ * mode and don't support bdrv_flush therefore. Usually qemu doesn't
+ * know how the server works (because the behaviour is hardcoded or
+ * depends on server-side configuration), so we can't ensure that
+ * everything is safe on disk. Returning an error doesn't work because
+ * that would break guests even if the server operates in writethrough
+ * mode.
+ *
+ * Let's hope the user knows what he's doing.
+ */
+ return 0;
+ }
+}
+
+int bdrv_flush(BlockDriverState *bs)
+{
+ Coroutine *co;
+ RwCo rwco = {
+ .bs = bs,
+ .ret = NOT_DONE,
};
- BlockDriverAIOCB *acb;
- acb = bdrv_aio_flush(bs, bdrv_co_io_em_complete, &co);
- if (!acb) {
+ if (qemu_in_coroutine()) {
+ /* Fast-path if already in coroutine context */
+ bdrv_flush_co_entry(&rwco);
+ } else {
+ co = qemu_coroutine_create(bdrv_flush_co_entry);
+ qemu_coroutine_enter(co, &rwco);
+ while (rwco.ret == NOT_DONE) {
+ qemu_aio_wait();
+ }
+ }
+
+ return rwco.ret;
+}
+
+static void coroutine_fn bdrv_discard_co_entry(void *opaque)
+{
+ RwCo *rwco = opaque;
+
+ rwco->ret = bdrv_co_discard(rwco->bs, rwco->sector_num, rwco->nb_sectors);
+}
+
+int coroutine_fn bdrv_co_discard(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors)
+{
+ if (!bs->drv) {
+ return -ENOMEDIUM;
+ } else if (bdrv_check_request(bs, sector_num, nb_sectors)) {
return -EIO;
+ } else if (bs->read_only) {
+ return -EROFS;
+ } else if (bs->drv->bdrv_co_discard) {
+ return bs->drv->bdrv_co_discard(bs, sector_num, nb_sectors);
+ } else if (bs->drv->bdrv_aio_discard) {
+ BlockDriverAIOCB *acb;
+ CoroutineIOCompletion co = {
+ .coroutine = qemu_coroutine_self(),
+ };
+
+ acb = bs->drv->bdrv_aio_discard(bs, sector_num, nb_sectors,
+ bdrv_co_io_em_complete, &co);
+ if (acb == NULL) {
+ return -EIO;
+ } else {
+ qemu_coroutine_yield();
+ return co.ret;
+ }
+ } else {
+ return 0;
}
- qemu_coroutine_yield();
- return co.ret;
+}
+
+int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
+{
+ Coroutine *co;
+ RwCo rwco = {
+ .bs = bs,
+ .sector_num = sector_num,
+ .nb_sectors = nb_sectors,
+ .ret = NOT_DONE,
+ };
+
+ if (qemu_in_coroutine()) {
+ /* Fast-path if already in coroutine context */
+ bdrv_discard_co_entry(&rwco);
+ } else {
+ co = qemu_coroutine_create(bdrv_discard_co_entry);
+ qemu_coroutine_enter(co, &rwco);
+ while (rwco.ret == NOT_DONE) {
+ qemu_aio_wait();
+ }
+ }
+
+ return rwco.ret;
}
/**************************************************************/
void bdrv_iostatus_enable(BlockDriverState *bs)
{
- bs->iostatus = BDRV_IOS_OK;
+ 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 != BDRV_IOS_INVAL &&
+ return (bs->iostatus_enabled &&
(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;
+ bs->iostatus_enabled = false;
}
void bdrv_iostatus_reset(BlockDriverState *bs)
{
if (bdrv_iostatus_is_enabled(bs)) {
- bs->iostatus = BDRV_IOS_OK;
+ bs->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
}
}
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) {
+ if (bdrv_iostatus_is_enabled(bs) &&
+ bs->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
assert(error >= 0);
- bs->iostatus = error == ENOSPC ? BDRV_IOS_ENOSPC : BDRV_IOS_FAILED;
+ bs->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
+ BLOCK_DEVICE_IO_STATUS_FAILED;
}
}