218e99
From 6270aec1271880bb5f12db46d40f51671c548f59 Mon Sep 17 00:00:00 2001
218e99
From: Jeff Cody <jcody@redhat.com>
218e99
Date: Thu, 7 Nov 2013 07:28:56 +0100
218e99
Subject: [PATCH 57/81] block: optionally disable live block jobs
218e99
218e99
RH-Author: Jeff Cody <jcody@redhat.com>
218e99
Message-id: <5b15ff37a1f28a76e2b66c07df996d3a7c37d6e9.1383712781.git.jcody@redhat.com>
218e99
Patchwork-id: 55478
218e99
O-Subject: [RHEL7 qemu-kvm PATCH 1/3] block: optionally disable live block jobs
218e99
Bugzilla: 987582
218e99
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
RH-Acked-by: Eric Blake <eblake@redhat.com>
218e99
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
218e99
218e99
This disables all block job operations that are part of the virt
218e99
differentiation features.
218e99
218e99
This includes:
218e99
    * live snapshots (single and group)
218e99
    * block stream
218e99
    * block commit
218e99
    * block mirror
218e99
    * block transactions
218e99
218e99
All of these are disabled via the CONFIG_LIVE_BLOCK_OPS config option.
218e99
218e99
In RHEL6, block job differentiation grew from live snapshot disablement,
218e99
which was used to encompass many operations that were not live
218e99
snapshots.  CONFIG_LIVE_SNAPSHOTS was used for disablement of multiple
218e99
features.
218e99
218e99
For RHEL7, let's use naming that is more accurate:
218e99
CONFIG_LIVE_BLOCK_OPS, to denote live block operations.
218e99
218e99
RHEL and RHEV have different binaries, where RHEV qemu-kvm binaries
218e99
support live snapshots.
218e99
218e99
The JSON files qapi-schema-rhel.json and qapi-schema-rhev.json are
218e99
automatically generated from the qapi-schema.json, by looking for
218e99
'_rhev_only' comments in the 'master' JSON file.
218e99
218e99
For RHEL6, the JSON file had makeshift 'ifdef' statements.  This was
218e99
changed to '_rhev_only' and '_end_rhev-only' blocks, because calling
218e99
them 'ifdef' was misleading - it did not depend on the actual state
218e99
of that variable itself.
218e99
218e99
The Makefile variable RHEV_CONFIGS can be appended with additional
218e99
config items that may appear in the qapi-schema.json file.  For
218e99
instance, to have features CONFIG_LIVE_BLOCK_OPS and CONFIG_SOME_FEATURE
218e99
both be RHEV only, set the variable like so:
218e99
218e99
RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS CONFIG_SOME_FEATURE
218e99
218e99
RHEV_CONFIGS is then turned into a regex. For the example above, the
218e99
following pattern is matched when generating the RHEL/RHEV JSON files:
218e99
^#_rhev-only +(\bCONFIG_LIVE_BLOCK_OPS\b|\bCONFIG_SOME_FEATURE\b)
218e99
218e99
Unlike the RHEL6 counterpart, this one uses original qmp-commands.h,
218e99
qapi-types.h, qapi-visit.c, etc.. filenames, simplifying the Makefile a
218e99
bit.
218e99
218e99
BZ: 987582
218e99
218e99
The Makefile changes were derived from
218e99
RHEL6 commit bb5bd75dd86a6d05c9df4c2d271f98744d6c90b7, but this was not
218e99
a cherry-pick as the actual changes differed significantly.
218e99
218e99
Signed-off-by: Jeff Cody <jcody@redhat.com>
218e99
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
---
218e99
 Makefile            |   48 ++++++++++++++++++++++++++++++++++++++++++------
218e99
 block/Makefile.objs |    2 ++
218e99
 blockdev.c          |    7 +++++++
218e99
 configure           |   14 +++++++++++++-
218e99
 hmp-commands.hx     |    5 ++++-
218e99
 hmp.c               |    4 ++++
218e99
 qapi-schema.json    |    6 ++++++
218e99
 qmp-commands.hx     |    4 ++++
218e99
 8 files changed, 82 insertions(+), 8 deletions(-)
