static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; const char *pool, *snap, *conf, *user, *image_name, *keypairs; const char *secretid, *filename; QemuOpts *opts; Error *local_err = NULL; char *mon_host = NULL; 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); if (local_err) { r = -EINVAL; error_propagate(errp, local_err); goto exit; } } opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } mon_host = qemu_rbd_mon_host(options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } secretid = qemu_opt_get(opts, "password-secret"); pool = qemu_opt_get(opts, "pool"); conf = qemu_opt_get(opts, "conf"); snap = qemu_opt_get(opts, "snapshot"); user = qemu_opt_get(opts, "user"); image_name = qemu_opt_get(opts, "image"); keypairs = qemu_opt_get(opts, "=keyvalue-pairs"); if (!pool || !image_name) { error_setg(errp, "Parameters 'pool' and 'image' are required"); r = -EINVAL; goto failed_opts; } r = rados_create(&s->cluster, user); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } s->snap = g_strdup(snap); s->image_name = g_strdup(image_name); /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(s->cluster, conf); if (conf && r < 0) { error_setg_errno(errp, -r, "error reading conf file %s", conf); goto failed_shutdown; } r = qemu_rbd_set_keypairs(s->cluster, keypairs, errp); if (r < 0) { goto failed_shutdown; } if (mon_host) { r = rados_conf_set(s->cluster, "mon_host", mon_host); if (r < 0) { goto failed_shutdown; } } if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) { r = -EIO; goto failed_shutdown; } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (flags & BDRV_O_NOCACHE) { rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); } r = rados_connect(s->cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", pool); goto failed_shutdown; } /* 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; } } } qemu_opts_del(opts); return 0; failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); g_free(s->image_name); failed_opts: qemu_opts_del(opts); g_free(mon_host); exit: return r; }
static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, QemuOpts *opts, Error **errp) { Error *local_err = NULL; int64_t bytes = 0; int64_t objsize; int obj_order = 0; const char *pool, *image_name, *conf, *user, *keypairs; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; QDict *options = NULL; int ret = 0; secretid = qemu_opt_get(opts, "password-secret"); /* Read out options */ bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); if (objsize) { if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); ret = -EINVAL; goto exit; } if (objsize < 4096) { error_setg(errp, "obj size too small"); ret = -EINVAL; goto exit; } obj_order = ctz32(objsize); } options = qdict_new(); qemu_rbd_parse_filename(filename, options, &local_err); if (local_err) { ret = -EINVAL; error_propagate(errp, local_err); goto exit; } /* * Caution: while qdict_get_try_str() is fine, getting non-string * types would require more care. When @options come from -blockdev * or blockdev_add, its members are typed according to the QAPI * schema, but when they come from -drive, they're all QString. */ pool = qdict_get_try_str(options, "pool"); conf = qdict_get_try_str(options, "conf"); user = qdict_get_try_str(options, "user"); image_name = qdict_get_try_str(options, "image"); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); ret = rados_create(&cluster, user); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; } /* try default location when conf=NULL, but ignore failure */ ret = rados_conf_read_file(cluster, conf); if (conf && ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", conf); ret = -EIO; goto shutdown; } ret = qemu_rbd_set_keypairs(cluster, keypairs, errp); if (ret < 0) { ret = -EIO; goto shutdown; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { ret = -EIO; goto shutdown; } ret = rados_connect(cluster); if (ret < 0) { error_setg_errno(errp, -ret, "error connecting"); goto shutdown; } ret = rados_ioctx_create(cluster, pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); goto shutdown; } ret = rbd_create(io_ctx, image_name, bytes, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } rados_ioctx_destroy(io_ctx); shutdown: rados_shutdown(cluster); exit: QDECREF(options); return ret; }
static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVRBDState *s = bs->opaque; const char *pool, *snap, *conf, *clientname, *name, *keypairs; const char *secretid; QemuOpts *opts; Error *local_err = NULL; char *mon_host = NULL; int r; opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } mon_host = qemu_rbd_mon_host(options, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } secretid = qemu_opt_get(opts, "password-secret"); pool = qemu_opt_get(opts, "pool"); conf = qemu_opt_get(opts, "conf"); snap = qemu_opt_get(opts, "snapshot"); clientname = qemu_opt_get(opts, "user"); name = qemu_opt_get(opts, "image"); keypairs = qemu_opt_get(opts, "=keyvalue-pairs"); if (!pool || !name) { error_setg(errp, "Parameters 'pool' and 'image' are required"); r = -EINVAL; goto failed_opts; } r = rados_create(&s->cluster, clientname); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } s->snap = g_strdup(snap); s->name = g_strdup(name); /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(s->cluster, conf); if (conf && r < 0) { error_setg_errno(errp, -r, "error reading conf file %s", conf); goto failed_shutdown; } r = qemu_rbd_set_keypairs(s->cluster, keypairs, errp); if (r < 0) { goto failed_shutdown; } if (mon_host) { r = rados_conf_set(s->cluster, "mon_host", mon_host); if (r < 0) { goto failed_shutdown; } } if (qemu_rbd_set_auth(s->cluster, secretid, errp) < 0) { r = -EIO; goto failed_shutdown; } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (flags & BDRV_O_NOCACHE) { rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); } r = rados_connect(s->cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_setg_errno(errp, -r, "error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); qemu_opts_del(opts); return 0; failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); g_free(s->name); failed_opts: qemu_opts_del(opts); g_free(mon_host); return r; }
static int qemu_rbd_connect(rados_t *cluster, rados_ioctx_t *io_ctx, BlockdevOptionsRbd *opts, bool cache, const char *keypairs, const char *secretid, Error **errp) { char *mon_host = NULL; Error *local_err = NULL; int r; if (secretid) { if (opts->key_secret) { error_setg(errp, "Legacy 'password-secret' clashes with 'key-secret'"); return -EINVAL; } opts->key_secret = g_strdup(secretid); opts->has_key_secret = true; } mon_host = qemu_rbd_mon_host(opts, &local_err); if (local_err) { error_propagate(errp, local_err); r = -EINVAL; goto failed_opts; } r = rados_create(cluster, opts->user); if (r < 0) { error_setg_errno(errp, -r, "error initializing"); goto failed_opts; } /* try default location when conf=NULL, but ignore failure */ r = rados_conf_read_file(*cluster, opts->conf); if (opts->has_conf && r < 0) { error_setg_errno(errp, -r, "error reading conf file %s", opts->conf); goto failed_shutdown; } r = qemu_rbd_set_keypairs(*cluster, keypairs, errp); if (r < 0) { goto failed_shutdown; } if (mon_host) { r = rados_conf_set(*cluster, "mon_host", mon_host); if (r < 0) { goto failed_shutdown; } } r = qemu_rbd_set_auth(*cluster, opts, errp); if (r < 0) { goto failed_shutdown; } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (cache) { rados_conf_set(*cluster, "rbd_cache", "true"); } else { rados_conf_set(*cluster, "rbd_cache", "false"); } r = rados_connect(*cluster); if (r < 0) { error_setg_errno(errp, -r, "error connecting"); goto failed_shutdown; } r = rados_ioctx_create(*cluster, opts->pool, io_ctx); if (r < 0) { error_setg_errno(errp, -r, "error opening pool %s", opts->pool); goto failed_shutdown; } return 0; failed_shutdown: rados_shutdown(*cluster); failed_opts: g_free(mon_host); return r; }
static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) { Error *local_err = NULL; int64_t bytes = 0; int64_t objsize; int obj_order = 0; const char *pool, *name, *conf, *clientname, *keypairs; const char *secretid; rados_t cluster; rados_ioctx_t io_ctx; QDict *options = NULL; int ret = 0; secretid = qemu_opt_get(opts, "password-secret"); /* Read out options */ bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); if (objsize) { if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); ret = -EINVAL; goto exit; } if (objsize < 4096) { error_setg(errp, "obj size too small"); ret = -EINVAL; goto exit; } obj_order = ctz32(objsize); } options = qdict_new(); qemu_rbd_parse_filename(filename, options, &local_err); if (local_err) { ret = -EINVAL; error_propagate(errp, local_err); goto exit; } pool = qdict_get_try_str(options, "pool"); conf = qdict_get_try_str(options, "conf"); clientname = qdict_get_try_str(options, "user"); name = qdict_get_try_str(options, "image"); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); ret = rados_create(&cluster, clientname); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; } /* try default location when conf=NULL, but ignore failure */ ret = rados_conf_read_file(cluster, conf); if (conf && ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", conf); ret = -EIO; goto shutdown; } ret = qemu_rbd_set_keypairs(cluster, keypairs, errp); if (ret < 0) { ret = -EIO; goto shutdown; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { ret = -EIO; goto shutdown; } ret = rados_connect(cluster); if (ret < 0) { error_setg_errno(errp, -ret, "error connecting"); goto shutdown; } ret = rados_ioctx_create(cluster, pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); goto shutdown; } ret = rbd_create(io_ctx, name, bytes, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } rados_ioctx_destroy(io_ctx); shutdown: rados_shutdown(cluster); exit: QDECREF(options); return ret; }