9ae3a8
From 0404a8f41dd2d4b7a76bdf07dac6b267adf694cb Mon Sep 17 00:00:00 2001
9ae3a8
From: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Date: Tue, 5 Nov 2013 14:09:01 +0100
9ae3a8
Subject: [PATCH 48/87] blockdev: 'blockdev-add' QMP command
9ae3a8
9ae3a8
RH-Author: Kevin Wolf <kwolf@redhat.com>
9ae3a8
Message-id: <1383660558-32096-8-git-send-email-kwolf@redhat.com>
9ae3a8
Patchwork-id: 55386
9ae3a8
O-Subject: [RHEL-7.0 qemu-kvm PATCH 07/24] blockdev: 'blockdev-add' QMP command
9ae3a8
Bugzilla: 978402
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
RH-Acked-by: Max Reitz <mreitz@redhat.com>
9ae3a8
9ae3a8
For examples see the changes to qmp-commands.hx.
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
(cherry picked from commit d26c9a15738147a8dccc451c6f6d1ddc2305713d)
9ae3a8
9ae3a8
Conflicts:
9ae3a8
	qapi-schema.json
9ae3a8
	qmp-commands.hx
9ae3a8
9ae3a8
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
9ae3a8
---
9ae3a8
 blockdev.c       |  57 ++++++++++++++
9ae3a8
 qapi-schema.json | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 qmp-commands.hx  |  55 +++++++++++++
9ae3a8
 3 files changed, 348 insertions(+)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 blockdev.c       |   57 +++++++++++++
9ae3a8
 qapi-schema.json |  236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
9ae3a8
 qmp-commands.hx  |   55 +++++++++++++
9ae3a8
 3 files changed, 348 insertions(+), 0 deletions(-)
9ae3a8
9ae3a8
diff --git a/blockdev.c b/blockdev.c
9ae3a8
index e379a91..d4f66db 100644
9ae3a8
--- a/blockdev.c
9ae3a8
+++ b/blockdev.c
9ae3a8
@@ -38,6 +38,8 @@
9ae3a8
 #include "qemu/option.h"
9ae3a8
 #include "qemu/config-file.h"
9ae3a8
 #include "qapi/qmp/types.h"
9ae3a8
+#include "qapi-visit.h"
9ae3a8
+#include "qapi/qmp-output-visitor.h"
9ae3a8
 #include "sysemu/sysemu.h"
9ae3a8
 #include "block/block_int.h"
9ae3a8
 #include "qmp-commands.h"
9ae3a8
@@ -1656,6 +1658,61 @@ void qmp_block_job_complete(const char *device, Error **errp)
9ae3a8
     block_job_complete(job, errp);
9ae3a8
 }
9ae3a8
 
