Allow passing a socket of an externally launched virtiofsd to the vhost-user-fs device. <filesystem type='mount'> <driver type='virtiofs' queue='1024'/> <source socket='/tmp/sock/'/> </filesystem> https://bugzilla.redhat.com/show_bug.cgi?id=1855789 Signed-off-by: Ján Tomko <jtomko@xxxxxxxxxx> --- docs/schemas/domaincommon.rng | 11 ++++++ src/conf/domain_conf.c | 21 ++++++---- src/conf/domain_conf.h | 1 + src/qemu/qemu_validate.c | 17 ++++---- tests/qemuxml2argvdata/vhost-user-fs-sock.xml | 39 +++++++++++++++++++ .../vhost-user-fs-sock.x86_64-latest.xml | 1 + tests/qemuxml2xmltest.c | 1 + 7 files changed, 76 insertions(+), 15 deletions(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-sock.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-sock.x86_64-latest.xml diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index f5ced5b7a2..361cd44e4e 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2747,9 +2747,18 @@ <ref name="fsBinary"/> </optional> <element name="source"> + <choice> + <group> <attribute name="dir"> <ref name="absDirPath"/> </attribute> + </group> + <group> + <attribute name="socket"> + <ref name="absFilePath"/> + </attribute> + </group> + </choice> <empty/> </element> </interleave> @@ -2811,10 +2820,12 @@ </group> </choice> <interleave> + <optional> <element name="target"> <attribute name="dir"/> <empty/> </element> + </optional> <optional> <attribute name="accessmode"> <choice> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5a1e193b2d..ddf072783b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2472,6 +2472,7 @@ void virDomainFSDefFree(virDomainFSDefPtr def) g_free(def->virtio); virObjectUnref(def->privateData); g_free(def->binary); + g_free(def->sock); g_free(def); } @@ -5490,7 +5491,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDefPtr mem, static int virDomainFSDefPostParse(virDomainFSDefPtr fs) { - if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_DEFAULT) + if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_DEFAULT && !fs->sock) fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH; return 0; @@ -10252,6 +10253,7 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, g_autofree char *multidevs = NULL; g_autofree char *fmode = NULL; g_autofree char *dmode = NULL; + g_autofree char *sock = NULL; ctxt->node = node; @@ -10334,9 +10336,9 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { - if (!source && + if (!source && !sock && virXMLNodeNameEqual(cur, "source")) { - + sock = virXMLPropString(cur, "socket"); if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT || def->type == VIR_DOMAIN_FS_TYPE_BIND) { source = virXMLPropString(cur, "dir"); @@ -10458,13 +10460,13 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } if (source == NULL && def->type != VIR_DOMAIN_FS_TYPE_RAM - && def->type != VIR_DOMAIN_FS_TYPE_VOLUME) { + && def->type != VIR_DOMAIN_FS_TYPE_VOLUME && !sock) { virReportError(VIR_ERR_NO_SOURCE, target ? "%s" : NULL, target); goto error; } - if (target == NULL) { + if (target == NULL && !sock) { virReportError(VIR_ERR_NO_TARGET, source ? "%s" : NULL, source); goto error; @@ -10488,6 +10490,7 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } def->src->path = g_steal_pointer(&source); + def->sock = g_steal_pointer(&sock); def->dst = g_steal_pointer(&target); if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, @@ -22372,7 +22375,7 @@ static bool virDomainFsDefCheckABIStability(virDomainFSDefPtr src, virDomainFSDefPtr dst) { - if (STRNEQ(src->dst, dst->dst)) { + if (STRNEQ_NULLABLE(src->dst, dst->dst)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target filesystem guest target %s does not match source %s"), dst->dst, src->dst); @@ -25508,8 +25511,10 @@ virDomainFSDefFormat(virBufferPtr buf, switch (def->type) { case VIR_DOMAIN_FS_TYPE_MOUNT: case VIR_DOMAIN_FS_TYPE_BIND: - virBufferEscapeString(buf, "<source dir='%s'/>\n", - src); + if (!def->sock) + virBufferEscapeString(buf, "<source dir='%s'/>\n", src); + else + virBufferEscapeString(buf, "<source socket='%s'/>\n", def->sock); break; case VIR_DOMAIN_FS_TYPE_BLOCK: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9c47df99f6..0c1124078b 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -859,6 +859,7 @@ struct _virDomainFSDef { int multidevs; /* virDomainFSMultidevs */ unsigned long long usage; /* in bytes */ virStorageSourcePtr src; + char *sock; char *dst; bool readonly; virDomainDeviceInfo info; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 6043f974ce..0843a7f74a 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4102,26 +4102,29 @@ qemuValidateDomainDeviceDefFS(virDomainFSDefPtr fs, return -1; case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: - if (fs->readonly) { + if (!fs->sock) { + if (fs->readonly) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtiofs does not yet support read-only mode")); return -1; - } - if (!driver->privileged) { + } + if (!driver->privileged) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtiofs is not yet supported in session mode")); return -1; - } - if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) { + } + if (fs->accessmode != VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtiofs only supports passthrough accessmode")); return -1; - } - if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) { + } + if (fs->wrpolicy != VIR_DOMAIN_FS_WRPOLICY_DEFAULT) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtiofs does not support wrpolicy")); return -1; + } } + if (fs->model != VIR_DOMAIN_FS_MODEL_DEFAULT) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("virtiofs does not support model")); diff --git a/tests/qemuxml2argvdata/vhost-user-fs-sock.xml b/tests/qemuxml2argvdata/vhost-user-fs-sock.xml new file mode 100644 index 0000000000..aef005d3fd --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-sock.xml @@ -0,0 +1,39 @@ +<domain type='kvm'> + <name>guest</name> + <uuid>126f2720-6f8e-45ab-a886-ec9277079a67</uuid> + <memory unit='KiB'>14680064</memory> + <currentMemory unit='KiB'>14680064</currentMemory> + <memoryBacking> + <source type='file'/> + <access mode='shared'/> + </memoryBacking> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + <numa> + <cell id='0' cpus='0-1' memory='14680064' unit='KiB' memAccess='shared'/> + </numa> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pci-root'/> + <filesystem type='mount'> + <driver type='virtiofs' queue='1024'/> + <source socket='/tmp/sock'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </filesystem> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/vhost-user-fs-sock.x86_64-latest.xml b/tests/qemuxml2xmloutdata/vhost-user-fs-sock.x86_64-latest.xml new file mode 120000 index 0000000000..ea0382990a --- /dev/null +++ b/tests/qemuxml2xmloutdata/vhost-user-fs-sock.x86_64-latest.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/vhost-user-fs-sock.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 4e7cce21c6..0fe4b3b480 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1415,6 +1415,7 @@ mymain(void) DO_TEST_CAPS_LATEST("vhost-user-fs-fd-memory"); DO_TEST_CAPS_LATEST("vhost-user-fs-hugepages"); + DO_TEST_CAPS_LATEST("vhost-user-fs-sock"); DO_TEST("riscv64-virt", QEMU_CAPS_DEVICE_VIRTIO_MMIO); -- 2.29.2