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 19/27] sheepdog: Support .bdrv_co_create
Date: Thu,  8 Feb 2018 20:23:20 +0100	[thread overview]
Message-ID: <20180208192328.16550-20-kwolf@redhat.com> (raw)
In-Reply-To: <20180208192328.16550-1-kwolf@redhat.com>

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

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json |  24 +++++-
 block/sheepdog.c     | 209 ++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 170 insertions(+), 63 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7d004dddf9..08217e3e38 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3492,6 +3492,28 @@
             'erasure-coded': 'SheepdogRedundancyErasureCoded' } }
 
 ##
+# @BlockdevCreateOptionsSheepdog:
+#
+# Driver specific image creation options for Sheepdog.
+#
+# @location         Where to store the new image file
+# @size             Size of the virtual disk in bytes
+# @backing_file     File name of a base image
+# @preallocation    Preallocation mode (allowed values: off, full)
+# @redundancy       Redundancy of the image
+# @object-size      Object size of the image
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsSheepdog',
+  'data': { 'location':         'BlockdevOptionsSheepdog',
+            'size':             'size',
+            '*backing-file':    'str',
+            '*preallocation':   'PreallocMode',
+            '*redundancy':      'SheepdogRedundancy',
+            '*object-size':     'size' } }
+
+##
 # @BlockdevCreateNotSupported:
 #
 # This is used for all drivers that don't support creating images.
@@ -3541,7 +3563,7 @@
       'raw':            'BlockdevCreateNotSupported',
       'rbd':            'BlockdevCreateOptionsRbd',
       'replication':    'BlockdevCreateNotSupported',
-      'sheepdog':       'BlockdevCreateNotSupported',
+      'sheepdog':       'BlockdevCreateOptionsSheepdog',
       'ssh':            'BlockdevCreateNotSupported',
       'throttle':       'BlockdevCreateNotSupported',
       'vdi':            'BlockdevCreateNotSupported',
diff --git a/block/sheepdog.c b/block/sheepdog.c
index dc0348f120..05129dc809 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -15,8 +15,9 @@
 #include "qemu/osdep.h"
 #include "qapi-visit.h"
 #include "qapi/error.h"
-#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/types.h"
 #include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
 #include "qemu/uri.h"
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
@@ -532,23 +533,6 @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVSheepdogState *s,
     qemu_co_mutex_unlock(&s->queue_lock);
 }
 
