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