218e99
218e99
diff --git a/Makefile b/Makefile
218e99
index dcd31c6..45048a3 100644
218e99
--- a/Makefile
218e99
+++ b/Makefile
218e99
@@ -2,6 +2,11 @@
218e99
 
218e99
 # Always point to the root of the build tree (needs GNU make).
218e99
 BUILD_DIR=$(CURDIR)
218e99
+# useful for passing ' ' and ',' into Makefile functional calls,
218e99
+# as these characters cannot be passed otherwise
218e99
+_empty :=  
218e99
+_space := $(_empty) $(_empty)
218e99
+_comma := ,
218e99
 
218e99
 # All following code might depend on configuration variables
218e99
 ifneq ($(wildcard config-host.mak),)
218e99
@@ -213,15 +218,45 @@ qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
218e99
 $(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
218e99
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o qga/qapi-generated -p "qga-" < $<, "  GEN   $@")
218e99
 
218e99
+# if there are multiple config items to be RHEV-only, simply add it to
218e99
+# RHEV_CONFIGS, like so: RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS CONFIG_SOME_FEATURE
218e99
+RHEV_CONFIGS = CONFIG_LIVE_BLOCK_OPS
218e99
+# Turn $(RHEV_CONFIGS) into a regex with logical OR, and whole word matching
218e99
+RHEV_ONLY_CONFIG_ITEMS = (\b$(subst $(_space),\b|\b,$(strip $(RHEV_CONFIGS)))\b)
218e99
+
218e99
+GENERATED_JSON_FILES = $(addprefix $(SRC_PATH)/, qapi-schema-rhel.json qapi-schema-rhev.json)
218e99
+
218e99
+$(SRC_PATH)/qapi-schema-rhev.json: $(SRC_PATH)/qapi-schema.json
218e99
+	-@echo "# THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY" > $@
218e99
+	-@echo "#" >> $@
218e99
+	$(call quiet-command,sed -r "/^#_rhev-only +$(RHEV_ONLY_CONFIG_ITEMS)/d;/^#_end-rhev-only/d" $< >> $@, "  GEN   $@")
218e99
+
218e99
+$(SRC_PATH)/qapi-schema-rhel.json: $(SRC_PATH)/qapi-schema.json
218e99
+	-@echo "# THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY" > $@
218e99
+	-@echo "#" >> $@
218e99
+	$(call quiet-command,sed -r "/^#_rhev-only +$(RHEV_ONLY_CONFIG_ITEMS)/$(_comma)/^#_end-rhev-only/d" $< >> $@, "  GEN   $@")
218e99
+
218e99
+ifeq ($(CONFIG_LIVE_BLOCK_OPS),y)
218e99
 qapi-types.c qapi-types.h :\
218e99
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
218e99
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "." < $<, "  GEN   $@")
218e99
+$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
218e99
 qapi-visit.c qapi-visit.h :\
218e99
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
218e99
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
218e99
+$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
218e99
 qmp-commands.h qmp-marshal.c :\
218e99
-$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
218e99
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, "  GEN   $@")
218e99
+$(SRC_PATH)/qapi-schema-rhev.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "."  < $<, "  GEN   $@")
218e99
+else
218e99
+qapi-types.c qapi-types.h :\
218e99
+$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
218e99
+qapi-visit.c qapi-visit.h :\
218e99
+$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "."  < $<, "  GEN   $@")
218e99
+qmp-commands.h qmp-marshal.c :\
218e99
+$(SRC_PATH)/qapi-schema-rhel.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
218e99
+	$(call quiet-command,python $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "."  < $<, "  GEN   $@")
218e99
+endif
218e99
 
218e99
 QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
