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 16/27] nfs: Use QAPI options in nfs_client_open()
Date: Thu,  8 Feb 2018 20:23:17 +0100	[thread overview]
Message-ID: <20180208192328.16550-17-kwolf@redhat.com> (raw)
In-Reply-To: <20180208192328.16550-1-kwolf@redhat.com>

Using the QAPI visitor to turn all options into QAPI BlockdevOptionsNfs
simplifies the code a lot. It will also be useful for implementing the
QAPI based .bdrv_co_create callback.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/nfs.c | 176 ++++++++++++++++++------------------------------------------
 1 file changed, 53 insertions(+), 123 deletions(-)

diff --git a/block/nfs.c b/block/nfs.c
index effc8719b5..f540c74c87 100644
--- a/block/nfs.c
+++ b/block/nfs.c
@@ -367,49 +367,6 @@ static int coroutine_fn nfs_co_flush(BlockDriverState *bs)
     return task.ret;
 }
 
-static QemuOptsList runtime_opts = {
-    .name = "nfs",
-    .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
-    .desc = {
-        {
-            .name = "path",
-            .type = QEMU_OPT_STRING,
-            .help = "Path of the image on the host",
-        },
-        {
-            .name = "user",
-            .type = QEMU_OPT_NUMBER,
-            .help = "UID value to use when talking to the server",
-        },
-        {
-            .name = "group",
-            .type = QEMU_OPT_NUMBER,
-            .help = "GID value to use when talking to the server",
-        },
-        {
-            .name = "tcp-syn-count",
-            .type = QEMU_OPT_NUMBER,
-            .help = "Number of SYNs to send during the session establish",
-        },
-        {
-            .name = "readahead-size",
-            .type = QEMU_OPT_NUMBER,
-            .help = "Set the readahead size in bytes",
-        },
-        {
-            .name = "page-cache-size",
-            .type = QEMU_OPT_NUMBER,
-            .help = "Set the pagecache size in bytes",
-        },
-        {
-            .name = "debug",
-            .type = QEMU_OPT_NUMBER,
-            .help = "Set the NFS debug level (max 2)",
-        },
-        { /* end of list */ }
-    },
-};
-
 static void nfs_detach_aio_context(BlockDriverState *bs)
 {
     NFSClient *client = bs->opaque;
@@ -452,71 +409,16 @@ static void nfs_file_close(BlockDriverState *bs)
     nfs_client_close(client);
 }
 
-static NFSServer *nfs_config(QDict *options, Error **errp)
-{
-    NFSServer *server = NULL;
-    QDict *addr = NULL;
-    QObject *crumpled_addr = NULL;
-    Visitor *iv = NULL;
-    Error *local_error = NULL;
-
-    qdict_extract_subqdict(options, &addr, "server.");
-    if (!qdict_size(addr)) {
-        error_setg(errp, "NFS server address missing");
-        goto out;
-    }
-
-    crumpled_addr = qdict_crumple(addr, errp);
-    if (!crumpled_addr) {
-        goto out;
-    }
-
-    /*
-     * Caution: this works only because all scalar members of
-     * NFSServer are QString in @crumpled_addr.  The visitor expects
-     * @crumpled_addr to be typed according to the QAPI schema.  It
-     * is when @options come from -blockdev or blockdev_add.  But when
-     * they come from -drive, they're all QString.
-     */
-    iv = qobject_input_visitor_new(crumpled_addr);
-    visit_type_NFSServer(iv, NULL, &server, &local_error);
-    if (local_error) {
-        error_propagate(errp, local_error);
-        goto out;
-    }
-
-out:
-    QDECREF(addr);
-    qobject_decref(crumpled_addr);
-    visit_free(iv);
-    return server;
-}
-
-
-static int64_t nfs_client_open(NFSClient *client, QDict *options,
+static int64_t nfs_client_open(NFSClient *client, BlockdevOptionsNfs *opts,
                                int flags, int open_flags, Error **errp)
 {
     int64_t ret = -EINVAL;
-    QemuOpts *opts = NULL;
-    Error *local_err = NULL;
     struct stat st;
     char *file = NULL, *strp = NULL;
 
     qemu_mutex_init(&client->mutex);
-    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);
-        ret = -EINVAL;
-        goto fail;
-    }
 
