static int qemu_rbd_convert_options(QDict *options, BlockdevOptionsRbd **opts, Error **errp) { Visitor *v; Error *local_err = NULL; /* Convert the remaining options into a QAPI object */ v = qobject_input_visitor_new_flat_confused(options, errp); if (!v) { return -EINVAL; } visit_type_BlockdevOptionsRbd(v, NULL, opts, &local_err); visit_free(v); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } return 0; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; BlockdevOptionsRbd *opts = NULL; Visitor *v; QObject *crumpled = NULL; const QDictEntry *e; Error *local_err = NULL; const char *filename; char *keypairs, *secretid; int r; /* If we are given a filename, parse the filename, with precedence given to * filename encoded options */ filename = qdict_get_try_str(options, "filename"); if (filename) { warn_report("'filename' option specified. " "This is an unsupported option, and may be deprecated " "in the future"); qemu_rbd_parse_filename(filename, options, &local_err); qdict_del(options, "filename"); if (local_err) { error_propagate(errp, local_err); return -EINVAL; } } keypairs = g_strdup(qdict_get_try_str(options, "=keyvalue-pairs")); if (keypairs) { qdict_del(options, "=keyvalue-pairs"); } secretid = g_strdup(qdict_get_try_str(options, "password-secret")); if (secretid) { qdict_del(options, "password-secret"); } /* Convert the remaining options into a QAPI object */ crumpled = qdict_crumple(options, errp); if (crumpled == NULL) { r = -EINVAL; goto out; } v = qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); visit_free(v); qobject_unref(crumpled); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto out; } /* Remove the processed options from the QDict (the visitor processes * _all_ options in the QDict) */ while ((e = qdict_first(options))) { qdict_del(options, e->key); } r = qemu_rbd_connect(&s->cluster, &s->io_ctx, opts, !(flags & BDRV_O_NOCACHE), keypairs, secretid, errp); if (r < 0) { goto out; } s->snap = g_strdup(opts->snapshot); s->image_name = g_strdup(opts->image); /* rbd_open is always r/w */ r = rbd_open(s->io_ctx, s->image_name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->image_name); goto failed_open; } /* If we are using an rbd snapshot, we must be r/o, otherwise * leave as-is */ if (s->snap != NULL) { if (!bdrv_is_read_only(bs)) { error_report("Opening rbd snapshots without an explicit " "read-only=on option is deprecated. Future versions " "will refuse to open the image instead of " "automatically marking the image read-only."); r = bdrv_set_read_only(bs, true, &local_err); if (r < 0) { error_propagate(errp, local_err); goto failed_open; } } } r = 0; goto out; failed_open: rados_ioctx_destroy(s->io_ctx); g_free(s->snap); g_free(s->image_name); rados_shutdown(s->cluster); out: qapi_free_BlockdevOptionsRbd(opts); g_free(keypairs); g_free(secretid); return r; }