From nobody Fri Oct 10 16:39:36 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1583748379; cv=none; d=zohomail.com; s=zohoarc; b=Ty4pysNxHJ6DeVNPVy34IDgzaqNOHBlwxwbKb9fR+aaX0YVJn8F191fdGg627/+PQ5NT0t3iEFkayzq1dXHVKPa4+6zYw/r17d71/45735bdTDMBNAcvblEwwBg0JTWL8GaXKlxUQxtZM2mKDAW0KNuHolXuW+uw2d+xtjndCUI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1583748379; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eoWTkg9RP/Ne3BvQ1PvrWsx/dFnp1ZYmLM2v/TTJ4c8=; b=cc+ZE3BRA+UUA3wp7/7VkSfmTP5BbAy+7VF1FiqxL81A4FKZRQUKi8taklksY0M1OgPKteyUZR720LIghRuRpeKJAkJwo3riuTz23qwmvV1Ns2Ut7B3jaP/u+9xEznTaKp3fwhy7fylgubIVScx0SYDgLCAuk63bWBy18tcymiw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1583748379527544.759315871153; Mon, 9 Mar 2020 03:06:19 -0700 (PDT) Received: from localhost ([::1]:39888 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jBFIg-0003n0-9W for importer@patchew.org; Mon, 09 Mar 2020 06:06:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34689) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jBFHL-00023D-3J for qemu-devel@nongnu.org; Mon, 09 Mar 2020 06:04:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jBFHJ-0008Ee-6P for qemu-devel@nongnu.org; Mon, 09 Mar 2020 06:04:55 -0400 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]:38303) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1jBFHI-0008EK-U8 for qemu-devel@nongnu.org; Mon, 09 Mar 2020 06:04:53 -0400 Received: by mail-pj1-x1044.google.com with SMTP id a16so4222476pju.3 for ; Mon, 09 Mar 2020 03:04:52 -0700 (PDT) Received: from localhost.localdomain (tunnel571398-pt.tunnel.tserv14.sea1.ipv6.he.net. [2001:470:a:247::2]) by smtp.googlemail.com with ESMTPSA id s21sm16077377pfd.99.2020.03.09.03.04.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Mar 2020 03:04:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=eoWTkg9RP/Ne3BvQ1PvrWsx/dFnp1ZYmLM2v/TTJ4c8=; b=UK516x8llT1W8zIa7InnNDNwyPLNB3PtbgXDRltrMwGJYhPXTPVWpnYqKveszBhGqh 0G9UpwJTTXRn6zsAueU09SJ19VC8uKhO+V5xjFbaby1MXbKH60OvdkvWPt880eeRfutl ig6FqQKc7FhGTA3dUndLPtCgcps1L1VBpYsner9L3iQcGBsNaW+Dy1Z7Ydg5TrRSomrl 6QeOjiMDjI2AZKZ4Hfdhjcmh4CgikrSyFbwRc3rJi8fE+dUFprPoUXfF2MZY0XNAl+hb WJ+FqQRaCBdfMyWb6FysuCrq5zTKNV36ql+sqi7JLe1fKcMR4Ei8FjpshWCSd6lBYq/a Pf/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=eoWTkg9RP/Ne3BvQ1PvrWsx/dFnp1ZYmLM2v/TTJ4c8=; b=M8NFkrDeqfASEBdnjBx5i5JbKO1qetyTVVdK+GVDoA+dIVi61w62551sGgctPOndmh lVuQV23J8fAdjumlrWjIoz/mHa6ScEx2KUTP83eqlwHqvvzvhMFbI727pRza1/VBvZui TYG7pMpJYRflaeNJNA1k7R7pCkhyaDWX8/80kwzVrU3jbBbdbQt+4oRyIB49KHJFykcd sBY4lq0n16wrpmqDeWd27t3uYMDjeDGACl+/SX2ujc6VlpdGokRQ1bUhfeyIdr3ypOHZ rZdWzf4Y2mNNHE+RE3Z0vewVaNElQRctHjdIN1/t5EPpxunC6ZYCJ4+Wzy/wUh/DGgsj eVgQ== X-Gm-Message-State: ANhLgQ27eJKZvv1Q11JGdWsi3UXrG2VZwvipn3AT6OLgVtZkJtSh+uP1 iF2O5hRomOqCfoOiexnzsMN8c4e5Vz8QBg== X-Google-Smtp-Source: ADFU+vufRJzYKc6qz8mQ/rIH5S0S2KFxJl8UtPIumvH2GynV1VFxA0ejQyPAWticI5yx7rf0VN00Ew== X-Received: by 2002:a17:902:a710:: with SMTP id w16mr15112774plq.43.1583748291674; Mon, 09 Mar 2020 03:04:51 -0700 (PDT) From: Coiby Xu To: qemu-devel@nongnu.org Subject: [PATCH v5 4/5] a standone-alone tool to directly share disk image file via vhost-user protocol Date: Mon, 9 Mar 2020 18:03:41 +0800 Message-Id: <20200309100342.14921-5-coiby.xu@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200309100342.14921-1-coiby.xu@gmail.com> References: <20200309100342.14921-1-coiby.xu@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::1044 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, bharatlkmlkvm@gmail.com, Coiby Xu , stefanha@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" vhost-user-blk could 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). Kevin's qemu-storage-daemon will be used to replace this tool after his patches are merged into the mainline QEMU. Signed-off-by: Coiby Xu --- Makefile | 4 + configure | 3 + qemu-vu.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 qemu-vu.c diff --git a/Makefile b/Makefile index 9d4b224126..6da192222d 100644 --- a/Makefile +++ b/Makefile @@ -585,6 +585,10 @@ qemu-img.o: qemu-img-cmds.h =20 qemu-img$(EXESUF): qemu-img.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y= ) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) qemu-nbd$(EXESUF): qemu-nbd.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y= ) $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) + +ifdef CONFIG_LINUX +qemu-vu$(EXESUF): qemu-vu.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) = $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) +endif qemu-io$(EXESUF): qemu-io.o $(authz-obj-y) $(block-obj-y) $(crypto-obj-y) = $(io-obj-y) $(qom-obj-y) $(COMMON_LDADDS) =20 qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o $(COMMON_LDADDS) diff --git a/configure b/configure index fab6281eb7..53dd9fb88f 100755 --- a/configure +++ b/configure @@ -6318,6 +6318,9 @@ if test "$want_tools" =3D "yes" ; then if [ "$linux" =3D "yes" -o "$bsd" =3D "yes" -o "$solaris" =3D "yes" ] ; = then tools=3D"qemu-nbd\$(EXESUF) $tools" fi + if [ "$linux" =3D "yes" ] ; then + tools=3D"qemu-vu\$(EXESUF) $tools" + fi if [ "$ivshmem" =3D "yes" ]; then tools=3D"ivshmem-client\$(EXESUF) ivshmem-server\$(EXESUF) $tools" fi diff --git a/qemu-vu.c b/qemu-vu.c new file mode 100644 index 0000000000..3d2e4df5eb --- /dev/null +++ b/qemu-vu.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2020 Coiby Xu + * + * standone-alone vhost-user-blk device server 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 . + */ + +#include "qemu/osdep.h" +#include +#include +#include "block/export/vhost-user-blk-server.h" +#include "block/block_int.h" +#include "io/net-listener.h" +#include "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" +#include "qemu/config-file.h" +#include "qemu/cutils.h" +#include "qemu/main-loop.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qemu-common.h" +#include "qemu-version.h" +#include "qom/object_interfaces.h" +#include "sysemu/block-backend.h" +#define QEMU_VU_OPT_CACHE 256 +#define QEMU_VU_OPT_AIO 257 +#define QEMU_VU_OBJ_ID "vu_disk" +static QemuOptsList qemu_object_opts =3D { + .name =3D "object", + .implied_opt_name =3D "qom-type", + .head =3D QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head), + .desc =3D { + { } + }, +}; +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=3DPATH path to the unix socket\n" +"\n" +"General purpose options:\n" +" -e, -- exit-panic When the panic callback is called, the progra= m\n" +" will exit. Useful for make check-qtest.\n" +"\n" +"Block device options:\n" +" -f, --format=3DFORMAT set image format (raw, qcow2, ...)\n" +" -r, --read-only export read-only\n" +" -n, --nocache disable host cache\n" +" --cache=3DMODE set cache mode (none, writeback, ...)\n" +" --aio=3DMODE 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 N= O\n" +"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS= E.\n" + , name); +} + +static VuBlockDev *vu_block_device; + +static void vus_shutdown(void) +{ + + Error *local_err =3D NULL; + job_cancel_sync_all(); + bdrv_close_all(); + user_creatable_del(QEMU_VU_OBJ_ID, &local_err); +} + +int main(int argc, char **argv) +{ + BlockBackend *blk; + BlockDriverState *bs; + bool readonly =3D false; + char *sockpath =3D NULL; + const char *sopt =3D "hVrnvek:f:"; + struct option lopt[] =3D { + { "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 =3D 0; + int flags =3D BDRV_O_RDWR; + bool seen_cache =3D false; + bool seen_aio =3D false; + const char *fmt =3D NULL; + Error *local_err =3D NULL; + QDict *options =3D NULL; + bool writethrough =3D true; + bool exit_when_panic =3D false; + + error_init(argv[0]); + + module_call_init(MODULE_INIT_QOM); + qemu_init_exec_dir(argv[0]); + + while ((ch =3D getopt_long(argc, argv, sopt, lopt, &opt_ind)) !=3D -1)= { + switch (ch) { + case 'e': + exit_when_panic =3D true; + break; + case 'n': + optarg =3D (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 =3D true; + if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) =3D= =3D -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 =3D true; + if (!strcmp(optarg, "native")) { + flags |=3D 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 =3D true; + flags &=3D ~BDRV_O_RDWR; + break; + case 'k': + sockpath =3D optarg; + if (sockpath[0] !=3D '/') { + error_report("socket path must be absolute"); + exit(EXIT_FAILURE); + } + break; + case 'f': + fmt =3D 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) !=3D 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 =3D argv[optind]; + if (fmt) { + options =3D qdict_new(); + qdict_put_str(options, "driver", fmt); + } + blk =3D 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 =3D blk_bs(blk); + + char buf[300]; + snprintf(buf, 300, "%s,id=3D%s,node-name=3D%s,unix-socket=3D%s,writabl= e=3D%s", + TYPE_VHOST_USER_BLK_SERVER, QEMU_VU_OBJ_ID, bdrv_get_node_nam= e(bs), + sockpath, !readonly ? "on" : "off"); + /* While calling user_creatable_del, 'object' group is required */ + qemu_add_opts(&qemu_object_opts); + QemuOpts *opts =3D qemu_opts_parse(&qemu_object_opts, buf, true, &loca= l_err); + if (local_err) { + error_report_err(local_err); + goto error; + } + + Object *obj =3D user_creatable_add_opts(opts, &local_err); + + if (local_err) { + error_report_err(local_err); + goto error; + } + + vu_block_device =3D VHOST_USER_BLK_SERVER(obj); + vu_block_device->exit_when_panic =3D exit_when_panic; + + do { + main_loop_wait(false); + } while (!vu_block_device->exit_when_panic || !vu_block_device->vu_ser= ver->close); + + error: + vus_shutdown(); + exit(EXIT_SUCCESS); +} --=20 2.25.1