/* Takes the ownership of bs_opts */
static DriveInfo *blockdev_init(const char *file, QDict *bs_opts,
- BlockInterfaceType type,
Error **errp)
{
const char *buf;
* stay in bs_opts for processing by bdrv_open(). */
id = qdict_get_try_str(bs_opts, "id");
opts = qemu_opts_create(&qemu_common_drive_opts, id, 1, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
return NULL;
}
qemu_opts_absorb_qdict(opts, bs_opts, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
on_write_error = BLOCKDEV_ON_ERROR_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
- if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
- error_setg(errp, "werror is not supported by this bus type");
- goto early_err;
- }
-
on_write_error = parse_block_error_action(buf, 0, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
on_read_error = BLOCKDEV_ON_ERROR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI && type != IF_NONE) {
- error_report("rerror is not supported by this bus type");
- goto early_err;
- }
-
on_read_error = parse_block_error_action(buf, 1, &error);
- if (error_is_set(&error)) {
+ if (error) {
error_propagate(errp, error);
goto early_err;
}
}
+ if (bdrv_find_node(qemu_opts_id(opts))) {
+ error_setg(errp, "device id=%s is conflicting with a node-name",
+ qemu_opts_id(opts));
+ goto early_err;
+ }
+
/* init */
dinfo = g_malloc0(sizeof(*dinfo));
dinfo->id = g_strdup(qemu_opts_id(opts));
dinfo->bdrv = bdrv_new(dinfo->id);
dinfo->bdrv->open_flags = snapshot ? BDRV_O_SNAPSHOT : 0;
dinfo->bdrv->read_only = ro;
- dinfo->type = type;
dinfo->refcount = 1;
if (serial != NULL) {
dinfo->serial = g_strdup(serial);
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
QINCREF(bs_opts);
- ret = bdrv_open(dinfo->bdrv, file, bs_opts, bdrv_flags, drv, &error);
+ ret = bdrv_open(&dinfo->bdrv, file, NULL, bs_opts, bdrv_flags, drv, &error);
if (ret < 0) {
error_setg(errp, "could not open disk image %s: %s",
.name = "read-only",
.type = QEMU_OPT_BOOL,
.help = "open drive file as read-only",
+ },{
+ .name = "rerror",
+ .type = QEMU_OPT_STRING,
+ .help = "read error action",
+ },{
+ .name = "werror",
+ .type = QEMU_OPT_STRING,
+ .help = "write error action",
},{
.name = "copy-on-read",
.type = QEMU_OPT_BOOL,
int cyls, heads, secs, translation;
int max_devs, bus_id, unit_id, index;
const char *devaddr;
+ const char *werror, *rerror;
bool read_only = false;
bool copy_on_read;
const char *filename;
legacy_opts = qemu_opts_create(&qemu_legacy_drive_opts, NULL, 0,
&error_abort);
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
goto fail;
translation = BIOS_ATA_TRANSLATION_NONE;
} else if (!strcmp(value, "lba")) {
translation = BIOS_ATA_TRANSLATION_LBA;
+ } else if (!strcmp(value, "large")) {
+ translation = BIOS_ATA_TRANSLATION_LARGE;
+ } else if (!strcmp(value, "rechs")) {
+ translation = BIOS_ATA_TRANSLATION_RECHS;
} else if (!strcmp(value, "auto")) {
translation = BIOS_ATA_TRANSLATION_AUTO;
} else {
filename = qemu_opt_get(legacy_opts, "file");
+ /* Check werror/rerror compatibility with if=... */
+ werror = qemu_opt_get(legacy_opts, "werror");
+ if (werror != NULL) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO &&
+ type != IF_NONE) {
+ error_report("werror is not supported by this bus type");
+ goto fail;
+ }
+ qdict_put(bs_opts, "werror", qstring_from_str(werror));
+ }
+
+ rerror = qemu_opt_get(legacy_opts, "rerror");
+ if (rerror != NULL) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI &&
+ type != IF_NONE) {
+ error_report("rerror is not supported by this bus type");
+ goto fail;
+ }
+ qdict_put(bs_opts, "rerror", qstring_from_str(rerror));
+ }
+
/* Actual block device init: Functionality shared with blockdev-add */
- dinfo = blockdev_init(filename, bs_opts, type, &local_err);
+ dinfo = blockdev_init(filename, bs_opts, &local_err);
if (dinfo == NULL) {
- if (error_is_set(&local_err)) {
+ if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
}
goto fail;
} else {
- assert(!error_is_set(&local_err));
+ assert(!local_err);
}
/* Set legacy DriveInfo fields */
dinfo->secs = secs;
dinfo->trans = translation;
+ dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
dinfo->devaddr = devaddr;
}
ret = bdrv_snapshot_find_by_id_and_name(bs, id, name, &sn, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
}
bdrv_snapshot_delete(bs, id, name, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return NULL;
}
state->old_bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
state->old_bs->filename,
state->old_bs->drv->format_name,
NULL, -1, flags, &local_err, false);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
qstring_from_str(snapshot_node_name));
}
- /* We will manually add the backing_hd field to the bs later */
- state->new_bs = bdrv_new("");
/* TODO Inherit bs->options or only take explicit options with an
* extended QMP command? */
- ret = bdrv_open(state->new_bs, new_image_file, options,
+ assert(state->new_bs == NULL);
+ ret = bdrv_open(&state->new_bs, new_image_file, NULL, options,
flags | BDRV_O_NO_BACKING, drv, &local_err);
+ /* We will manually add the backing_hd field to the bs later */
if (ret != 0) {
error_propagate(errp, local_err);
}
-
- QDECREF(options);
}
static void external_snapshot_commit(BlkTransactionState *common)
backup->has_on_source_error, backup->on_source_error,
backup->has_on_target_error, backup->on_target_error,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
state->bs = NULL;
state->job = NULL;
QSIMPLEQ_INSERT_TAIL(&snap_bdrv_states, state, entry);
state->ops->prepare(state, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto delete_and_fail;
}
bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
Error *local_err = NULL;
int ret;
- ret = bdrv_open(bs, filename, NULL, bdrv_flags, drv, &local_err);
+ ret = bdrv_open(&bs, filename, NULL, NULL, bdrv_flags, drv, &local_err);
if (ret < 0) {
error_propagate(errp, local_err);
return;
}
eject_device(bs, 0, &err);
- if (error_is_set(&err)) {
+ if (err) {
error_propagate(errp, err);
return;
}
bs = bdrv_lookup_bs(has_device ? device : NULL,
has_node_name ? node_name : NULL,
&local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
stream_start(bs, base_bs, base, has_speed ? speed : 0,
on_error, block_job_cb, bs, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
}
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
- target_bs = bdrv_new("");
- ret = bdrv_open(target_bs, target, NULL, flags, drv, &local_err);
+ target_bs = NULL;
+ ret = bdrv_open(&target_bs, target, NULL, NULL, flags, drv, &local_err);
if (ret < 0) {
- bdrv_unref(target_bs);
error_propagate(errp, local_err);
return;
}
}
}
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
return;
}
/* Mirroring takes care of copy-on-write using the source's backing
* file.
*/
- target_bs = bdrv_new("");
- ret = bdrv_open(target_bs, target, NULL, flags | BDRV_O_NO_BACKING, drv,
- &local_err);
+ target_bs = NULL;
+ ret = bdrv_open(&target_bs, target, NULL, NULL, flags | BDRV_O_NO_BACKING,
+ drv, &local_err);
if (ret < 0) {
- bdrv_unref(target_bs);
error_propagate(errp, local_err);
return;
}
void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
{
QmpOutputVisitor *ov = qmp_output_visitor_new();
+ DriveInfo *dinfo;
QObject *obj;
QDict *qdict;
Error *local_err = NULL;
*
* For now, simply forbidding the combination for all drivers will do. */
if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
- bool direct = options->cache->has_direct && options->cache->direct;
- if (!options->has_cache && !direct) {
+ bool direct = options->has_cache &&
+ options->cache->has_direct &&
+ options->cache->direct;
+ if (!direct) {
error_setg(errp, "aio=native requires cache.direct=true");
goto fail;
}
visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
&options, NULL, &local_err);
- if (error_is_set(&local_err)) {
+ if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
qdict_flatten(qdict);
- blockdev_init(NULL, qdict, IF_NONE, &local_err);
- if (error_is_set(&local_err)) {
+ dinfo = blockdev_init(NULL, qdict, &local_err);
+ if (local_err) {
error_propagate(errp, local_err);
goto fail;
}
+ if (bdrv_key_required(dinfo->bdrv)) {
+ drive_uninit(dinfo);
+ error_setg(errp, "blockdev-add doesn't support encrypted devices");
+ goto fail;
+ }
+
fail:
qmp_output_visitor_cleanup(ov);
}