From patchwork Thu Feb 8 19:23:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Wolf X-Patchwork-Id: 871107 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zcpkt3gcLz9sP1 for ; Fri, 9 Feb 2018 06:52:38 +1100 (AEDT) Received: from localhost ([::1]:40589 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ejsFH-0001Ti-3X for incoming@patchwork.ozlabs.org; Thu, 08 Feb 2018 14:52:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58002) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ejroM-0003Ow-FD for qemu-devel@nongnu.org; Thu, 08 Feb 2018 14:24:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ejroK-0001ec-UU for qemu-devel@nongnu.org; Thu, 08 Feb 2018 14:24:46 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52640 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ejroG-0001UK-6R; Thu, 08 Feb 2018 14:24:40 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BB1FF4040093; Thu, 8 Feb 2018 19:24:39 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-74.ams2.redhat.com [10.36.117.74]) by smtp.corp.redhat.com (Postfix) with ESMTP id 04FEDB3013; Thu, 8 Feb 2018 19:24:36 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Thu, 8 Feb 2018 20:23:16 +0100 Message-Id: <20180208192328.16550-16-kwolf@redhat.com> In-Reply-To: <20180208192328.16550-1-kwolf@redhat.com> References: <20180208192328.16550-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Thu, 08 Feb 2018 19:24:39 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Thu, 08 Feb 2018 19:24:39 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 15/27] rbd: Support .bdrv_co_create X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, jdurgin@redhat.com, pkrempa@redhat.com, mitake.hitoshi@lab.ntt.co.jp, jcody@redhat.com, qemu-devel@nongnu.org, mreitz@redhat.com, namei.unix@gmail.com Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This adds the .bdrv_co_create driver callback to rbd, which enables image creation over QMP. Signed-off-by: Kevin Wolf Reviewed-by: Max Reitz --- qapi/block-core.json | 20 +++++++- block/rbd.c | 137 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 49 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 5b4cd6bd12..370fcd9584 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3415,6 +3415,24 @@ '*refcount-bits': 'int' } } ## +# @BlockdevCreateOptionsRbd: +# +# Driver specific image creation options for rbd/Ceph. +# +# @location Where to store the new image file +# @size Size of the virtual disk in bytes +# @password-secret ID of secret providing the password +# @cluster_size RBD object size +# +# Since: 2.12 +## +{ 'struct': 'BlockdevCreateOptionsRbd', + 'data': { 'location': 'BlockdevOptionsRbd', + 'size': 'size', + '*password-secret': 'str', + '*cluster-size' : 'size' } } + +## # @BlockdevCreateNotSupported: # # This is used for all drivers that don't support creating images. @@ -3462,7 +3480,7 @@ 'qed': 'BlockdevCreateNotSupported', 'quorum': 'BlockdevCreateNotSupported', 'raw': 'BlockdevCreateNotSupported', - 'rbd': 'BlockdevCreateNotSupported', + 'rbd': 'BlockdevCreateOptionsRbd', 'replication': 'BlockdevCreateNotSupported', 'sheepdog': 'BlockdevCreateNotSupported', 'ssh': 'BlockdevCreateNotSupported', diff --git a/block/rbd.c b/block/rbd.c index a76a5e8755..c164f70167 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -348,69 +348,46 @@ static QemuOptsList runtime_opts = { }, }; -static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) +/* FIXME Deprecate and remove keypairs or make it available in QMP */ +static int qemu_rbd_do_create(BlockdevCreateOptions *options, + const char *keypairs, 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) { + 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; } @@ -421,7 +398,7 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) goto shutdown; } - if (qemu_rbd_set_auth(cluster, secretid, errp) < 0) { + if (qemu_rbd_set_auth(cluster, opts->password_secret, errp) < 0) { ret = -EIO; goto shutdown; } @@ -432,24 +409,87 @@ static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) 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, errp); +} + +static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp) +{ + BlockdevCreateOptions *create_options; + BlockdevCreateOptionsRbd *rbd_opts; + BlockdevOptionsRbd *loc; + Error *local_err = NULL; + const char *keypairs; + 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); + + rbd_opts->password_secret = (char *) 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 = !!rbd_opts->location->conf; + loc->user = g_strdup(qdict_get_try_str(options, "user")); + loc->has_user = !!rbd_opts->location->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, errp); + if (ret < 0) { + goto exit; + } exit: QDECREF(options); + qapi_free_BlockdevCreateOptions(create_options); return ret; } @@ -1130,6 +1170,7 @@ static BlockDriver bdrv_rbd = { .bdrv_close = qemu_rbd_close, .bdrv_reopen_prepare = qemu_rbd_reopen_prepare, .bdrv_create = qemu_rbd_create, + .bdrv_co_create = qemu_rbd_co_create, .bdrv_has_zero_init = bdrv_has_zero_init_1, .bdrv_get_info = qemu_rbd_getinfo, .create_opts = &qemu_rbd_create_opts,