218e99
 $(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
218e99
@@ -243,6 +278,7 @@ clean:
218e99
 	rm -f trace/generated-tracers-dtrace.h*
218e99
 	rm -f $(foreach f,$(GENERATED_HEADERS),$(f) $(f)-timestamp)
218e99
 	rm -f $(foreach f,$(GENERATED_SOURCES),$(f) $(f)-timestamp)
218e99
+	rm -f $(foreach f,$(GENERATED_JSON_FILES),$(f) $(f)-timestamp)
218e99
 	rm -rf qapi-generated
218e99
 	rm -rf qga/qapi-generated
218e99
 	$(MAKE) -C tests/tcg clean
218e99
diff --git a/block/Makefile.objs b/block/Makefile.objs
218e99
index 6b8d5ec..f355271 100644
218e99
--- a/block/Makefile.objs
218e99
+++ b/block/Makefile.objs
218e99
@@ -17,8 +17,10 @@ block-obj-$(CONFIG_GLUSTERFS) += gluster.o
218e99
 block-obj-$(CONFIG_LIBSSH2) += ssh.o
218e99
 endif
218e99
 
218e99
+ifeq ($(CONFIG_LIVE_BLOCK_OPS),y)
218e99
 common-obj-y += stream.o
218e99
 common-obj-y += commit.o
218e99
 common-obj-y += mirror.o
218e99
+endif
218e99
 
218e99
 $(obj)/curl.o: QEMU_CFLAGS+=$(CURL_CFLAGS)
218e99
diff --git a/blockdev.c b/blockdev.c
218e99
index f65aff4..6710f61 100644
218e99
--- a/blockdev.c
218e99
+++ b/blockdev.c
218e99
@@ -237,6 +237,8 @@ typedef struct {
218e99
     DriveInfo *dinfo;
218e99
 } DrivePutRefBH;
218e99
 
218e99
+/* right now, this is only used from block_job_cb() */
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
 static void drive_put_ref_bh(void *opaque)
218e99
 {
218e99
     DrivePutRefBH *s = opaque;
218e99
@@ -262,6 +264,7 @@ static void drive_put_ref_bh_schedule(DriveInfo *dinfo)
218e99
     s->dinfo = dinfo;
218e99
     qemu_bh_schedule(s->bh);
218e99
 }
218e99
+#endif
218e99
 
218e99
 static int parse_block_error_action(const char *buf, bool is_read)
218e99
 {
218e99
@@ -806,6 +809,7 @@ void do_commit(Monitor *mon, const QDict *qdict)
218e99
     }
218e99
 }
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
 static void blockdev_do_action(int kind, void *data, Error **errp)
218e99
 {
218e99
     BlockdevAction action;
218e99
@@ -1051,6 +1055,7 @@ exit:
218e99
         g_free(states);
218e99
     }
218e99
 }
218e99
+#endif
218e99
 
218e99
 
218e99
 static void eject_device(BlockDriverState *bs, int force, Error **errp)
218e99
@@ -1286,6 +1291,7 @@ void qmp_block_resize(const char *device, int64_t size, Error **errp)
218e99
     }
218e99
 }
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
 static void block_job_cb(void *opaque, int ret)
218e99
 {
218e99
     BlockDriverState *bs = opaque;
218e99
@@ -1547,6 +1553,7 @@ void qmp_drive_mirror(const char *device, const char *target,
218e99
      */
218e99
     drive_get_ref(drive_get_by_blockdev(bs));
218e99
 }
218e99
+#endif
218e99
 
218e99
 static BlockJob *find_block_job(const char *device)
218e99
 {
218e99
diff --git a/configure b/configure
218e99
index 4830f7e..9260d3c 100755
218e99
--- a/configure
218e99
+++ b/configure
218e99
@@ -240,6 +240,7 @@ gtk=""
218e99
 gtkabi="2.0"
218e99
 tpm="no"
218e99
 libssh2=""
218e99
+live_block_ops="yes"
218e99
 
218e99
 # parse CC options first
218e99
 for opt do
218e99
@@ -927,7 +928,11 @@ for opt do
218e99
   ;;
218e99
   --enable-libssh2) libssh2="yes"
218e99
   ;;
218e99
-  *) echo "ERROR: unknown option $opt"; show_help="yes"
218e99
+  --disable-live-block-ops) live_block_ops="no"
218e99
+  ;;
218e99
+  --enable-live-block-ops) live_block_ops="yes"
218e99
+  ;;
218e99
+*) echo "ERROR: unknown option $opt"; show_help="yes"
218e99
   ;;
218e99
   esac
218e99
 done