-    client->path = g_strdup(qemu_opt_get(opts, "path"));
-    if (!client->path) {
-        ret = -EINVAL;
-        error_setg(errp, "No path was specified");
-        goto fail;
-    }
+    client->path = g_strdup(opts->path);
 
     strp = strrchr(client->path, '/');
     if (strp == NULL) {
@@ -526,12 +428,10 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
     file = g_strdup(strp);
     *strp = 0;
 
-    /* Pop the config into our state object, Exit if invalid */
-    client->server = nfs_config(options, errp);
-    if (!client->server) {
-        ret = -EINVAL;
-        goto fail;
-    }
+    /* Steal the NFSServer object from opts; set the original pointer to NULL
+     * to avoid use after free and double free. */
+    client->server = opts->server;
+    opts->server = NULL;
 
     client->context = nfs_init_context();
     if (client->context == NULL) {
@@ -539,29 +439,29 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
         goto fail;
     }
 
-    if (qemu_opt_get(opts, "user")) {
-        client->uid = qemu_opt_get_number(opts, "user", 0);
+    if (opts->has_user) {
+        client->uid = opts->user;
         nfs_set_uid(client->context, client->uid);
     }
 
-    if (qemu_opt_get(opts, "group")) {
-        client->gid = qemu_opt_get_number(opts, "group", 0);
+    if (opts->has_group) {
+        client->gid = opts->group;
         nfs_set_gid(client->context, client->gid);
     }
 
-    if (qemu_opt_get(opts, "tcp-syn-count")) {
-        client->tcp_syncnt = qemu_opt_get_number(opts, "tcp-syn-count", 0);
+    if (opts->has_tcp_syn_count) {
+        client->tcp_syncnt = opts->tcp_syn_count;
         nfs_set_tcp_syncnt(client->context, client->tcp_syncnt);
     }
 
 #ifdef LIBNFS_FEATURE_READAHEAD
-    if (qemu_opt_get(opts, "readahead-size")) {
+    if (opts->has_readahead_size) {
         if (open_flags & BDRV_O_NOCACHE) {
             error_setg(errp, "Cannot enable NFS readahead "
                              "if cache.direct = on");
             goto fail;
         }
-        client->readahead = qemu_opt_get_number(opts, "readahead-size", 0);
+        client->readahead = opts->readahead_size;
         if (client->readahead > QEMU_NFS_MAX_READAHEAD_SIZE) {
             warn_report("Truncating NFS readahead size to %d",
                         QEMU_NFS_MAX_READAHEAD_SIZE);
@@ -576,13 +476,13 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
 #endif
 
 #ifdef LIBNFS_FEATURE_PAGECACHE
-    if (qemu_opt_get(opts, "page-cache-size")) {
+    if (opts->has_page_cache_size) {
         if (open_flags & BDRV_O_NOCACHE) {
             error_setg(errp, "Cannot enable NFS pagecache "
                              "if cache.direct = on");
             goto fail;
         }
-        client->pagecache = qemu_opt_get_number(opts, "page-cache-size", 0);
+        client->pagecache = opts->page_cache_size;
         if (client->pagecache > QEMU_NFS_MAX_PAGECACHE_SIZE) {
             warn_report("Truncating NFS pagecache size to %d pages",
                         QEMU_NFS_MAX_PAGECACHE_SIZE);
@@ -595,8 +495,8 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
 #endif
 
 #ifdef LIBNFS_FEATURE_DEBUG
-    if (qemu_opt_get(opts, "debug")) {
-        client->debug = qemu_opt_get_number(opts, "debug", 0);
+    if (opts->has_debug) {
+        client->debug = opts->debug;
         /* limit the maximum debug level to avoid potential flooding
          * of our log files. */
         if (client->debug > QEMU_NFS_MAX_DEBUG_LEVEL) {
@@ -647,11 +547,41 @@ static int64_t nfs_client_open(NFSClient *client, QDict *options,
 fail:
     nfs_client_close(client);
 out:
-    qemu_opts_del(opts);
     g_free(file);
     return ret;
 }
 
+static int64_t nfs_client_open_qdict(NFSClient *client, QDict *options,
+                                     int flags, int open_flags, Error **errp)
+{
+    BlockdevOptionsNfs *opts;
+    QObject *crumpled = NULL;
+    Visitor *v;
+    Error *local_err = NULL;
+    int ret;
+
+    crumpled = qdict_crumple(options, errp);
+    if (crumpled == NULL) {
+        return -EINVAL;
+    }
+
+    v = qobject_input_visitor_new_keyval(crumpled);
+    visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err);
+    visit_free(v);
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        ret = -EINVAL;
+        goto fail;
+    }
+
+    ret = nfs_client_open(client, opts, flags, open_flags, errp);
+fail:
+    qobject_decref(crumpled);
+    qapi_free_BlockdevOptionsNfs(opts);
+    return ret;
+}
+
 static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
                          Error **errp) {
     NFSClient *client = bs->opaque;
@@ -659,9 +589,9 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags,
 
     client->aio_context = bdrv_get_aio_context(bs);
 
-    ret = nfs_client_open(client, options,
-                          (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY,
-                          bs->open_flags, errp);
+    ret = nfs_client_open_qdict(client, options,
+                                (flags & BDRV_O_RDWR) ? O_RDWR : O_RDONLY,
+                                bs->open_flags, errp);
     if (ret < 0) {
         return ret;
     }
@@ -702,7 +632,7 @@ static int nfs_file_create(const char *url, QemuOpts *opts, Error **errp)
         goto out;
     }
 
-    ret = nfs_client_open(client, options, O_CREAT, 0, errp);
+    ret = nfs_client_open_qdict(client, options, O_CREAT, 0, errp);
     if (ret < 0) {
         goto out;
     }
-- 
2.13.6

  parent reply	other threads:[~2018-02-08 19:24 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 ` Kevin Wolf [this message]
2018-02-12 15:36   ` [Qemu-devel] [PATCH 16/27] nfs: Use QAPI options in nfs_client_open() 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 ` [Qemu-devel] [PATCH 19/27] sheepdog: Support .bdrv_co_create Kevin Wolf
2018-02-12 16:43   ` 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-17-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.