From: Coiby Xu <coiby.xu@gmail.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, bharatlkmlkvm@gmail.com,
Coiby Xu <coiby.xu@gmail.com>,
stefanha@redhat.com
Subject: [PATCH v2 3/5] a standone-alone tool to directly share disk image file via vhost-user protocol
Date: Tue, 14 Jan 2020 22:06:18 +0800 [thread overview]
Message-ID: <20200114140620.10385-4-coiby.xu@gmail.com> (raw)
In-Reply-To: <20200114140620.10385-1-coiby.xu@gmail.com>
vhost-user-blk can have played as vhost-user backend but it only supports raw file and don't support VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES operations on raw file (ioctl(fd, BLKDISCARD) is only valid for real block device).
Signed-off-by: Coiby Xu <coiby.xu@gmail.com>
---
qemu-vu.c | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 264 insertions(+)
create mode 100644 qemu-vu.c
diff --git a/qemu-vu.c b/qemu-vu.c
new file mode 100644
index 0000000000..25c32c2c6d
--- /dev/null
+++ b/qemu-vu.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2020 Coiby Xu <coiby.xu@gmail.com>
+ *
+ * Vhost-user-blk device backend
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include <getopt.h>
+#include <libgen.h>
+#include "block/vhost-user.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "qemu/cutils.h"
+#include "sysemu/block-backend.h"
+#include "block/block_int.h"
+#include "qemu/main-loop.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/error-report.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qstring.h"
+#include "qom/object_interfaces.h"
+#include "io/net-listener.h"
+#include "qemu-version.h"
+
+#define QEMU_VU_OPT_CACHE 256
+
+#define QEMU_VU_OPT_AIO 257
+
+static char *srcpath;
+
+static void usage(const char *name)
+{
+ (printf) (
+"Usage: %s [OPTIONS] FILE\n"
+" or: %s -L [OPTIONS]\n"
+"QEMU Vhost-user Server Utility\n"
+"\n"
+" -h, --help display this help and exit\n"
+" -V, --version output version information and exit\n"
+"\n"
+"Connection properties:\n"
+" -k, --socket=PATH path to the unix socket\n"
+"\n"
+"General purpose options:\n"
+" -e, -- exit-panic When the panic callback is called, the program\n"
+" will exit. Useful for make check-qtest.\n"
+"\n"
+"Block device options:\n"
+" -f, --format=FORMAT set image format (raw, qcow2, ...)\n"
+" -r, --read-only export read-only\n"
+" -n, --nocache disable host cache\n"
+" --cache=MODE set cache mode (none, writeback, ...)\n"
+" --aio=MODE set AIO mode (native or threads)\n"
+"\n"
+QEMU_HELP_BOTTOM "\n"
+ , name, name);
+}
+
+static void version(const char *name)
+{
+ printf(
+"%s " QEMU_FULL_VERSION "\n"
+"Written by Coiby Xu, based on qemu-nbd by Anthony Liguori\n"
+"\n"
+QEMU_COPYRIGHT "\n"
+"This is free software; see the source for copying conditions. There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+ , name);
+}
+
+static VubDev *vub_device;
+
+static void vus_shutdown(void)
+{
+ job_cancel_sync_all();
+ bdrv_close_all();
+ vub_free(vub_device, false);
+}
+
+int main(int argc, char **argv)
+{
+ BlockBackend *blk;
+ BlockDriverState *bs;
+ bool readonly = false;
+ char *sockpath = NULL;
+ int64_t fd_size;
+ const char *sopt = "hVrnvek:f:";
+ struct option lopt[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "exit-panic", no_argument, NULL, 'e' },
+ { "socket", required_argument, NULL, 'k' },
+ { "read-only", no_argument, NULL, 'r' },
+ { "nocache", no_argument, NULL, 'n' },
+ { "cache", required_argument, NULL, QEMU_VU_OPT_CACHE },
+ { "aio", required_argument, NULL, QEMU_VU_OPT_AIO },
+ { "format", required_argument, NULL, 'f' },
+ { NULL, 0, NULL, 0 }
+ };
+ int ch;
+ int opt_ind = 0;
+ int flags = BDRV_O_RDWR;
+ bool seen_cache = false;
+ bool seen_aio = false;
+ const char *fmt = NULL;
+ Error *local_err = NULL;
+ QDict *options = NULL;
+ bool writethrough = true;
+ bool exit_panic = false;
+
+ error_init(argv[0]);
+
+ module_call_init(MODULE_INIT_QOM);
+ qemu_init_exec_dir(argv[0]);
+
+ while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+ switch (ch) {
+ case 'e':
+ exit_panic = true;
+ break;
+ case 'n':
+ optarg = (char *) "none";
+ /* fallthrough */
+ case QEMU_VU_OPT_CACHE:
+ if (seen_cache) {
+ error_report("-n and --cache can only be specified once");
+ exit(EXIT_FAILURE);
+ }
+ seen_cache = true;
+ if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) == -1) {
+ error_report("Invalid cache mode `%s'", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case QEMU_VU_OPT_AIO:
+ if (seen_aio) {
+ error_report("--aio can only be specified once");
+ exit(EXIT_FAILURE);
+ }
+ seen_aio = true;
+ if (!strcmp(optarg, "native")) {
+ flags |= BDRV_O_NATIVE_AIO;
+ } else if (!strcmp(optarg, "threads")) {
+ /* this is the default */
+ } else {
+ error_report("invalid aio mode `%s'", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'r':
+ readonly = true;
+ flags &= ~BDRV_O_RDWR;
+ break;
+ case 'k':
+ sockpath = optarg;
+ if (sockpath[0] != '/') {
+ error_report("socket path must be absolute");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'V':
+ version(argv[0]);
+ exit(0);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ case '?':
+ error_report("Try `%s --help' for more information.", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if ((argc - optind) != 1) {
+ error_report("Invalid number of arguments");
+ error_printf("Try `%s --help' for more information.\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (qemu_init_main_loop(&local_err)) {
+ error_report_err(local_err);
+ exit(EXIT_FAILURE);
+ }
+ bdrv_init();
+
+ srcpath = argv[optind];
+ if (fmt) {
+ options = qdict_new();
+ qdict_put_str(options, "driver", fmt);
+ }
+ blk = blk_new_open(srcpath, NULL, options, flags, &local_err);
+
+ if (!blk) {
+ error_reportf_err(local_err, "Failed to blk_new_open '%s': ",
+ argv[optind]);
+ exit(EXIT_FAILURE);
+ }
+ bs = blk_bs(blk);
+
+ blk_set_enable_write_cache(blk, !writethrough);
+
+ fd_size = blk_getlength(blk);
+ if (fd_size < 0) {
+ error_report("Failed to determine the image length: %s",
+ strerror(-fd_size));
+ exit(EXIT_FAILURE);
+ }
+
+ AioContext *ctx = bdrv_get_aio_context(bs);
+ bdrv_invalidate_cache(bs, NULL);
+
+ vub_device = g_new0(VubDev, 1);
+ vub_device->unix_socket = g_strdup(sockpath);
+ vub_device->writable = !readonly;
+ vub_device->blkcfg.wce = !writethrough;
+ vub_device->backend = blk;
+ vub_device->ctx = ctx;
+ vub_initialize_config(bs, &vub_device->blkcfg);
+ vub_device->listener = qio_net_listener_new();
+ vub_device->exit_panic = exit_panic;
+
+ qio_net_listener_set_name(vub_device->listener,
+ "vhost-user-backend-listener");
+
+ SocketAddress *addr = g_new0(SocketAddress, 1);
+ addr->u.q_unix.path = (char *) sockpath;
+ addr->type = SOCKET_ADDRESS_TYPE_UNIX;
+ Error **errp = NULL;
+ if (qio_net_listener_open_sync(vub_device->listener, addr, 1, errp) < 0) {
+ goto error;
+ }
+
+ qio_net_listener_set_client_func(vub_device->listener,
+ vub_accept,
+ vub_device,
+ NULL);
+
+ QTAILQ_INIT(&vub_device->clients);
+
+ do {
+ main_loop_wait(false);
+ } while (!vub_device->exit_panic || !vub_device->close);
+
+ error:
+ vus_shutdown();
+ exit(EXIT_SUCCESS);
+}
--
2.24.1
next prev parent reply other threads:[~2020-01-14 14:14 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-14 14:06 [PATCH v2 0/5] vhost-user block device backend implementation Coiby Xu
2020-01-14 14:06 ` [PATCH v2 1/5] vhost-user block device backend Coiby Xu
2020-01-16 13:51 ` Stefan Hajnoczi
2020-01-16 14:20 ` Kevin Wolf
2020-02-14 3:07 ` Coiby Xu
2020-01-16 13:56 ` Kevin Wolf
2020-02-20 7:04 ` Coiby Xu
2020-02-20 9:30 ` Coiby Xu
2020-01-14 14:06 ` [PATCH v2 2/5] extend libvhost to support IOThread Coiby Xu
2020-01-14 14:06 ` Coiby Xu [this message]
2020-01-16 14:04 ` [PATCH v2 3/5] a standone-alone tool to directly share disk image file via vhost-user protocol Stefan Hajnoczi
2020-01-17 8:12 ` Coiby Xu
2020-01-17 10:11 ` Kevin Wolf
2020-01-31 16:42 ` Coiby Xu
2020-02-02 9:33 ` Kevin Wolf
2020-02-13 1:00 ` Coiby Xu
2020-01-14 14:06 ` [PATCH v2 4/5] new qTest case for the vhost-user-blk device backend Coiby Xu
2020-01-14 14:06 ` [PATCH v2 5/5] building configuration files changes Coiby Xu
2020-01-16 11:07 ` Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200114140620.10385-4-coiby.xu@gmail.com \
--to=coiby.xu@gmail.com \
--cc=bharatlkmlkvm@gmail.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).