-static SocketAddress *sd_socket_address(const char *path,
-                                        const char *host, const char *port)
-{
-    SocketAddress *addr = g_new0(SocketAddress, 1);
-
-    if (path) {
-        addr->type = SOCKET_ADDRESS_TYPE_UNIX;
-        addr->u.q_unix.path = g_strdup(path);
-    } else {
-        addr->type = SOCKET_ADDRESS_TYPE_INET;
-        addr->u.inet.host = g_strdup(host ?: SD_DEFAULT_ADDR);
-        addr->u.inet.port = g_strdup(port ?: stringify(SD_DEFAULT_PORT));
-    }
-
-    return addr;
-}
-
 static SocketAddress *sd_server_config(QDict *options, Error **errp)
 {
     QDict *server = NULL;
@@ -1825,7 +1809,7 @@ static int do_sd_create(BDRVSheepdogState *s, uint32_t *vdi_id, int snapshot,
     return 0;
 }
 
-static int sd_prealloc(const char *filename, Error **errp)
+static int sd_prealloc(BlockdevOptionsSheepdog *location, Error **errp)
 {
     BlockBackend *blk = NULL;
     BDRVSheepdogState *base = NULL;
@@ -1834,9 +1818,26 @@ static int sd_prealloc(const char *filename, Error **errp)
     uint32_t object_size;
     int64_t vdi_size;
     void *buf = NULL;
+    Visitor *v;
+    QObject *obj = NULL;
+    QDict *qdict;
+    Error *local_err = NULL;
     int ret;
 
-    blk = blk_new_open(filename, NULL, NULL,
+    v = qobject_output_visitor_new(&obj);
+    visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err);
+    visit_free(v);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        qobject_decref(obj);
+        return -EINVAL;
+    }
+
+    qdict = qobject_to_qdict(obj);
+    qdict_flatten(qdict);
+
+    blk = blk_new_open(NULL, NULL, qdict,
                        BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, errp);
     if (blk == NULL) {
         ret = -EIO;
@@ -1939,9 +1940,9 @@ static int parse_redundancy(BDRVSheepdogState *s, SheepdogRedundancy *opt)
  * # create a erasure coded vdi with x data strips and y parity strips
  * -o redundancy=x:y (x must be one of {2,4,8,16} and 1 <= y < SD_EC_MAX_STRIP)
  */
-static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
+static SheepdogRedundancy *parse_redundancy_str(const char *opt)
 {
-    struct SheepdogRedundancy redundancy;
+    SheepdogRedundancy *redundancy;
     const char *n1, *n2;
     long copy, parity;
     char p[10];
@@ -1951,14 +1952,15 @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
     n2 = strtok(NULL, ":");
 
     if (!n1) {
-        return -EINVAL;
+        return NULL;
     }
 
     /* FIXME fix error checking by switching to qemu_strtol() */
     copy = strtol(n1, NULL, 10);
 
+    redundancy = g_new0(SheepdogRedundancy, 1);
     if (!n2) {
-        redundancy = (SheepdogRedundancy) {
+        *redundancy = (SheepdogRedundancy) {
             .type               = SHEEPDOG_REDUNDANCY_TYPE_FULL,
             .u.full.copies      = copy,
         };
@@ -1966,7 +1968,7 @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
         /* FIXME fix error checking by switching to qemu_strtol() */
         parity = strtol(n2, NULL, 10);
 
-        redundancy = (SheepdogRedundancy) {
+        *redundancy = (SheepdogRedundancy) {
             .type               = SHEEPDOG_REDUNDANCY_TYPE_ERASURE_CODED,
             .u.erasure_coded    = {
                 .data_strips    = copy,
@@ -1975,17 +1977,19 @@ static int parse_redundancy_str(BDRVSheepdogState *s, const char *opt)
         };
     }
 
-    return parse_redundancy(s, &redundancy);
+    return redundancy;
 }
 
-static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
+static int parse_block_size_shift(BDRVSheepdogState *s,
+                                  BlockdevCreateOptionsSheepdog *opts)
 {
     struct SheepdogInode *inode = &s->inode;
     uint64_t object_size;
     int obj_order;
 
-    object_size = qemu_opt_get_size_del(opt, BLOCK_OPT_OBJECT_SIZE, 0);
-    if (object_size) {
+    if (opts->has_object_size) {
+        object_size = opts->object_size;
+
         if ((object_size - 1) & object_size) {    /* not a power of 2? */
             return -EINVAL;
         }
@@ -1999,57 +2003,55 @@ static int parse_block_size_shift(BDRVSheepdogState *s, QemuOpts *opt)
     return 0;
 }
 
-static int sd_create(const char *filename, QemuOpts *opts,
-                     Error **errp)
+static int sd_co_create(BlockdevCreateOptions *options, Error **errp)
 {
-    Error *err = NULL;
+    BlockdevCreateOptionsSheepdog *opts = &options->u.sheepdog;
     int ret = 0;
     uint32_t vid = 0;
     char *backing_file = NULL;
     char *buf = NULL;
     BDRVSheepdogState *s;
-    SheepdogConfig cfg;
     uint64_t max_vdi_size;
     bool prealloc = false;
 
+    assert(options->driver == BLOCKDEV_DRIVER_SHEEPDOG);
+
     s = g_new0(BDRVSheepdogState, 1);
 
-    if (strstr(filename, "://")) {
-        sd_parse_uri(&cfg, filename, &err);
-    } else {
-        parse_vdiname(&cfg, filename, &err);
-    }
-    if (err) {
-        error_propagate(errp, err);
+    /* Steal SocketAddress from QAPI, set NULL to prevent double free */
+    s->addr = opts->location->server;
+    opts->location->server = NULL;
+
+    if (strlen(opts->location->vdi) >= sizeof(s->name)) {
+        error_setg(errp, "'vdi' string too long");
+        ret = -EINVAL;
         goto out;
     }
+    pstrcpy(s->name, sizeof(s->name), opts->location->vdi);
 
-    buf = cfg.port ? g_strdup_printf("%d", cfg.port) : NULL;
-    s->addr = sd_socket_address(cfg.path, cfg.host, buf);
-    g_free(buf);
-    strcpy(s->name, cfg.vdi);
-    sd_config_done(&cfg);
+    s->inode.vdi_size = opts->size;
+    backing_file = opts->backing_file;
 
-    s->inode.vdi_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
-                                 BDRV_SECTOR_SIZE);
-    backing_file = qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE);
-    buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
-    if (!buf || !strcmp(buf, "off")) {
+    if (!opts->has_preallocation) {
+        opts->preallocation = PREALLOC_MODE_OFF;
+    }
+    switch (opts->preallocation) {
+    case PREALLOC_MODE_OFF:
         prealloc = false;
-    } else if (!strcmp(buf, "full")) {
+        break;
+    case PREALLOC_MODE_FULL:
         prealloc = true;
-    } else {
-        error_setg(errp, "Invalid preallocation mode: '%s'", buf);
+        break;
+    default:
+        error_setg(errp, "Preallocation mode not supported for Sheepdog");
         ret = -EINVAL;
         goto out;
     }
 
-    g_free(buf);
-    buf = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
-    if (buf) {
-        ret = parse_redundancy_str(s, buf);
+    if (opts->has_redundancy) {
+        ret = parse_redundancy(s, opts->redundancy);
         if (ret < 0) {
-            error_setg(errp, "Invalid redundancy mode: '%s'", buf);
+            error_setg(errp, "Invalid redundancy mode");
             goto out;
         }
     }
@@ -2061,20 +2063,20 @@ static int sd_create(const char *filename, QemuOpts *opts,
         goto out;
     }
 
-    if (backing_file) {
+    if (opts->has_backing_file) {
         BlockBackend *blk;
         BDRVSheepdogState *base;
         BlockDriver *drv;
 
         /* Currently, only Sheepdog backing image is supported. */
-        drv = bdrv_find_protocol(backing_file, true, NULL);
+        drv = bdrv_find_protocol(opts->backing_file, true, NULL);
         if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
             error_setg(errp, "backing_file must be a sheepdog image");
             ret = -EINVAL;
             goto out;
         }
 
-        blk = blk_new_open(backing_file, NULL, NULL,
+        blk = blk_new_open(opts->backing_file, NULL, NULL,
                            BDRV_O_PROTOCOL, errp);
         if (blk == NULL) {
             ret = -EIO;
@@ -2142,15 +2144,95 @@ static int sd_create(const char *filename, QemuOpts *opts,
     }
 
     if (prealloc) {
-        ret = sd_prealloc(filename, errp);
+        ret = sd_prealloc(opts->location, errp);
     }
 out:
     g_free(backing_file);
     g_free(buf);
+    g_free(s->addr);
     g_free(s);
     return ret;
 }
 
+static int sd_create(const char *filename, QemuOpts *opts,
+                     Error **errp)
+{
+    BlockdevCreateOptions *create_options = NULL;
+    QDict *qdict, *location_qdict;
+    QObject *crumpled;
+    Visitor *v;
+    const char *redundancy;
+    Error *local_err = NULL;
+    int ret;
+
+    redundancy = qemu_opt_get_del(opts, BLOCK_OPT_REDUNDANCY);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_put_str(qdict, "driver", "sheepdog");
+
+    location_qdict = qdict_new();
+    qdict_put(qdict, "location", location_qdict);
+
+    sd_parse_filename(filename, location_qdict, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    qdict_flatten(qdict);
+
+    /* Change legacy command line options into QMP ones */
+    static const QDictRenames opt_renames[] = {
+        { BLOCK_OPT_BACKING_FILE,       "backing-file" },
+        { BLOCK_OPT_OBJECT_SIZE,        "object-size" },
+        { NULL, NULL },
+    };
+
+    if (!qdict_rename_keys(qdict, opt_renames, errp)) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    /* Get the QAPI object */
+    crumpled = qdict_crumple(qdict, errp);
+    if (crumpled == NULL) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    v = qobject_input_visitor_new_keyval(crumpled);
+    visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err);
+    visit_free(v);
+    qobject_decref(crumpled);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    create_options->u.sheepdog.size =
+        ROUND_UP(create_options->u.sheepdog.size, BDRV_SECTOR_SIZE);
+
+    if (redundancy) {
+        create_options->u.sheepdog.has_redundancy = true;
+        create_options->u.sheepdog.redundancy =
+            parse_redundancy_str(redundancy);
+        if (create_options->u.sheepdog.redundancy == NULL) {
+            error_setg(errp, "Invalid redundancy mode");
+            ret = -EINVAL;
+            goto fail;
+        }
+    }
+
+    ret = sd_co_create(create_options, errp);
+fail:
+    qapi_free_BlockdevCreateOptions(create_options);
+    QDECREF(qdict);
+    return ret;
+}
+
 static void sd_close(BlockDriverState *bs)
 {
     Error *local_err = NULL;
@@ -3122,6 +3204,7 @@ static BlockDriver bdrv_sheepdog = {
     .bdrv_reopen_abort            = sd_reopen_abort,
     .bdrv_close                   = sd_close,
     .bdrv_create                  = sd_create,
+    .bdrv_co_create               = sd_co_create,
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
     .bdrv_getlength               = sd_getlength,
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
@@ -3158,6 +3241,7 @@ static BlockDriver bdrv_sheepdog_tcp = {
     .bdrv_reopen_abort            = sd_reopen_abort,
     .bdrv_close                   = sd_close,
     .bdrv_create                  = sd_create,
+    .bdrv_co_create               = sd_co_create,
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
     .bdrv_getlength               = sd_getlength,
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
@@ -3194,6 +3278,7 @@ static BlockDriver bdrv_sheepdog_unix = {
     .bdrv_reopen_abort            = sd_reopen_abort,
     .bdrv_close                   = sd_close,
     .bdrv_create                  = sd_create,
+    .bdrv_co_create               = sd_co_create,
     .bdrv_has_zero_init           = bdrv_has_zero_init_1,
     .bdrv_getlength               = sd_getlength,
     .bdrv_get_allocated_file_size = sd_get_allocated_file_size,
-- 
2.13.6

  parent reply	other threads:[~2018-02-08 19:25 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-08 19:23 [Qemu-devel] [PATCH 00/27] x-blockdev-create for protocols and qcow2 Kevin Wolf
2018-02-08 19:23 ` [Qemu-devel] [PATCH 01/27] block/qapi: Introduce BlockdevCreateOptions Kevin Wolf
2018-02-08 22:48   ` Eric Blake
2018-02-09 13:19   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 02/27] block/qapi: Add qcow2 create options to schema Kevin Wolf
2018-02-08 23:14   ` Eric Blake
2018-02-09 13:36   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 03/27] qcow2: Let qcow2_create() handle protocol layer Kevin Wolf
2018-02-09 13:57   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 04/27] qcow2: Pass BlockdevCreateOptions to qcow2_create2() Kevin Wolf
2018-02-08 23:29   ` Eric Blake
2018-02-09 14:00     ` Kevin Wolf
2018-02-09 14:12   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 05/27] qcow2: Use BlockdevRef in qcow2_create2() Kevin Wolf
2018-02-09 13:57   ` Eric Blake
2018-02-09 14:31   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 06/27] qcow2: Use QCryptoBlockCreateOptions " Kevin Wolf
2018-02-09 14:13   ` Eric Blake
2018-02-09 18:01   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 07/27] qcow2: Handle full/falloc preallocation " Kevin Wolf
2018-02-09 18:04   ` Max Reitz
2018-02-12 14:19   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 08/27] util: Add qemu_opts_to_qdict_filtered() Kevin Wolf
2018-02-09 18:07   ` Max Reitz
2018-02-15 19:33   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 09/27] qdict: Introduce qdict_rename_keys() Kevin Wolf
2018-02-09 18:18   ` Max Reitz
2018-02-09 18:19     ` Max Reitz
2018-02-15 19:39   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 10/27] qcow2: Use visitor for options in qcow2_create() Kevin Wolf
2018-02-09 18:43   ` Max Reitz
2018-02-15 19:51   ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 11/27] block: x-blockdev-create QMP command Kevin Wolf
2018-02-12 13:48   ` Max Reitz
2018-02-15 19:58   ` Eric Blake
2018-02-21 10:29     ` Kevin Wolf
2018-02-21 16:21       ` Eric Blake
2018-02-08 19:23 ` [Qemu-devel] [PATCH 12/27] file-posix: Support .bdrv_co_create Kevin Wolf
2018-02-12 13:55   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 13/27] file-win32: " Kevin Wolf
2018-02-12 13:57   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 14/27] gluster: " Kevin Wolf
2018-02-12 14:28   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 15/27] rbd: " Kevin Wolf
2018-02-12 15:16   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 16/27] nfs: Use QAPI options in nfs_client_open() Kevin Wolf
2018-02-12 15:36   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 17/27] nfs: Support .bdrv_co_create Kevin Wolf
2018-02-12 15:45   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 18/27] sheepdog: QAPIfy "redundacy" create option Kevin Wolf
2018-02-12 16:03   ` Max Reitz
2018-02-08 19:23 ` Kevin Wolf [this message]
2018-02-12 16:43   ` [Qemu-devel] [PATCH 19/27] sheepdog: Support .bdrv_co_create Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 20/27] ssh: Use QAPI BlockdevOptionsSsh object Kevin Wolf
2018-02-12 17:17   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 21/27] ssh: QAPIfy host-key-check option Kevin Wolf
2018-02-12 17:29   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 22/27] ssh: Pass BlockdevOptionsSsh to connect_to_ssh() Kevin Wolf
2018-02-12 17:35   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 23/27] ssh: Support .bdrv_co_create Kevin Wolf
2018-02-12 17:40   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 24/27] file-posix: Fix no-op bdrv_truncate() with falloc preallocation Kevin Wolf
2018-02-12 17:41   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 25/27] block: Fail bdrv_truncate() with negative size Kevin Wolf
2018-02-12 17:42   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 26/27] qemu-iotests: Test qcow2 over file image creation with QMP Kevin Wolf
2018-02-12 17:50   ` Max Reitz
2018-02-08 19:23 ` [Qemu-devel] [PATCH 27/27] qemu-iotests: Test ssh image creation over QMP Kevin Wolf
2018-02-12 17:56   ` 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=20180208192328.16550-20-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.