#include "block/block_int.h"
#include "block/trace.h"
#include "sysemu/arch_init.h"
-#include "sysemu/qtest.h"
#include "sysemu/runstate.h"
#include "sysemu/replay.h"
#include "qemu/cutils.h"
return NULL;
}
-void drive_mark_claimed_by_board(void)
-{
- BlockBackend *blk;
- DriveInfo *dinfo;
-
- for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- dinfo = blk_legacy_dinfo(blk);
- if (dinfo && blk_get_attached_dev(blk)) {
- dinfo->claimed_by_board = true;
- }
- }
-}
-
+/*
+ * Check board claimed all -drive that are meant to be claimed.
+ * Fatal error if any remain unclaimed.
+ */
void drive_check_orphaned(void)
{
BlockBackend *blk;
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
dinfo = blk_legacy_dinfo(blk);
- if (dinfo->is_default || dinfo->type == IF_NONE) {
+ /*
+ * Ignore default drives, because we create certain default
+ * drives unconditionally, then leave them unclaimed. Not the
+ * users fault.
+ * Ignore IF_VIRTIO, because it gets desugared into -device,
+ * so we can leave failing to -device.
+ * Ignore IF_NONE, because leaving unclaimed IF_NONE remains
+ * available for device_add is a feature.
+ */
+ if (dinfo->is_default || dinfo->type == IF_VIRTIO
+ || dinfo->type == IF_NONE) {
continue;
}
if (!blk_get_attached_dev(blk)) {
if_name[dinfo->type], dinfo->bus, dinfo->unit);
loc_pop(&loc);
orphans = true;
- continue;
- }
- if (!dinfo->claimed_by_board && dinfo->type != IF_VIRTIO) {
- loc_push_none(&loc);
- qemu_opts_loc_restore(dinfo->opts);
- warn_report("bogus if=%s is deprecated, use if=none",
- if_name[dinfo->type]);
- loc_pop(&loc);
}
}
blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
blk_rs = blk_get_root_state(blk);
- blk_rs->open_flags = bdrv_flags;
- blk_rs->read_only = read_only;
+ blk_rs->open_flags = bdrv_flags | (read_only ? 0 : BDRV_O_RDWR);
blk_rs->detect_zeroes = detect_zeroes;
qobject_unref(bs_opts);
QemuOpts *devopts;
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
&error_abort);
- if (arch_type == QEMU_ARCH_S390X) {
- qemu_opt_set(devopts, "driver", "virtio-blk-ccw", &error_abort);
- } else {
- qemu_opt_set(devopts, "driver", "virtio-blk-pci", &error_abort);
- }
+ qemu_opt_set(devopts, "driver", "virtio-blk", &error_abort);
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
&error_abort);
}
static void external_snapshot_prepare(BlkActionState *common,
Error **errp)
{
+ int ret;
int flags = 0;
QDict *options = NULL;
Error *local_err = NULL;
s->has_snapshot_node_name ? s->snapshot_node_name : NULL;
if (node_name && !snapshot_node_name) {
- error_setg(errp, "New overlay node name missing");
+ error_setg(errp, "New overlay node-name missing");
goto out;
}
if (snapshot_node_name &&
bdrv_lookup_bs(snapshot_node_name, snapshot_node_name, NULL)) {
- error_setg(errp, "New overlay node name already in use");
+ error_setg(errp, "New overlay node-name already in use");
goto out;
}
goto out;
}
- /* This removes our old bs and adds the new bs. This is an operation that
- * can fail, so we need to do it in .prepare; undoing it for abort is
- * always possible. */
- bdrv_ref(state->new_bs);
- bdrv_append(state->new_bs, state->old_bs, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ ret = bdrv_append(state->new_bs, state->old_bs, errp);
+ if (ret < 0) {
goto out;
}
state->overlay_appended = true;
aio_context = bdrv_get_aio_context(bs);
aio_context_acquire(aio_context);
+ state->bs = bs;
/* Paired with .clean() */
bdrv_drained_begin(bs);
aio_context_acquire(aio_context);
if (set_backing_hd) {
- bdrv_set_backing_hd(target_bs, source, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
+ if (bdrv_set_backing_hd(target_bs, source, errp) < 0) {
goto unref;
}
}
- state->bs = bs;
-
state->job = do_backup_common(qapi_DriveBackup_base(backup),
bs, target_bs, aio_context,
common->block_job_txn, errp);
job_txn_unref(block_job_txn);
}
-void qmp_block_passwd(bool has_device, const char *device,
- bool has_node_name, const char *node_name,
- const char *password, Error **errp)
-{
- error_setg(errp,
- "Setting block passwords directly is no longer supported");
-}
-
BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
const char *name,
Error **errp)
visit_free(v);
}
-void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
+void qmp_blockdev_reopen(BlockdevOptionsList *reopen_list, Error **errp)
{
- BlockDriverState *bs;
- AioContext *ctx;
- QObject *obj;
- Visitor *v = qobject_output_visitor_new(&obj);
- BlockReopenQueue *queue;
- QDict *qdict;
+ BlockReopenQueue *queue = NULL;
+ GSList *drained = NULL;
- /* Check for the selected node name */
- if (!options->has_node_name) {
- error_setg(errp, "Node name not specified");
- goto fail;
- }
+ /* Add each one of the BDS that we want to reopen to the queue */
+ for (; reopen_list != NULL; reopen_list = reopen_list->next) {
+ BlockdevOptions *options = reopen_list->value;
+ BlockDriverState *bs;
+ AioContext *ctx;
+ QObject *obj;
+ Visitor *v;
+ QDict *qdict;
- bs = bdrv_find_node(options->node_name);
- if (!bs) {
- error_setg(errp, "Cannot find node named '%s'", options->node_name);
- goto fail;
- }
+ /* Check for the selected node name */
+ if (!options->has_node_name) {
+ error_setg(errp, "node-name not specified");
+ goto fail;
+ }
- /* Put all options in a QDict and flatten it */
- visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
- visit_complete(v, &obj);
- qdict = qobject_to(QDict, obj);
+ bs = bdrv_find_node(options->node_name);
+ if (!bs) {
+ error_setg(errp, "Failed to find node with node-name='%s'",
+ options->node_name);
+ goto fail;
+ }
- qdict_flatten(qdict);
+ /* Put all options in a QDict and flatten it */
+ v = qobject_output_visitor_new(&obj);
+ visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
+ visit_complete(v, &obj);
+ visit_free(v);
+
+ qdict = qobject_to(QDict, obj);
+
+ qdict_flatten(qdict);
+
+ ctx = bdrv_get_aio_context(bs);
+ aio_context_acquire(ctx);
+
+ bdrv_subtree_drained_begin(bs);
+ queue = bdrv_reopen_queue(queue, bs, qdict, false);
+ drained = g_slist_prepend(drained, bs);
+
+ aio_context_release(ctx);
+ }
/* Perform the reopen operation */
- ctx = bdrv_get_aio_context(bs);
- aio_context_acquire(ctx);
- bdrv_subtree_drained_begin(bs);
- queue = bdrv_reopen_queue(NULL, bs, qdict, false);
bdrv_reopen_multiple(queue, errp);
- bdrv_subtree_drained_end(bs);
- aio_context_release(ctx);
+ queue = NULL;
fail:
- visit_free(v);
+ bdrv_reopen_queue_free(queue);
+ g_slist_free_full(drained, (GDestroyNotify) bdrv_subtree_drained_end);
}
void qmp_blockdev_del(const char *node_name, Error **errp)
bs = bdrv_find_node(node_name);
if (!bs) {
- error_setg(errp, "Cannot find node %s", node_name);
+ error_setg(errp, "Failed to find node with node-name='%s'", node_name);
return;
}
if (bdrv_has_blk(bs)) {
BlockJobInfoList *qmp_query_block_jobs(Error **errp)
{
- BlockJobInfoList *head = NULL, **p_next = &head;
+ BlockJobInfoList *head = NULL, **tail = &head;
BlockJob *job;
for (job = block_job_next(NULL); job; job = block_job_next(job)) {
- BlockJobInfoList *elem;
+ BlockJobInfo *value;
AioContext *aio_context;
if (block_job_is_internal(job)) {
continue;
}
- elem = g_new0(BlockJobInfoList, 1);
aio_context = blk_get_aio_context(job->blk);
aio_context_acquire(aio_context);
- elem->value = block_job_query(job, errp);
+ value = block_job_query(job, errp);
aio_context_release(aio_context);
- if (!elem->value) {
- g_free(elem);
+ if (!value) {
qapi_free_BlockJobInfoList(head);
return NULL;
}
- *p_next = elem;
- p_next = &elem->next;
+ QAPI_LIST_APPEND(tail, value);
}
return head;
bs = bdrv_find_node(node_name);
if (!bs) {
- error_setg(errp, "Cannot find node %s", node_name);
+ error_setg(errp, "Failed to find node with node-name='%s'", node_name);
return;
}