All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, mreitz@redhat.com, pkrempa@redhat.com,
	eblake@redhat.com, jcody@redhat.com, jdurgin@redhat.com,
	mitake.hitoshi@lab.ntt.co.jp, namei.unix@gmail.com,
	qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH v3 22/36] rbd: Support .bdrv_co_create
Date: Fri, 23 Feb 2018 20:25:35 +0100	[thread overview]
Message-ID: <20180223192549.26666-23-kwolf@redhat.com> (raw)
In-Reply-To: <20180223192549.26666-1-kwolf@redhat.com>

This adds the .bdrv_co_create driver callback to rbd, which enables
image creation over QMP.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
---
 qapi/block-core.json |  19 ++++++-
 block/rbd.c          | 146 ++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 116 insertions(+), 49 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 74021c51d7..6c0c16ebe3 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3436,6 +3436,23 @@
             '*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:
 #
 # This is used for all drivers that don't support creating images.
@@ -3484,7 +3501,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 9b247f020d..ee71dc8941 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -332,69 +332,55 @@ 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.
+ * 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;
     }
@@ -405,7 +391,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, password_secret, errp) < 0) {
         ret = -EIO;
         goto shutdown;
     }
@@ -416,24 +402,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, 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, *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;
 }
 
@@ -1144,6 +1193,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,
-- 
2.13.6

  parent reply	other threads:[~2018-02-23 19:26 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-23 19:25 [Qemu-devel] [PATCH v3 00/36] x-blockdev-create for protocols and qcow2 Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 01/36] block/qapi: Introduce BlockdevCreateOptions Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 02/36] block/qapi: Add qcow2 create options to schema Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 03/36] qcow2: Let qcow2_create() handle protocol layer Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 04/36] qcow2: Pass BlockdevCreateOptions to qcow2_create2() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 05/36] qcow2: Use BlockdevRef in qcow2_create2() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 06/36] qcow2: Use QCryptoBlockCreateOptions " Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 07/36] qcow2: Handle full/falloc preallocation " Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 08/36] util: Add qemu_opts_to_qdict_filtered() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 09/36] test-qemu-opts: Test qemu_opts_append() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 10/36] test-qemu-opts: Test qemu_opts_to_qdict_filtered() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 11/36] qdict: Introduce qdict_rename_keys() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 12/36] qcow2: Use visitor for options in qcow2_create() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 13/36] block: Make bdrv_is_whitelisted() public Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 14/36] block: x-blockdev-create QMP command Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 15/36] file-posix: Support .bdrv_co_create Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 16/36] file-win32: " Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 17/36] gluster: " Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 18/36] rbd: Fix use after free in qemu_rbd_set_keypairs() error path Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 19/36] rbd: Factor out qemu_rbd_connect() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 20/36] rbd: Remove non-schema options from runtime_opts Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 21/36] rbd: Pass BlockdevOptionsRbd to qemu_rbd_connect() Kevin Wolf
2018-02-26 12:23   ` Max Reitz
2018-02-23 19:25 ` Kevin Wolf [this message]
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 23/36] rbd: Assign s->snap/image_name in qemu_rbd_open() Kevin Wolf
2018-02-26 12:24   ` Max Reitz
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 24/36] rbd: Use qemu_rbd_connect() in qemu_rbd_do_create() Kevin Wolf
2018-02-26 12:25   ` Max Reitz
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 25/36] nfs: Use QAPI options in nfs_client_open() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 26/36] nfs: Support .bdrv_co_create Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 27/36] sheepdog: QAPIfy "redundancy" create option Kevin Wolf
2018-02-26 12:28   ` Max Reitz
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 28/36] sheepdog: Support .bdrv_co_create Kevin Wolf
2018-02-26 12:30   ` Max Reitz
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 29/36] ssh: Use QAPI BlockdevOptionsSsh object Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 30/36] ssh: QAPIfy host-key-check option Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 31/36] ssh: Pass BlockdevOptionsSsh to connect_to_ssh() Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 32/36] ssh: Support .bdrv_co_create Kevin Wolf
2018-02-26 12:43   ` Max Reitz
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 33/36] file-posix: Fix no-op bdrv_truncate() with falloc preallocation Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 34/36] block: Fail bdrv_truncate() with negative size Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 35/36] qemu-iotests: Test qcow2 over file image creation with QMP Kevin Wolf
2018-02-23 19:25 ` [Qemu-devel] [PATCH v3 36/36] qemu-iotests: Test ssh image creation over QMP Kevin Wolf
2018-02-26 12:55   ` Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180223192549.26666-23-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=eblake@redhat.com \
    --cc=jcody@redhat.com \
    --cc=jdurgin@redhat.com \
    --cc=mitake.hitoshi@lab.ntt.co.jp \
    --cc=mreitz@redhat.com \
    --cc=namei.unix@gmail.com \
    --cc=pkrempa@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.