diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 20a43148b1..046f17b3ae 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2763,9 +2763,18 @@
+
+
+
+
+
+
+
+
+
@@ -2827,10 +2836,12 @@
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a9ed74f33e..f30c1b9e5d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2480,6 +2480,7 @@ void virDomainFSDefFree(virDomainFSDef *def)
g_free(def->virtio);
virObjectUnref(def->privateData);
g_free(def->binary);
+ g_free(def->sock);
g_free(def);
}
@@ -5516,7 +5517,7 @@ virDomainMemoryDefPostParse(virDomainMemoryDef *mem,
static int
virDomainFSDefPostParse(virDomainFSDef *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;
@@ -10031,6 +10032,7 @@ virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
g_autofree char *multidevs = NULL;
g_autofree char *fmode = NULL;
g_autofree char *dmode = NULL;
+ g_autofree char *sock = NULL;
ctxt->node = node;
@@ -10113,9 +10115,9 @@ virDomainFSDefParseXML(virDomainXMLOption *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");
@@ -10237,13 +10239,13 @@ virDomainFSDefParseXML(virDomainXMLOption *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;
@@ -10267,6 +10269,7 @@ virDomainFSDefParseXML(virDomainXMLOption *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,
@@ -22199,7 +22202,7 @@ static bool
virDomainFsDefCheckABIStability(virDomainFSDef *src,
virDomainFSDef *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);
@@ -25337,8 +25340,10 @@ virDomainFSDefFormat(virBuffer *buf,
switch (def->type) {
case VIR_DOMAIN_FS_TYPE_MOUNT:
case VIR_DOMAIN_FS_TYPE_BIND:
- virBufferEscapeString(buf, "\n",
- src);
+ if (!def->sock)
+ virBufferEscapeString(buf, "\n", src);
+ else
+ virBufferEscapeString(buf, "\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 e808c09ef2..4d1826362f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -861,6 +861,7 @@ struct _virDomainFSDef {
int multidevs; /* virDomainFSMultidevs */
unsigned long long usage; /* in bytes */
virStorageSource *src;
+ char *sock;
char *dst;
bool readonly;
virDomainDeviceInfo info;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 44d20088bf..60befb2282 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -4162,26 +4162,29 @@ qemuValidateDomainDeviceDefFS(virDomainFSDef *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 @@
+
+ guest
+ 126f2720-6f8e-45ab-a886-ec9277079a67
+ 14680064
+ 14680064
+
+
+
+
+ 2
+
+ hvm
+
+
+
+ qemu64
+
+ |
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
+
+
+
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 32b68fcfb0..c37de0c704 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1434,6 +1434,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);