Loading block/rbd.c +100 −50 Original line number Diff line number Diff line Loading @@ -332,71 +332,55 @@ static QemuOptsList runtime_opts = { }, }; static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, QemuOpts *opts, /* FIXME Deprecate and remove keypairs or make it available in QMP. * password_secret should eventually be configurable in opts->location. Support * for it in .bdrv_open will make it work here as well. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_secret, 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; BlockdevCreateOptionsRbd *opts = &options->u.rbd; rados_t cluster; rados_ioctx_t io_ctx; QDict *options = NULL; int ret = 0; int obj_order = 0; int ret; secretid = qemu_opt_get(opts, "password-secret"); assert(options->driver == BLOCKDEV_DRIVER_RBD); if (opts->location->has_snapshot) { error_setg(errp, "Can't use snapshot name for image creation"); return -EINVAL; } /* 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) { /* TODO Remove the limitation */ if (opts->location->has_server) { error_setg(errp, "Can't specify server for image creation"); return -EINVAL; } if (opts->has_cluster_size) { int64_t objsize = opts->cluster_size; if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); ret = -EINVAL; goto exit; return -EINVAL; } if (objsize < 4096) { error_setg(errp, "obj size too small"); ret = -EINVAL; goto exit; return -EINVAL; } 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); ret = rados_create(&cluster, opts->location->user); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; return ret; } /* 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 = rados_conf_read_file(cluster, opts->location->conf); if (opts->location->conf && ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", opts->location->conf); ret = -EIO; goto shutdown; } Loading @@ -407,7 +391,7 @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, goto shutdown; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { if (qemu_rbd_set_auth(cluster, password_secret, errp) < 0) { ret = -EIO; goto shutdown; } Loading @@ -418,24 +402,89 @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, goto shutdown; } ret = rados_ioctx_create(cluster, pool, &io_ctx); ret = rados_ioctx_create(cluster, opts->location->pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); error_setg_errno(errp, -ret, "error opening pool %s", opts->location->pool); goto shutdown; } ret = rbd_create(io_ctx, image_name, bytes, &obj_order); ret = rbd_create(io_ctx, opts->location->image, opts->size, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } rados_ioctx_destroy(io_ctx); ret = 0; shutdown: rados_shutdown(cluster); return ret; } static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp) { return qemu_rbd_do_create(options, NULL, NULL, errp); } static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options; BlockdevCreateOptionsRbd *rbd_opts; BlockdevOptionsRbd *loc; Error *local_err = NULL; const char *keypairs, *password_secret; QDict *options = NULL; int ret = 0; create_options = g_new0(BlockdevCreateOptions, 1); create_options->driver = BLOCKDEV_DRIVER_RBD; rbd_opts = &create_options->u.rbd; rbd_opts->location = g_new0(BlockdevOptionsRbd, 1); password_secret = qemu_opt_get(opts, "password-secret"); /* Read out options */ rbd_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); rbd_opts->cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); rbd_opts->has_cluster_size = (rbd_opts->cluster_size != 0); 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. */ loc = rbd_opts->location; loc->pool = g_strdup(qdict_get_try_str(options, "pool")); loc->conf = g_strdup(qdict_get_try_str(options, "conf")); loc->has_conf = !!loc->conf; loc->user = g_strdup(qdict_get_try_str(options, "user")); loc->has_user = !!loc->user; loc->image = g_strdup(qdict_get_try_str(options, "image")); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); ret = qemu_rbd_do_create(create_options, keypairs, password_secret, errp); if (ret < 0) { goto exit; } exit: QDECREF(options); qapi_free_BlockdevCreateOptions(create_options); return ret; } Loading Loading @@ -1143,6 +1192,7 @@ static BlockDriver bdrv_rbd = { .bdrv_file_open = qemu_rbd_open, .bdrv_close = qemu_rbd_close, .bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .bdrv_co_create = qemu_rbd_co_create, .bdrv_co_create_opts = qemu_rbd_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_get_info = qemu_rbd_getinfo, Loading qapi/block-core.json +18 −1 Original line number Diff line number Diff line Loading @@ -3435,6 +3435,23 @@ '*lazy-refcounts': 'bool', '*refcount-bits': 'int' } } ## # @BlockdevCreateOptionsRbd: # # Driver specific image creation options for rbd/Ceph. # # @location Where to store the new image file. This location cannot # point to a snapshot. # @size Size of the virtual disk in bytes # @cluster-size RBD object size # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsRbd', 'data': { 'location': 'BlockdevOptionsRbd', 'size': 'size', '*cluster-size' : 'size' } } ## # @BlockdevCreateNotSupported: # Loading Loading @@ -3484,7 +3501,7 @@ 'qed': 'BlockdevCreateNotSupported', 'quorum': 'BlockdevCreateNotSupported', 'raw': 'BlockdevCreateNotSupported', 'rbd': 'BlockdevCreateNotSupported', 'rbd': 'BlockdevCreateOptionsRbd', 'replication': 'BlockdevCreateNotSupported', 'sheepdog': 'BlockdevCreateNotSupported', 'ssh': 'BlockdevCreateNotSupported', Loading Loading
block/rbd.c +100 −50 Original line number Diff line number Diff line Loading @@ -332,71 +332,55 @@ static QemuOptsList runtime_opts = { }, }; static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, QemuOpts *opts, /* FIXME Deprecate and remove keypairs or make it available in QMP. * password_secret should eventually be configurable in opts->location. Support * for it in .bdrv_open will make it work here as well. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_secret, 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; BlockdevCreateOptionsRbd *opts = &options->u.rbd; rados_t cluster; rados_ioctx_t io_ctx; QDict *options = NULL; int ret = 0; int obj_order = 0; int ret; secretid = qemu_opt_get(opts, "password-secret"); assert(options->driver == BLOCKDEV_DRIVER_RBD); if (opts->location->has_snapshot) { error_setg(errp, "Can't use snapshot name for image creation"); return -EINVAL; } /* 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) { /* TODO Remove the limitation */ if (opts->location->has_server) { error_setg(errp, "Can't specify server for image creation"); return -EINVAL; } if (opts->has_cluster_size) { int64_t objsize = opts->cluster_size; if ((objsize - 1) & objsize) { /* not a power of 2? */ error_setg(errp, "obj size needs to be power of 2"); ret = -EINVAL; goto exit; return -EINVAL; } if (objsize < 4096) { error_setg(errp, "obj size too small"); ret = -EINVAL; goto exit; return -EINVAL; } 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); ret = rados_create(&cluster, opts->location->user); if (ret < 0) { error_setg_errno(errp, -ret, "error initializing"); goto exit; return ret; } /* 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 = rados_conf_read_file(cluster, opts->location->conf); if (opts->location->conf && ret < 0) { error_setg_errno(errp, -ret, "error reading conf file %s", opts->location->conf); ret = -EIO; goto shutdown; } Loading @@ -407,7 +391,7 @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, goto shutdown; } if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { if (qemu_rbd_set_auth(cluster, password_secret, errp) < 0) { ret = -EIO; goto shutdown; } Loading @@ -418,24 +402,89 @@ static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, goto shutdown; } ret = rados_ioctx_create(cluster, pool, &io_ctx); ret = rados_ioctx_create(cluster, opts->location->pool, &io_ctx); if (ret < 0) { error_setg_errno(errp, -ret, "error opening pool %s", pool); error_setg_errno(errp, -ret, "error opening pool %s", opts->location->pool); goto shutdown; } ret = rbd_create(io_ctx, image_name, bytes, &obj_order); ret = rbd_create(io_ctx, opts->location->image, opts->size, &obj_order); if (ret < 0) { error_setg_errno(errp, -ret, "error rbd create"); } rados_ioctx_destroy(io_ctx); ret = 0; shutdown: rados_shutdown(cluster); return ret; } static int qemu_rbd_co_create(BlockdevCreateOptions *options, Error **errp) { return qemu_rbd_do_create(options, NULL, NULL, errp); } static int coroutine_fn qemu_rbd_co_create_opts(const char *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options; BlockdevCreateOptionsRbd *rbd_opts; BlockdevOptionsRbd *loc; Error *local_err = NULL; const char *keypairs, *password_secret; QDict *options = NULL; int ret = 0; create_options = g_new0(BlockdevCreateOptions, 1); create_options->driver = BLOCKDEV_DRIVER_RBD; rbd_opts = &create_options->u.rbd; rbd_opts->location = g_new0(BlockdevOptionsRbd, 1); password_secret = qemu_opt_get(opts, "password-secret"); /* Read out options */ rbd_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), BDRV_SECTOR_SIZE); rbd_opts->cluster_size = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0); rbd_opts->has_cluster_size = (rbd_opts->cluster_size != 0); 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. */ loc = rbd_opts->location; loc->pool = g_strdup(qdict_get_try_str(options, "pool")); loc->conf = g_strdup(qdict_get_try_str(options, "conf")); loc->has_conf = !!loc->conf; loc->user = g_strdup(qdict_get_try_str(options, "user")); loc->has_user = !!loc->user; loc->image = g_strdup(qdict_get_try_str(options, "image")); keypairs = qdict_get_try_str(options, "=keyvalue-pairs"); ret = qemu_rbd_do_create(create_options, keypairs, password_secret, errp); if (ret < 0) { goto exit; } exit: QDECREF(options); qapi_free_BlockdevCreateOptions(create_options); return ret; } Loading Loading @@ -1143,6 +1192,7 @@ static BlockDriver bdrv_rbd = { .bdrv_file_open = qemu_rbd_open, .bdrv_close = qemu_rbd_close, .bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .bdrv_co_create = qemu_rbd_co_create, .bdrv_co_create_opts = qemu_rbd_co_create_opts, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_get_info = qemu_rbd_getinfo, Loading
qapi/block-core.json +18 −1 Original line number Diff line number Diff line Loading @@ -3435,6 +3435,23 @@ '*lazy-refcounts': 'bool', '*refcount-bits': 'int' } } ## # @BlockdevCreateOptionsRbd: # # Driver specific image creation options for rbd/Ceph. # # @location Where to store the new image file. This location cannot # point to a snapshot. # @size Size of the virtual disk in bytes # @cluster-size RBD object size # # Since: 2.12 ## { 'struct': 'BlockdevCreateOptionsRbd', 'data': { 'location': 'BlockdevOptionsRbd', 'size': 'size', '*cluster-size' : 'size' } } ## # @BlockdevCreateNotSupported: # Loading Loading @@ -3484,7 +3501,7 @@ 'qed': 'BlockdevCreateNotSupported', 'quorum': 'BlockdevCreateNotSupported', 'raw': 'BlockdevCreateNotSupported', 'rbd': 'BlockdevCreateNotSupported', 'rbd': 'BlockdevCreateOptionsRbd', 'replication': 'BlockdevCreateNotSupported', 'sheepdog': 'BlockdevCreateNotSupported', 'ssh': 'BlockdevCreateNotSupported', Loading