9ae3a8
+void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
9ae3a8
+{
9ae3a8
+    QmpOutputVisitor *ov = qmp_output_visitor_new();
9ae3a8
+    QObject *obj;
9ae3a8
+    QDict *qdict;
9ae3a8
+    DriveInfo *dinfo;
9ae3a8
+    Error *local_err = NULL;
9ae3a8
+
9ae3a8
+    /* Require an ID in the top level */
9ae3a8
+    if (!options->has_id) {
9ae3a8
+        error_setg(errp, "Block device needs an ID");
9ae3a8
+        goto fail;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    /* TODO Sort it out in raw-posix and drive_init: Reject aio=native with
9ae3a8
+     * cache.direct=false instead of silently switching to aio=threads, except
9ae3a8
+     * if called from drive_init.
9ae3a8
+     *
9ae3a8
+     * For now, simply forbidding the combination for all drivers will do. */
9ae3a8
+    if (options->has_aio && options->aio == BLOCKDEV_AIO_OPTIONS_NATIVE) {
9ae3a8
+        bool direct = options->cache->has_direct && options->cache->direct;
9ae3a8
+        if (!options->has_cache && !direct) {
9ae3a8
+            error_setg(errp, "aio=native requires cache.direct=true");
9ae3a8
+            goto fail;
9ae3a8
+        }
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    visit_type_BlockdevOptions(qmp_output_get_visitor(ov),
9ae3a8
+                               &options, NULL, &local_err);
9ae3a8
+    if (error_is_set(&local_err)) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
+        goto fail;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    obj = qmp_output_get_qobject(ov);
9ae3a8
+    qdict = qobject_to_qdict(obj);
9ae3a8
+
9ae3a8
+    qdict_flatten(qdict);
9ae3a8
+
9ae3a8
+    QemuOpts *opts = qemu_opts_from_qdict(&qemu_drive_opts, qdict, &local_err);
9ae3a8
+    if (error_is_set(&local_err)) {
9ae3a8
+        error_propagate(errp, local_err);
9ae3a8
+        goto fail;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    dinfo = blockdev_init(opts, IF_NONE);
9ae3a8
+    if (!dinfo) {
9ae3a8
+        error_setg(errp, "Could not open image");
9ae3a8
+        goto fail;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+fail:
9ae3a8
+    qmp_output_visitor_cleanup(ov);
9ae3a8
+}
9ae3a8
+
9ae3a8
 static void do_qmp_query_block_jobs_one(void *opaque, BlockDriverState *bs)
9ae3a8
 {
9ae3a8
     BlockJobInfoList **prev = opaque;
9ae3a8
diff --git a/qapi-schema.json b/qapi-schema.json
9ae3a8
index 12a360a..32b41b0 100644
9ae3a8
--- a/qapi-schema.json
9ae3a8
+++ b/qapi-schema.json
9ae3a8
@@ -3674,3 +3674,239 @@
9ae3a8
             '*cpuid-input-ecx': 'int',
9ae3a8
             'cpuid-register': 'X86CPURegister32',
9ae3a8
             'features': 'int' } }
9ae3a8
+
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevDiscardOptions
9ae3a8
+#
9ae3a8
+# Determines how to handle discard requests.
9ae3a8
+#
9ae3a8
+# @ignore:      Ignore the request
9ae3a8
+# @unmap:       Forward as an unmap request
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'enum': 'BlockdevDiscardOptions',
9ae3a8
+  'data': [ 'ignore', 'unmap' ] }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevAioOptions
9ae3a8
+#
9ae3a8
+# Selects the AIO backend to handle I/O requests
9ae3a8
+#
9ae3a8
+# @threads:     Use qemu's thread pool
9ae3a8
+# @native:      Use native AIO backend (only Linux and Windows)
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'enum': 'BlockdevAioOptions',
9ae3a8
+  'data': [ 'threads', 'native' ] }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevCacheOptions
9ae3a8
+#
9ae3a8
+# Includes cache-related options for block devices
9ae3a8
+#
9ae3a8
+# @writeback:   #optional enables writeback mode for any caches (default: true)
9ae3a8
+# @direct:      #optional enables use of O_DIRECT (bypass the host page cache;
9ae3a8
+#               default: false)
9ae3a8
+# @no-flush:    #optional ignore any flush requests for the device (default:
9ae3a8
+#               false)
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevCacheOptions',
9ae3a8
+  'data': { '*writeback': 'bool',
9ae3a8
+            '*direct': 'bool',
9ae3a8
+            '*no-flush': 'bool' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsBase
9ae3a8
+#
9ae3a8
+# Options that are available for all block devices, independent of the block
9ae3a8
+# driver.
9ae3a8
+#
9ae3a8
+# @driver:      block driver name
9ae3a8
+# @id:          #optional id by which the new block device can be referred to.
9ae3a8
+#               This is a required option on the top level of blockdev-add, and
9ae3a8
+#               currently not allowed on any other level.
9ae3a8
+# @discard:     #optional discard-related options (default: ignore)
9ae3a8
+# @cache:       #optional cache-related options
9ae3a8
+# @aio:         #optional AIO backend (default: threads)
9ae3a8
+# @rerror:      #optional how to handle read errors on the device
9ae3a8
+#               (default: report)
9ae3a8
+# @werror:      #optional how to handle write errors on the device
9ae3a8
+#               (default: enospc)
9ae3a8
+# @read-only:   #optional whether the block device should be read-only
9ae3a8
+#               (default: false)
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsBase',
9ae3a8
+  'data': { 'driver': 'str',
9ae3a8
+            '*id': 'str',
9ae3a8
+            '*discard': 'BlockdevDiscardOptions',
9ae3a8
+            '*cache': 'BlockdevCacheOptions',
9ae3a8
+            '*aio': 'BlockdevAioOptions',
9ae3a8
+            '*rerror': 'BlockdevOnError',
9ae3a8
+            '*werror': 'BlockdevOnError',
9ae3a8
+            '*read-only': 'bool' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsFile
9ae3a8
+#
9ae3a8
+# Driver specific block device options for the file backend and similar
9ae3a8
+# protocols.
9ae3a8
+#
9ae3a8
+# @filename:    path to the image file
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsFile',
9ae3a8
+  'data': { 'filename': 'str' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsVVFAT
9ae3a8
+#
9ae3a8
+# Driver specific block device options for the vvfat protocol.
9ae3a8
+#
9ae3a8
+# @dir:         directory to be exported as FAT image
9ae3a8
+# @fat-type:    #optional FAT type: 12, 16 or 32
9ae3a8
+# @floppy:      #optional whether to export a floppy image (true) or
9ae3a8
+#               partitioned hard disk (false; default)
9ae3a8
+# @rw:          #optional whether to allow write operations (default: false)
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsVVFAT',
9ae3a8
+  'data': { 'dir': 'str', '*fat-type': 'int', '*floppy': 'bool',
9ae3a8
+            '*rw': 'bool' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsGenericFormat
9ae3a8
+#
9ae3a8
+# Driver specific block device options for image format that have no option
9ae3a8
+# besides their data source.
9ae3a8
+#
9ae3a8
+# @file:        reference to or definition of the data source block device
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsGenericFormat',
9ae3a8
+  'data': { 'file': 'BlockdevRef' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsGenericCOWFormat
9ae3a8
+#
9ae3a8
+# Driver specific block device options for image format that have no option
9ae3a8
+# besides their data source and an optional backing file.
9ae3a8
+#
9ae3a8
+# @backing:     #optional reference to or definition of the backing file block
9ae3a8
+#               device (if missing, taken from the image file content). It is
9ae3a8
+#               allowed to pass an empty string here in order to disable the
9ae3a8
+#               default backing file.
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsGenericCOWFormat',
9ae3a8
+  'base': 'BlockdevOptionsGenericFormat',
9ae3a8
+  'data': { '*backing': 'BlockdevRef' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptionsQcow2
9ae3a8
+#
9ae3a8
+# Driver specific block device options for qcow2.
9ae3a8
+#
9ae3a8
+# @lazy-refcounts:        #optional whether to enable the lazy refcounts
9ae3a8
+#                         feature (default is taken from the image file)
9ae3a8
+#
9ae3a8
+# @pass-discard-request:  #optional whether discard requests to the qcow2
9ae3a8
+#                         device should be forwarded to the data source
9ae3a8
+#
9ae3a8
+# @pass-discard-snapshot: #optional whether discard requests for the data source
9ae3a8
+#                         should be issued when a snapshot operation (e.g.
9ae3a8
+#                         deleting a snapshot) frees clusters in the qcow2 file
9ae3a8
+#
9ae3a8
+# @pass-discard-other:    #optional whether discard requests for the data source
9ae3a8
+#                         should be issued on other occasions where a cluster
9ae3a8
+#                         gets freed
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'type': 'BlockdevOptionsQcow2',
9ae3a8
+  'base': 'BlockdevOptionsGenericCOWFormat',
9ae3a8
+  'data': { '*lazy-refcounts': 'bool',
9ae3a8
+            '*pass-discard-request': 'bool',
9ae3a8
+            '*pass-discard-snapshot': 'bool',
9ae3a8
+            '*pass-discard-other': 'bool' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevOptions
9ae3a8
+#
9ae3a8
+# Options for creating a block device.
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'union': 'BlockdevOptions',
9ae3a8
+  'base': 'BlockdevOptionsBase',
9ae3a8
+  'discriminator': 'driver',
9ae3a8
+  'data': {
9ae3a8
+      'file':       'BlockdevOptionsFile',
9ae3a8
+      'http':       'BlockdevOptionsFile',
9ae3a8
+      'https':      'BlockdevOptionsFile',
9ae3a8
+      'ftp':        'BlockdevOptionsFile',
9ae3a8
+      'ftps':       'BlockdevOptionsFile',
9ae3a8
+      'tftp':       'BlockdevOptionsFile',
9ae3a8
+# TODO gluster: Wait for structured options
9ae3a8
+# TODO iscsi: Wait for structured options
9ae3a8
+# TODO nbd: Should take InetSocketAddress for 'host'?
9ae3a8
+# TODO rbd: Wait for structured options
9ae3a8
+# TODO sheepdog: Wait for structured options
9ae3a8
+# TODO ssh: Should take InetSocketAddress for 'host'?
9ae3a8
+      'vvfat':      'BlockdevOptionsVVFAT',
9ae3a8
+
9ae3a8
+# TODO blkdebug: Wait for structured options
9ae3a8
+# TODO blkverify: Wait for structured options
9ae3a8
+
9ae3a8
+      'bochs':      'BlockdevOptionsGenericFormat',
9ae3a8
+      'cloop':      'BlockdevOptionsGenericFormat',
9ae3a8
+      'cow':        'BlockdevOptionsGenericCOWFormat',
9ae3a8
+      'dmg':        'BlockdevOptionsGenericFormat',
9ae3a8
+      'parallels':  'BlockdevOptionsGenericFormat',
9ae3a8
+      'qcow':       'BlockdevOptionsGenericCOWFormat',
9ae3a8
+      'qcow2':      'BlockdevOptionsQcow2',
9ae3a8
+      'qed':        'BlockdevOptionsGenericCOWFormat',
9ae3a8
+      'raw':        'BlockdevOptionsGenericFormat',
9ae3a8
+      'vdi':        'BlockdevOptionsGenericFormat',
9ae3a8
+      'vhdx':       'BlockdevOptionsGenericFormat',
9ae3a8
+      'vmdk':       'BlockdevOptionsGenericCOWFormat',
9ae3a8
+      'vpc':        'BlockdevOptionsGenericFormat'
9ae3a8
+  } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @BlockdevRef
9ae3a8
+#
9ae3a8
+# Reference to a block device.
9ae3a8
+#
9ae3a8
+# @definition:      defines a new block device inline
9ae3a8
+# @reference:       references the ID of an existing block device. An
9ae3a8
+#                   empty string means that no block device should be
9ae3a8
+#                   referenced.
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'union': 'BlockdevRef',
9ae3a8
+  'discriminator': {},
9ae3a8
+  'data': { 'definition': 'BlockdevOptions',
9ae3a8
+            'reference': 'str' } }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @blockdev-add:
9ae3a8
+#
9ae3a8
+# Creates a new block device.
9ae3a8
+#
9ae3a8
+# @options: block device options for the new device
9ae3a8
+#
9ae3a8
+# Since: 1.7
9ae3a8
+##
9ae3a8
+{ 'command': 'blockdev-add', 'data': { 'options': 'BlockdevOptions' } }
9ae3a8
diff --git a/qmp-commands.hx b/qmp-commands.hx
9ae3a8
index e40d54d..d1f6f8b 100644
9ae3a8
--- a/qmp-commands.hx
9ae3a8
+++ b/qmp-commands.hx
9ae3a8
@@ -2941,3 +2941,58 @@ Example:
9ae3a8
 <- { "return": {} }
9ae3a8
 
9ae3a8
 EQMP
9ae3a8
+
9ae3a8
+    {
9ae3a8
+        .name       = "blockdev-add",
9ae3a8
+        .args_type  = "options:q",
9ae3a8
+        .mhandler.cmd_new = qmp_marshal_input_blockdev_add,
9ae3a8
+    },
9ae3a8
+
9ae3a8
+SQMP
9ae3a8
+blockdev-add
9ae3a8
+------------
9ae3a8
+
9ae3a8
+Add a block device.
9ae3a8
+
9ae3a8
+Arguments:
9ae3a8
+
9ae3a8
+- "options": block driver options
9ae3a8
+
9ae3a8
+Example (1):
9ae3a8
+
9ae3a8
+-> { "execute": "blockdev-add",
9ae3a8
+    "arguments": { "options" : { "driver": "qcow2",
9ae3a8
+                                 "file": { "driver": "file",
9ae3a8
+                                           "filename": "test.qcow2" } } } }
9ae3a8
+<- { "return": {} }
9ae3a8
+
9ae3a8
+Example (2):
9ae3a8
+
9ae3a8
+-> { "execute": "blockdev-add",
9ae3a8
+     "arguments": {
9ae3a8
+         "options": {
9ae3a8
+           "driver": "qcow2",
9ae3a8
+           "id": "my_disk",
9ae3a8
+           "discard": "unmap",
9ae3a8
+           "cache": {
9ae3a8
+               "direct": true,
9ae3a8
+               "writeback": true
9ae3a8
+           },
9ae3a8
+           "file": {
9ae3a8
+               "driver": "file",
9ae3a8
+               "filename": "/tmp/test.qcow2"
9ae3a8
+           },
9ae3a8
+           "backing": {
9ae3a8
+               "driver": "raw",
9ae3a8
+               "file": {
9ae3a8
+                   "driver": "file",
9ae3a8
+                   "filename": "/dev/fdset/4"
9ae3a8
+               }
9ae3a8
+           }
9ae3a8
+         }
9ae3a8
+       }
9ae3a8
+     }
9ae3a8
+
9ae3a8
+<- { "return": {} }
9ae3a8
+
9ae3a8
+EQMP
9ae3a8
-- 
9ae3a8
1.7.1
9ae3a8