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(a)redhat.com>
---
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