218e99
@@ -1195,6 +1200,8 @@ echo "  --gcov=GCOV              use specified gcov [$gcov_tool]"
218e99
 echo "  --enable-tpm             enable TPM support"
218e99
 echo "  --disable-libssh2        disable ssh block device support"
218e99
 echo "  --enable-libssh2         enable ssh block device support"
218e99
+echo "  --disable-live-block-ops disable live block operations support"
218e99
+echo "  --enable-live-block-ops  enable live block operations support"
218e99
 echo ""
218e99
 echo "NOTE: The object files are built at the place where configure is launched"
218e99
 exit 1
218e99
@@ -3556,6 +3563,7 @@ echo "TPM support       $tpm"
218e99
 echo "libssh2 support   $libssh2"
218e99
 echo "TPM passthrough   $tpm_passthrough"
218e99
 echo "QOM debugging     $qom_cast_debug"
218e99
+echo "Live block operations $live_block_ops"
218e99
 
218e99
 if test "$sdl_too_old" = "yes"; then
218e99
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
218e99
@@ -3940,6 +3948,10 @@ if test "$virtio_blk_data_plane" = "yes" ; then
218e99
   echo 'CONFIG_VIRTIO_BLK_DATA_PLANE=$(CONFIG_VIRTIO)' >> $config_host_mak
218e99
 fi
218e99
 
218e99
+if test "$live_block_ops" = "yes" ; then
218e99
+  echo "CONFIG_LIVE_BLOCK_OPS=y" >> $config_host_mak
218e99
+fi
218e99
+
218e99
 # USB host support
218e99
 if test "$libusb" = "yes"; then
218e99
   echo "HOST_USB=libusb legacy" >> $config_host_mak
218e99
diff --git a/hmp-commands.hx b/hmp-commands.hx
218e99
index 5cd6368..2fc2c0b 100644
218e99
--- a/hmp-commands.hx
218e99
+++ b/hmp-commands.hx
218e99
@@ -68,7 +68,7 @@ action to see the updated size.  Resize to a lower size is supported,
218e99
 but should be used with extreme caution.  Note that this command only
218e99
 resizes image files, it can not resize block devices like LVM volumes.
218e99
 ETEXI
218e99
-
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
     {
218e99
         .name       = "block_stream",
218e99
         .args_type  = "device:B,speed:o?,base:s?",
218e99
@@ -76,6 +76,7 @@ ETEXI
218e99
         .help       = "copy data from a backing file into a block device",
218e99
         .mhandler.cmd = hmp_block_stream,
218e99
     },
218e99
+#endif
218e99
 
218e99
 STEXI
218e99
 @item block_stream
218e99
@@ -1024,6 +1025,7 @@ gdb.
218e99
 ETEXI
218e99
 #endif
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
     {
218e99
         .name       = "snapshot_blkdev",
218e99
         .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
218e99
@@ -1066,6 +1068,7 @@ STEXI
218e99
 Start mirroring a block device's writes to a new destination,
218e99
 using the specified target.
218e99
 ETEXI
218e99
+#endif
218e99
 
218e99
     {
218e99
         .name       = "drive_add",
218e99
diff --git a/hmp.c b/hmp.c
218e99
index 3b3e7c7..29990d2 100644
218e99
--- a/hmp.c
218e99
+++ b/hmp.c
218e99
@@ -838,6 +838,7 @@ void hmp_block_resize(Monitor *mon, const QDict *qdict)
218e99
     hmp_handle_error(mon, &errp);
218e99
 }
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
 void hmp_drive_mirror(Monitor *mon, const QDict *qdict)
218e99
 {
218e99
     const char *device = qdict_get_str(qdict, "device");
218e99
@@ -889,6 +890,7 @@ void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict)
218e99
                                true, mode, &errp);
218e99
     hmp_handle_error(mon, &errp);
218e99
 }
218e99
+#endif
218e99
 
218e99
 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
218e99
 {
218e99
@@ -1030,6 +1032,7 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict)
218e99
     hmp_handle_error(mon, &err);
218e99
 }
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
 void hmp_block_stream(Monitor *mon, const QDict *qdict)
