[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 6/6] qemu-nbd: Add --qmp option to qemu-nbd.
From: |
Benoît Canet |
Subject: |
[Qemu-devel] [RFC 6/6] qemu-nbd: Add --qmp option to qemu-nbd. |
Date: |
Wed, 28 May 2014 16:57:38 +0200 |
This patch add a -qmp parameter to the qemu-nbd command line in order to be able
to manipulate the qemu-nbd block devices via qmp.
This could be used with containers to easily migrate from qemu to a container.
Signed-off-by: Benoit Canet <address@hidden>
---
Makefile.objs | 3 +-
include/monitor/monitor-init.h | 34 ++++++++++++
monitor-init.c | 121 +++++++++++++++++++++++++++++++++++++++++
monitor.c | 1 +
qemu-nbd.c | 33 ++++++++++-
vl.c | 88 +-----------------------------
6 files changed, 190 insertions(+), 90 deletions(-)
create mode 100644 include/monitor/monitor-init.h
create mode 100644 monitor-init.c
diff --git a/Makefile.objs b/Makefile.objs
index 51597dd..bbf32cc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -25,6 +25,7 @@ qapi-block-obj-y = block/qapi-generated/qmp-marshal.o
blockdev.o qmp.o
qapi-block-obj-y += qmp-stub.o qemu-log.o monitor.o qemu-char.o
qapi-block-obj-y += block/
qapi-block-obj-y += qom/
+qapi-block-obj-y += monitor-init.o
LIBS += -lutil
######################################################################
@@ -74,7 +75,7 @@ common-obj-y += bt-host.o bt-vhci.o
bt-host.o-cflags := $(BLUEZ_CFLAGS)
common-obj-y += dma-helpers.o
-common-obj-y += vl.o
+common-obj-y += vl.o monitor-init.o
vl.o-cflags := $(GPROF_CFLAGS) $(SDL_CFLAGS)
common-obj-y += tpm.o
diff --git a/include/monitor/monitor-init.h b/include/monitor/monitor-init.h
new file mode 100644
index 0000000..23be581
--- /dev/null
+++ b/include/monitor/monitor-init.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MONITOR_INIT_H
+#define MONITOR_INIT_H
+
+#include "qemu/option.h"
+
+int chardev_init_func(QemuOpts *opts, void *opaque);
+int mon_init_func(QemuOpts *opts, void *opaque);
+void monitor_parse(const char *optarg, const char *mode);
+
+#endif
diff --git a/monitor-init.c b/monitor-init.c
new file mode 100644
index 0000000..9888286
--- /dev/null
+++ b/monitor-init.c
@@ -0,0 +1,121 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "monitor/monitor-init.h"
+#include "monitor/monitor.h"
+#include "sysemu/char.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int chardev_init_func(QemuOpts *opts, void *opaque)
+{
+ Error *local_err = NULL;
+
+ qemu_chr_new_from_opts(opts, NULL, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ error_free(local_err);
+ return -1;
+ }
+ return 0;
+}
+
+int mon_init_func(QemuOpts *opts, void *opaque)
+{
+ CharDriverState *chr;
+ const char *chardev;
+ const char *mode;
+ int flags;
+
+ mode = qemu_opt_get(opts, "mode");
+ if (mode == NULL) {
+ mode = "readline";
+ }
+ if (strcmp(mode, "readline") == 0) {
+ flags = MONITOR_USE_READLINE;
+ } else if (strcmp(mode, "control") == 0) {
+ flags = MONITOR_USE_CONTROL;
+ } else {
+ fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
+ exit(1);
+ }
+
+ if (qemu_opt_get_bool(opts, "pretty", 0)) {
+ flags |= MONITOR_USE_PRETTY;
+ }
+
+ if (qemu_opt_get_bool(opts, "default", 0)) {
+ flags |= MONITOR_IS_DEFAULT;
+ }
+
+ chardev = qemu_opt_get(opts, "chardev");
+ chr = qemu_chr_find(chardev);
+ if (chr == NULL) {
+ fprintf(stderr, "chardev \"%s\" not found\n", chardev);
+ exit(1);
+ }
+
+ qemu_chr_fe_claim_no_fail(chr);
+ monitor_init(chr, flags);
+ return 0;
+}
+
+void monitor_parse(const char *optarg, const char *mode)
+{
+ static int monitor_device_index;
+ QemuOpts *opts;
+ const char *p;
+ char label[32];
+ int def = 0;
+
+ if (strstart(optarg, "chardev:", &p)) {
+ snprintf(label, sizeof(label), "%s", p);
+ } else {
+ snprintf(label, sizeof(label), "compat_monitor%d",
+ monitor_device_index);
+ if (monitor_device_index == 0) {
+ def = 1;
+ }
+ opts = qemu_chr_parse_compat(label, optarg);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
+ }
+
+ opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, NULL);
+ if (!opts) {
+ fprintf(stderr, "duplicate chardev: %s\n", label);
+ exit(1);
+ }
+ qemu_opt_set(opts, "mode", mode);
+ qemu_opt_set(opts, "chardev", label);
+ if (def) {
+ qemu_opt_set(opts, "default", "on");
+ }
+ monitor_device_index++;
+}
+
diff --git a/monitor.c b/monitor.c
index b8ca834..d70bb61 100644
--- a/monitor.c
+++ b/monitor.c
@@ -139,6 +139,7 @@ static mon_cmd_t info_cmds[] = {
};
size_t sizeof_info_cmds = sizeof(info_cmds);
static const mon_cmd_t qmp_cmds[] = {
+#include "block/qapi-generated/qmp-commands-old.h"
{ /* NULL */ },
};
#else
diff --git a/qemu-nbd.c b/qemu-nbd.c
index 621e654..5385164 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -16,13 +16,16 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "monitor/monitor-init.h"
#include "qemu-common.h"
#include "block/block.h"
#include "block/nbd.h"
+#include "qemu/config-file.h"
#include "qemu/main-loop.h"
#include "qemu/sockets.h"
#include "qemu/error-report.h"
#include "block/snapshot.h"
+#include "sysemu/sysemu.h"
#include <stdarg.h>
#include <stdio.h>
@@ -97,6 +100,9 @@ static void usage(const char *name)
" --aio=MODE set AIO mode (native or threads)\n"
#endif
"\n"
+"Management options:\n"
+" -q, --qmp=DEV machine monitor listen on DEV\n"
+"\n"
"Report bugs to <address@hidden>\n"
, name, NBD_DEFAULT_PORT, "DEVICE");
}
@@ -387,7 +393,7 @@ int main(int argc, char **argv)
off_t fd_size;
QemuOpts *sn_opts = NULL;
const char *sn_id_or_name = NULL;
- const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:";
+ const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:q:";
struct option lopt[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
@@ -409,6 +415,7 @@ int main(int argc, char **argv)
{ "discard", 1, NULL, QEMU_NBD_OPT_DISCARD },
{ "shared", 1, NULL, 'e' },
{ "format", 1, NULL, 'f' },
+ { "qmp", 1, NULL, 'q' },
{ "persistent", 0, NULL, 't' },
{ "verbose", 0, NULL, 'v' },
{ NULL, 0, NULL, 0 }
@@ -429,6 +436,11 @@ int main(int argc, char **argv)
pthread_t client_thread;
const char *fmt = NULL;
Error *local_err = NULL;
+ bool has_qmp = false;
+
+ module_call_init(MODULE_INIT_QOM);
+ qemu_add_opts(&qemu_mon_opts);
+ qemu_add_opts(&qemu_chardev_opts);
/* The client thread uses SIGTERM to interrupt the server. A signal
* handler ensures that "qemu-nbd -v -c" exits with a nice status code.
@@ -550,6 +562,10 @@ int main(int argc, char **argv)
case 't':
persistent = 1;
break;
+ case 'q':
+ monitor_parse(optarg, "control");
+ has_qmp = true;
+ break;
case 'v':
verbose = 1;
break;
@@ -573,6 +589,15 @@ int main(int argc, char **argv)
argv[0]);
}
+ if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func,
+ NULL, 1) != 0) {
+ exit(1);
+ }
+
+ if (qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, 1) != 0)
{
+ exit(1);
+ }
+
if (disconnect) {
fd = open(argv[optind], O_RDWR);
if (fd < 0) {
@@ -722,8 +747,10 @@ int main(int argc, char **argv)
(void *)(uintptr_t)fd);
/* now when the initialization is (almost) complete, chdir("/")
- * to free any busy filesystems */
- if (chdir("/") < 0) {
+ * to free any busy filesystems. We don't do this when QMP is used to avoid
+ * disturbing snapshot taking.
+ */
+ if (!has_qmp && chdir("/") < 0) {
err(EXIT_FAILURE, "Could not chdir to root directory");
}
diff --git a/vl.c b/vl.c
index 709d8cd..d959ad1 100644
--- a/vl.c
+++ b/vl.c
@@ -118,6 +118,8 @@ int main(int argc, char **argv)
#include "qapi/string-input-visitor.h"
#include "qom/object_interfaces.h"
+#include "monitor/monitor-init.h"
+
#define DEFAULT_RAM_SIZE 128
#define MAX_VIRTIO_CONSOLES 1
@@ -2416,19 +2418,6 @@ static int device_init_func(QemuOpts *opts, void *opaque)
return 0;
}
-static int chardev_init_func(QemuOpts *opts, void *opaque)
-{
- Error *local_err = NULL;
-
- qemu_chr_new_from_opts(opts, NULL, &local_err);
- if (local_err) {
- error_report("%s", error_get_pretty(local_err));
- error_free(local_err);
- return -1;
- }
- return 0;
-}
-
#ifdef CONFIG_VIRTFS
static int fsdev_init_func(QemuOpts *opts, void *opaque)
{
@@ -2439,79 +2428,6 @@ static int fsdev_init_func(QemuOpts *opts, void *opaque)
}
#endif
-static int mon_init_func(QemuOpts *opts, void *opaque)
-{
- CharDriverState *chr;
- const char *chardev;
- const char *mode;
- int flags;
-
- mode = qemu_opt_get(opts, "mode");
- if (mode == NULL) {
- mode = "readline";
- }
- if (strcmp(mode, "readline") == 0) {
- flags = MONITOR_USE_READLINE;
- } else if (strcmp(mode, "control") == 0) {
- flags = MONITOR_USE_CONTROL;
- } else {
- fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
- exit(1);
- }
-
- if (qemu_opt_get_bool(opts, "pretty", 0))
- flags |= MONITOR_USE_PRETTY;
-
- if (qemu_opt_get_bool(opts, "default", 0))
- flags |= MONITOR_IS_DEFAULT;
-
- chardev = qemu_opt_get(opts, "chardev");
- chr = qemu_chr_find(chardev);
- if (chr == NULL) {
- fprintf(stderr, "chardev \"%s\" not found\n", chardev);
- exit(1);
- }
-
- qemu_chr_fe_claim_no_fail(chr);
- monitor_init(chr, flags);
- return 0;
-}
-
-static void monitor_parse(const char *optarg, const char *mode)
-{
- static int monitor_device_index = 0;
- QemuOpts *opts;
- const char *p;
- char label[32];
- int def = 0;
-
- if (strstart(optarg, "chardev:", &p)) {
- snprintf(label, sizeof(label), "%s", p);
- } else {
- snprintf(label, sizeof(label), "compat_monitor%d",
- monitor_device_index);
- if (monitor_device_index == 0) {
- def = 1;
- }
- opts = qemu_chr_parse_compat(label, optarg);
- if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
- exit(1);
- }
- }
-
- opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, NULL);
- if (!opts) {
- fprintf(stderr, "duplicate chardev: %s\n", label);
- exit(1);
- }
- qemu_opt_set(opts, "mode", mode);
- qemu_opt_set(opts, "chardev", label);
- if (def)
- qemu_opt_set(opts, "default", "on");
- monitor_device_index++;
-}
-
struct device_config {
enum {
DEV_USB, /* -usbdevice */
--
1.9.1
- [Qemu-devel] [RFC 0/6] Add the --qmp option to qemu-nbd, Benoît Canet, 2014/05/28
- [Qemu-devel] [RFC 6/6] qemu-nbd: Add --qmp option to qemu-nbd.,
Benoît Canet <=
- [Qemu-devel] [RFC 3/6] qemu-nbd: build QAPI block core into qemu-nbd, Benoît Canet, 2014/05/28
- [Qemu-devel] [RFC 2/6] qmp: Extract system emulation related code from qmp.c into qmp-system.c, Benoît Canet, 2014/05/28
- [Qemu-devel] [RFC 5/6] qapi: Add a script to filter qmp-commands-old.h to generate a subset of it., Benoît Canet, 2014/05/28
- [Qemu-devel] [RFC 1/6] qapi: Extract QAPI block and common definitions., Benoît Canet, 2014/05/28
- [Qemu-devel] [RFC 4/6] monitor: Split monitor in two parts: core and system., Benoît Canet, 2014/05/28