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