218e99
 {
218e99
     Error *error = NULL;
218e99
@@ -1043,6 +1046,7 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict)
218e99
 
218e99
     hmp_handle_error(mon, &error);
218e99
 }
218e99
+#endif
218e99
 
218e99
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict)
218e99
 {
218e99
diff --git a/qapi-schema.json b/qapi-schema.json
218e99
index b779458..12a360a 100644
218e99
--- a/qapi-schema.json
218e99
+++ b/qapi-schema.json
218e99
@@ -1617,6 +1617,7 @@
218e99
 ##
218e99
 { 'command': 'block_resize', 'data': { 'device': 'str', 'size': 'int' }}
218e99
 
218e99
+#_rhev-only CONFIG_LIVE_BLOCK_OPS
218e99
 ##
218e99
 # @NewImageMode
218e99
 #
218e99
@@ -1697,6 +1698,7 @@
218e99
 ##
218e99
 { 'command': 'blockdev-snapshot-sync',
218e99
   'data': 'BlockdevSnapshot' }
218e99
+#_end-rhev-only
218e99
 
218e99
 ##
218e99
 # @human-monitor-command:
218e99
@@ -1726,6 +1728,7 @@
218e99
   'data': {'command-line': 'str', '*cpu-index': 'int'},
218e99
   'returns': 'str' }
218e99
 
218e99
+#_rhev-only CONFIG_LIVE_BLOCK_OPS
218e99
 ##
218e99
 # @block-commit
218e99
 #
218e99
@@ -1811,6 +1814,7 @@
218e99
             '*speed': 'int', '*granularity': 'uint32',
218e99
             '*buf-size': 'int', '*on-source-error': 'BlockdevOnError',
218e99
             '*on-target-error': 'BlockdevOnError' } }
218e99
+#_end-rhev-only
218e99
 
218e99
 ##
218e99
 # @migrate_cancel
218e99
@@ -2123,6 +2127,7 @@
218e99
   'data': { 'device': 'str', 'bps': 'int', 'bps_rd': 'int', 'bps_wr': 'int',
218e99
             'iops': 'int', 'iops_rd': 'int', 'iops_wr': 'int' } }
218e99
 
218e99
+#_rhev-only CONFIG_LIVE_BLOCK_OPS
218e99
 ##
218e99
 # @block-stream:
218e99
 #
218e99
@@ -2160,6 +2165,7 @@
218e99
 { 'command': 'block-stream',
218e99
   'data': { 'device': 'str', '*base': 'str', '*speed': 'int',
218e99
             '*on-error': 'BlockdevOnError' } }
218e99
+#_end-rhev-only
218e99
 
218e99
 ##
218e99
 # @block-job-set-speed:
218e99
diff --git a/qmp-commands.hx b/qmp-commands.hx
218e99
index de5f394..e40d54d 100644
218e99
--- a/qmp-commands.hx
218e99
+++ b/qmp-commands.hx
218e99
@@ -904,6 +904,7 @@ Example:
218e99
 
218e99
 EQMP
218e99
 
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
     {
218e99
         .name       = "block-stream",
218e99
         .args_type  = "device:B,base:s?,speed:o?,on-error:s?",
218e99
@@ -915,6 +916,7 @@ EQMP
218e99
         .args_type  = "device:B,base:s?,top:s,speed:o?",
218e99
         .mhandler.cmd_new = qmp_marshal_input_block_commit,
218e99
     },
218e99
+#endif
218e99
 
218e99
     {
218e99
         .name       = "block-job-set-speed",
218e99
@@ -942,6 +944,7 @@ EQMP
218e99
         .args_type  = "device:B",
218e99
         .mhandler.cmd_new = qmp_marshal_input_block_job_complete,
218e99
     },
218e99
+#ifdef CONFIG_LIVE_BLOCK_OPS
218e99
     {
218e99
         .name       = "transaction",
218e99
         .args_type  = "actions:q",
218e99
@@ -1085,6 +1088,7 @@ Example:
218e99
 <- { "return": {} }
218e99
 
218e99
 EQMP
218e99
+#endif
218e99
 
218e99
     {
218e99
         .name       = "balloon",
218e99
-- 
218e99
1.7.1
218e99