[libvirt PATCHv2 00/10] add virtiofs support (virtio-fs epopee)

v1: https://www.redhat.com/archives/libvir-list/2019-November/msg00005.html https://bugzilla.redhat.com/show_bug.cgi?id=1694166 Ján Tomko (10): conf: use virXMLFormatElement in virDomainFSDefFormat qemu: add QEMU_CAPS_VHOST_USER_FS schema: wrap fsDriver in a choice group conf: qemu: add virtiofs fsdriver type conf: add virtiofs-related elements and attributes qemu: add virtiofs_debug to qemu.conf qemu: validate virtiofs filesystems qemu: add code for handling virtiofsd qemu: build vhost-user-fs device command line docs: add virtiofs kbase docs/formatdomain.html.in | 23 ++ docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 +++++++++++ docs/schemas/domaincommon.rng | 117 +++++++-- po/POTFILES.in | 1 + src/conf/domain_conf.c | 161 +++++++++++- src/conf/domain_conf.h | 17 ++ src/libvirt_private.syms | 1 + src/qemu/Makefile.inc.am | 2 + src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf | 7 + src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 49 +++- src/qemu/qemu_conf.c | 2 + src/qemu/qemu_conf.h | 1 + src/qemu/qemu_domain.c | 36 +++ src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_domain_address.c | 4 + src/qemu/qemu_extdevice.c | 19 ++ src/qemu/qemu_virtiofs.c | 241 ++++++++++++++++++ src/qemu/qemu_virtiofs.h | 37 +++ src/qemu/test_libvirtd_qemu.aug.in | 1 + .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + ...vhost-user-fs-fd-memory.x86_64-latest.args | 38 +++ .../vhost-user-fs-fd-memory.xml | 42 +++ ...vhost-user-fs-hugepages.x86_64-latest.args | 46 ++++ .../vhost-user-fs-hugepages.xml | 75 ++++++ tests/qemuxml2argvtest.c | 9 + .../vhost-user-fs-fd-memory.x86_64-latest.xml | 1 + .../vhost-user-fs-hugepages.x86_64-latest.xml | 1 + tests/qemuxml2xmltest.c | 3 + 34 files changed, 1064 insertions(+), 35 deletions(-) create mode 100644 docs/kbase/virtiofs.rst create mode 100644 src/qemu/qemu_virtiofs.c create mode 100644 src/qemu/qemu_virtiofs.h create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml -- 2.21.0

Use the virXMLFormatElement helper to format the driver element to simplify adding further sub-elements. Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/conf/domain_conf.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 707d58e1a4..6deb8e5434 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -24996,7 +24996,7 @@ virDomainFSDefFormat(virBufferPtr buf, const char *fsdriver = virDomainFSDriverTypeToString(def->fsdriver); const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy); const char *src = def->src->path; - g_auto(virBuffer) driverBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; if (!type) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -25021,25 +25021,21 @@ virDomainFSDefFormat(virBufferPtr buf, virBufferAdjustIndent(buf, 2); if (def->fsdriver) { - virBufferAsprintf(&driverBuf, " type='%s'", fsdriver); + virBufferAsprintf(&driverAttrBuf, " type='%s'", fsdriver); if (def->format) - virBufferAsprintf(&driverBuf, " format='%s'", + virBufferAsprintf(&driverAttrBuf, " format='%s'", virStorageFileFormatTypeToString(def->format)); /* Don't generate anything if wrpolicy is set to default */ if (def->wrpolicy) - virBufferAsprintf(&driverBuf, " wrpolicy='%s'", wrpolicy); + virBufferAsprintf(&driverAttrBuf, " wrpolicy='%s'", wrpolicy); } - virDomainVirtioOptionsFormat(&driverBuf, def->virtio); + virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio); - if (virBufferUse(&driverBuf)) { - virBufferAddLit(buf, "<driver"); - virBufferAddBuffer(buf, &driverBuf); - virBufferAddLit(buf, "/>\n"); - } + virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); switch (def->type) { case VIR_DOMAIN_FS_TYPE_MOUNT: -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:02 +0100, Ján Tomko wrote:
Use the virXMLFormatElement helper to format the driver element to simplify adding further sub-elements.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/conf/domain_conf.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Introduced by QEMU commit 98fc1ada4cf70af0f1df1a2d7183cf786fc7da05 virtio: add vhost-user-fs base device Released in QEMU v4.2.0. Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml | 1 + 5 files changed, 6 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 17b0134ab8..425e7d2fb9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -557,6 +557,7 @@ VIR_ENUM_IMPL(virQEMUCaps, /* 350 */ "i8042", + "vhost-user-fs", ); @@ -1249,6 +1250,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "ramfb", QEMU_CAPS_DEVICE_RAMFB }, { "max-arm-cpu", QEMU_CAPS_ARM_MAX_CPU }, { "i8042", QEMU_CAPS_DEVICE_I8042 }, + { "vhost-user-fs-device", QEMU_CAPS_DEVICE_VHOST_USER_FS }, }; static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index ebfdb4b981..7963514a40 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -538,6 +538,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ /* 350 */ QEMU_CAPS_DEVICE_I8042, /* PS/2 controller */ + QEMU_CAPS_DEVICE_VHOST_USER_FS, /* -device vhost-user-fs */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml index 184bb7ff77..ef058266a4 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml @@ -176,6 +176,7 @@ <flag name='savevm-monitor-nodes'/> <flag name='drive-nvme'/> <flag name='smp-dies'/> + <flag name='vhost-user-fs'/> <version>4001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml b/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml index c8746f05ef..49963b7020 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml @@ -136,6 +136,7 @@ <flag name='blockdev-file-dynamic-auto-read-only'/> <flag name='drive-nvme'/> <flag name='smp-dies'/> + <flag name='vhost-user-fs'/> <version>4001050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>39100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml index c41df184be..f971021c8a 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml @@ -220,6 +220,7 @@ <flag name='drive-nvme'/> <flag name='smp-dies'/> <flag name='i8042'/> + <flag name='vhost-user-fs'/> <version>4002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:03 +0100, Ján Tomko wrote:
Introduced by QEMU commit 98fc1ada4cf70af0f1df1a2d7183cf786fc7da05 virtio: add vhost-user-fs base device
Released in QEMU v4.2.0.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_capabilities.c | 2 ++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml | 1 + 5 files changed, 6 insertions(+)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Allow adding new groups without changing indentation. Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/schemas/domaincommon.rng | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 76d94b156f..04854bf816 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2600,29 +2600,33 @@ for this kind of info, and 'type' for the storage format. We need the latter too, so had to invent a new attribute name --> - <optional> - <attribute name="type"> - <choice> - <value>path</value> - <value>handle</value> - <value>loop</value> - <value>nbd</value> - <value>ploop</value> - </choice> - </attribute> - </optional> - <optional> - <attribute name="format"> - <ref name="storageFormat"/> - </attribute> - </optional> - <optional> - <attribute name="wrpolicy"> - <value>immediate</value> - </attribute> - </optional> - <ref name='virtioOptions'/> - <empty/> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>path</value> + <value>handle</value> + <value>loop</value> + <value>nbd</value> + <value>ploop</value> + </choice> + </attribute> + </optional> + <optional> + <attribute name="format"> + <ref name="storageFormat"/> + </attribute> + </optional> + <optional> + <attribute name="wrpolicy"> + <value>immediate</value> + </attribute> + </optional> + <ref name='virtioOptions'/> + </group> + <empty/> + </choice> </element> </define> -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:04 +0100, Ján Tomko wrote:
Allow adding new groups without changing indentation.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/schemas/domaincommon.rng | 50 +++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 23 deletions(-)
Reviewed-by: Peter Krempa <pkrempa@redhat.com>

Introduce a new 'virtiofs' driver type for filesystem. <filesystem type='mount' accessmode='passthrough'> <driver type='virtiofs'/> <source dir='/path'/> <target dir='mount_tag'> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </filesystem> Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.html.in | 7 ++ docs/schemas/domaincommon.rng | 16 ++++ src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 4 + src/qemu/qemu_domain.c | 4 + src/qemu/qemu_domain_address.c | 4 + .../vhost-user-fs-fd-memory.xml | 38 ++++++++++ .../vhost-user-fs-hugepages.xml | 73 +++++++++++++++++++ .../vhost-user-fs-fd-memory.x86_64-latest.xml | 1 + .../vhost-user-fs-hugepages.x86_64-latest.xml | 1 + tests/qemuxml2xmltest.c | 3 + 12 files changed, 153 insertions(+) create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4db9c292b7..21f2a92ed6 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3921,6 +3921,11 @@ <target dir='/import/from/host'/> <readonly/> </filesystem> + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'/> + <source dir='/path'/> + <target dir='mount_tag'> + </filesystem> ... </devices> ...</pre> @@ -3949,6 +3954,8 @@ while the value <code>immediate</code> means that a host writeback is immediately triggered for all pages touched during a guest file write operation <span class="since">(since 0.9.10)</span>. + <span class="since">Since 6.1.0</span>, <code>type='virtiofs'</code> + is also supported. </dd> <dt><code>template</code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 04854bf816..66757d3b63 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2625,6 +2625,22 @@ </optional> <ref name='virtioOptions'/> </group> + <group> + <attribute name="type"> + <value>virtiofs</value> + </attribute> + <optional> + <attribute name="format"> + <ref name="storageFormat"/> + </attribute> + </optional> + <optional> + <attribute name="wrpolicy"> + <value>immediate</value> + </attribute> + </optional> + <ref name='virtioOptions'/> + </group> <empty/> </choice> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6deb8e5434..94e1fd64b5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -477,6 +477,7 @@ VIR_ENUM_IMPL(virDomainFSDriver, "loop", "nbd", "ploop", + "virtiofs", ); VIR_ENUM_IMPL(virDomainFSAccessMode, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 9ae8411f6c..6ee95ac653 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -771,6 +771,7 @@ typedef enum { VIR_DOMAIN_FS_DRIVER_TYPE_LOOP, VIR_DOMAIN_FS_DRIVER_TYPE_NBD, VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP, + VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS, VIR_DOMAIN_FS_DRIVER_TYPE_LAST } virDomainFSDriverType; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c66b60fd21..974c2b79af 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2687,6 +2687,10 @@ qemuBuildFilesystemCommandLine(virCommandPtr cmd, return -1; break; + case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* TODO: vhost-user-fs-pci */ + break; + case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP: case VIR_DOMAIN_FS_DRIVER_TYPE_NBD: case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 38addc7b61..eb8e82b545 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8275,6 +8275,10 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, _("Filesystem driver type not supported")); return -1; + case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* TODO: vhost-user-fs-pci */ + return 0; + case VIR_DOMAIN_FS_DRIVER_TYPE_LAST: default: virReportEnumRangeError(virDomainFSDriverType, fs->fsdriver); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 9e3bcc434d..3c6ac62ff5 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -690,6 +690,10 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, } break; + case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* vhost-user-fs-pci */ + return virtioFlags; + case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP: case VIR_DOMAIN_FS_DRIVER_TYPE_NBD: case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP: diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml new file mode 100644 index 0000000000..b02eb5cb2b --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml @@ -0,0 +1,38 @@ +<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> + <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' accessmode='passthrough'> + <driver type='virtiofs'/> + <source dir='/path'/> + <target dir='mount_tag'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </filesystem> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml new file mode 100644 index 0000000000..8a4b1c7c0b --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml @@ -0,0 +1,73 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <memoryBacking> + <hugepages> + <page size='2048' unit='KiB'/> + </hugepages> + <access mode='shared'/> + </memoryBacking> + <vcpu placement='static'>2</vcpu> + <os> + <type arch='x86_64' machine='q35'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + </features> + <cpu> + <numa> + <cell id='0' cpus='0-1' memory='2097152' 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> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/libvirt/images/guest.qcow2'/> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/> + </disk> + <controller type='usb' index='0' model='none'/> + <controller type='sata' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/> + </controller> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='1' port='0x8'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/> + </controller> + <controller type='pci' index='2' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='2' port='0x9'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='3' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='3' port='0xa'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='4' port='0xb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x3'/> + </controller> + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'/> + <source dir='/path'/> + <target dir='mount_tag'/> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </filesystem> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml b/tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml new file mode 120000 index 0000000000..fbc552ef94 --- /dev/null +++ b/tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/vhost-user-fs-fd-memory.xml \ No newline at end of file diff --git a/tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml b/tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml new file mode 120000 index 0000000000..0c0f05b254 --- /dev/null +++ b/tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/vhost-user-fs-hugepages.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 3cefc64833..bff71e2a9d 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1417,6 +1417,9 @@ mymain(void) DO_TEST("vhost-vsock-ccw-auto", QEMU_CAPS_DEVICE_VHOST_VSOCK, QEMU_CAPS_CCW); + DO_TEST_CAPS_LATEST("vhost-user-fs-fd-memory"); + DO_TEST_CAPS_LATEST("vhost-user-fs-hugepages"); + DO_TEST("riscv64-virt", QEMU_CAPS_DEVICE_VIRTIO_MMIO); DO_TEST("riscv64-virt-pci", -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:05 +0100, Ján Tomko wrote:
Introduce a new 'virtiofs' driver type for filesystem.
<filesystem type='mount' accessmode='passthrough'> <driver type='virtiofs'/> <source dir='/path'/> <target dir='mount_tag'> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </filesystem>
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.html.in | 7 ++ docs/schemas/domaincommon.rng | 16 ++++ src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/qemu/qemu_command.c | 4 + src/qemu/qemu_domain.c | 4 + src/qemu/qemu_domain_address.c | 4 + .../vhost-user-fs-fd-memory.xml | 38 ++++++++++ .../vhost-user-fs-hugepages.xml | 73 +++++++++++++++++++ .../vhost-user-fs-fd-memory.x86_64-latest.xml | 1 + .../vhost-user-fs-hugepages.x86_64-latest.xml | 1 + tests/qemuxml2xmltest.c | 3 + 12 files changed, 153 insertions(+) create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-fd-memory.x86_64-latest.xml create mode 120000 tests/qemuxml2xmloutdata/vhost-user-fs-hugepages.x86_64-latest.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 4db9c292b7..21f2a92ed6 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3921,6 +3921,11 @@ <target dir='/import/from/host'/> <readonly/> </filesystem> + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'/> + <source dir='/path'/> + <target dir='mount_tag'> + </filesystem> ... </devices> ...</pre> @@ -3949,6 +3954,8 @@ while the value <code>immediate</code> means that a host writeback is immediately triggered for all pages touched during a guest file write operation <span class="since">(since 0.9.10)</span>. + <span class="since">Since 6.1.0</span>, <code>type='virtiofs'</code> + is also supported.
I'd expect some more description on the topic of virtiofs. Not even the knowledge-base article is crosslinked from here. Specifically what does 'mount_tag' mean and perhaps how to use it in the guest. The validator then forces accessmode to passthrough and that is not mentioned here either.
</dd> <dt><code>template</code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 04854bf816..66757d3b63 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2625,6 +2625,22 @@ </optional> <ref name='virtioOptions'/> </group> + <group> + <attribute name="type"> + <value>virtiofs</value> + </attribute> + <optional> + <attribute name="format"> + <ref name="storageFormat"/> + </attribute>
The format attribute isn't documented and is rejected by the validator. Why bother adding it to the schema?
+ </optional> + <optional> + <attribute name="wrpolicy"> + <value>immediate</value> + </attribute>
This doesn't seem to be documented either.
+ </optional> + <ref name='virtioOptions'/> + </group> <empty/> </choice> </element>
[...]
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c66b60fd21..974c2b79af 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2687,6 +2687,10 @@ qemuBuildFilesystemCommandLine(virCommandPtr cmd, return -1; break;
+ case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* TODO: vhost-user-fs-pci */ + break;
IMO in these cases we should still fall through to error reporting rather than format nothing but you don't have to change it.
+ case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP: case VIR_DOMAIN_FS_DRIVER_TYPE_NBD: case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP: diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 38addc7b61..eb8e82b545 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8275,6 +8275,10 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, _("Filesystem driver type not supported")); return -1;
+ case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* TODO: vhost-user-fs-pci */ + return 0; + case VIR_DOMAIN_FS_DRIVER_TYPE_LAST: default: virReportEnumRangeError(virDomainFSDriverType, fs->fsdriver); diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 9e3bcc434d..3c6ac62ff5 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -690,6 +690,10 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, } break;
+ case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: + /* vhost-user-fs-pci */ + return virtioFlags; + case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP: case VIR_DOMAIN_FS_DRIVER_TYPE_NBD: case VIR_DOMAIN_FS_DRIVER_TYPE_PLOOP: diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml new file mode 100644 index 0000000000..b02eb5cb2b --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml @@ -0,0 +1,38 @@ +<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> + <numa> + <cell id='0' cpus='0-1' memory='14680064' unit='KiB' memAccess='shared'/> + </numa>
This is possibly worth mentioning too. Especially if you don't cross-link to the knowledge-base in patch 10. The rest looks good. I'm willing to review just the improved documentation if you reply with the changes.

On Fri, Jan 24, 2020 at 09:00:04AM +0100, Peter Krempa wrote:
@@ -3949,6 +3954,8 @@ while the value <code>immediate</code> means that a host writeback is immediately triggered for all pages touched during a guest file write operation <span class="since">(since 0.9.10)</span>. + <span class="since">Since 6.1.0</span>, <code>type='virtiofs'</code> + is also supported.
I'd expect some more description on the topic of virtiofs. Not even the knowledge-base article is crosslinked from here.
Specifically what does 'mount_tag' mean and perhaps how to use it in the guest.
The meaning of the target element does not differ from 9pfs which is already documented below: <dt><code>target</code></dt> <dd> Where the <code>source</code> can be accessed in the guest. For most drivers this is an automatic mount point, but for QEMU/KVM this is merely an arbitrary string tag that is exported to the guest as a hint for where to mount. </dd> But I will add the kbase link here, which shows the usage.
The validator then forces accessmode to passthrough and that is not mentioned here either.
</dd> <dt><code>template</code></dt> <dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 04854bf816..66757d3b63 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2625,6 +2625,22 @@ </optional> <ref name='virtioOptions'/> </group> + <group> + <attribute name="type"> + <value>virtiofs</value> + </attribute> + <optional> + <attribute name="format"> + <ref name="storageFormat"/> + </attribute>
The format attribute isn't documented and is rejected by the validator. Why bother adding it to the schema?
Leftovers from my fight with xmllint. O:-)
+ </optional> + <optional> + <attribute name="wrpolicy"> + <value>immediate</value> + </attribute>
This doesn't seem to be documented either.
+ </optional> + <ref name='virtioOptions'/> + </group> <empty/> </choice> </element>
[...]
diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml new file mode 100644 index 0000000000..b02eb5cb2b --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml @@ -0,0 +1,38 @@ +<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> + <numa> + <cell id='0' cpus='0-1' memory='14680064' unit='KiB' memAccess='shared'/> + </numa>
This is possibly worth mentioning too. Especially if you don't cross-link to the knowledge-base in patch 10.
The rest looks good. I'm willing to review just the improved documentation if you reply with the changes.
Given your exhaustive review of other patches, I'll send v3 separately. Jano

Add more elements for tuning the virtiofsd daemon and the vhost-user-fs device: <driver type='virtiofs' queue='1024' xattr='on'> <binary>/usr/libexec/virtiofsd</binary> <cache mode='always' size='2097152' unit='KiB'/> <lock posix='off' flock='off'/> </driver> Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.html.in | 18 ++- docs/schemas/domaincommon.rng | 51 ++++++ src/conf/domain_conf.c | 146 +++++++++++++++++- src/conf/domain_conf.h | 16 ++ src/libvirt_private.syms | 1 + .../vhost-user-fs-fd-memory.xml | 6 +- .../vhost-user-fs-hugepages.xml | 4 +- 7 files changed, 238 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 21f2a92ed6..cfdb1a7a9a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3922,10 +3922,15 @@ <readonly/> </filesystem> <filesystem type='mount' accessmode='passthrough'> - <driver type='virtiofs'/> + <driver type='virtiofs queue='1024' xattr='on''> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='2097152' unit='KiB'/> + <lock posix='off' flock='off'/> + </driver> <source dir='/path'/> <target dir='mount_tag'> </filesystem> + ... </devices> ...</pre> @@ -4046,6 +4051,17 @@ <a href="#elementsVirtio">Virtio-specific options</a> can also be set. (<span class="since">Since 3.5.0</span>) </li> + <li> + For <code>virtiofs</code>, the <code>queue</code> attribute can be used + to specify the queue size, <code>xattr</code> enables the use of filesystem + extended attributes. The <code>binary</code> sub-element contains the path + to the virtiofs daemon. + Caching can be tuned via the <code>cache</code> element, possible <code>mode</code> + values being <code>none</code> and <code>always</code>. + Locking can be controlled via the <code>lock</code> + element - attributes <code>posix</code> and <code>flock</code> both accepting + values <code>yes</code> or <code>no</code>. (<span class="since">Since 6.1.0</span>) + </li> </ul> </dd> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 66757d3b63..a67c56d1c7 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2629,6 +2629,57 @@ <attribute name="type"> <value>virtiofs</value> </attribute> + <optional> + <attribute name="queue"> + <ref name="unsignedInt"/> + </attribute> + </optional> + <optional> + <attribute name="xattr"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <element name="binary"> + <ref name="absFilePath"/> + </element> + </optional> + <optional> + <element name="cache"> + <optional> + <attribute name="size"> + <ref name="unsignedLong"/> + </attribute> + <optional> + <attribute name="unit"> + <ref name="unit"/> + </attribute> + </optional> + </optional> + <optional> + <attribute name="mode"> + <choice> + <value>none</value> + <value>always</value> + </choice> + </attribute> + </optional> + </element> + </optional> + <optional> + <element name="lock"> + <optional> + <attribute name="posix"> + <ref name="virOnOff"/> + </attribute> + </optional> + <optional> + <attribute name="flock"> + <ref name="virOnOff"/> + </attribute> + </optional> + </element> + </optional> <optional> <attribute name="format"> <ref name="storageFormat"/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 94e1fd64b5..e4f20bb0bf 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -501,6 +501,14 @@ VIR_ENUM_IMPL(virDomainFSModel, "virtio-non-transitional", ); +VIR_ENUM_IMPL(virDomainFSCacheMode, + VIR_DOMAIN_FS_CACHE_MODE_LAST, + "default", + "none", + "always", +); + + VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "user", @@ -2314,6 +2322,7 @@ void virDomainFSDefFree(virDomainFSDefPtr def) VIR_FREE(def->dst); virDomainDeviceInfoClear(&def->info); VIR_FREE(def->virtio); + VIR_FREE(def->binary); VIR_FREE(def); } @@ -11116,6 +11125,14 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, g_autofree char *usage = NULL; g_autofree char *units = NULL; g_autofree char *model = NULL; + g_autofree char *binary = NULL; + g_autofree char *queue_size = NULL; + g_autofree char *xattr = NULL; + g_autofree char *cache = NULL; + g_autofree char *cache_size = NULL; + g_autofree char *cache_unit = NULL; + g_autofree char *posix_lock = NULL; + g_autofree char *flock = NULL; ctxt->node = node; @@ -11193,12 +11210,39 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (virXMLNodeNameEqual(cur, "readonly")) { def->readonly = true; } else if (virXMLNodeNameEqual(cur, "driver")) { + xmlNodePtr child; + if (!fsdriver) fsdriver = virXMLPropString(cur, "type"); if (!wrpolicy) wrpolicy = virXMLPropString(cur, "wrpolicy"); if (!format) format = virXMLPropString(cur, "format"); + if (!queue_size) + queue_size = virXMLPropString(cur, "queue"); + if (!xattr) + xattr = virXMLPropString(cur, "xattr"); + + child = cur->children; + while (child != NULL) { + if (virXMLNodeNameEqual(child, "cache")) { + if (!cache) + cache = virXMLPropString(child, "mode"); + if (!cache_size) + cache_size = virXMLPropString(child, "size"); + if (!cache_unit) + cache_unit = virXMLPropString(child, "unit"); + } else if (virXMLNodeNameEqual(child, "lock")) { + if (!posix_lock) + posix_lock = virXMLPropString(child, "posix"); + if (!flock) + flock = virXMLPropString(child, "flock"); + } else if (virXMLNodeNameEqual(child, "binary")) { + if (!binary) + binary = virXMLNodeContentString(child); + } + child = child->next; + } if (virDomainVirtioOptionsParseXML(cur, &def->virtio) < 0) goto error; @@ -11208,11 +11252,72 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } if (fsdriver) { + int val; + if ((def->fsdriver = virDomainFSDriverTypeFromString(fsdriver)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown fs driver type '%s'"), fsdriver); goto error; } + + if (binary) + def->binary = virFileSanitizePath(binary); + + if (queue_size && virStrToLong_ull(queue_size, NULL, 10, &def->queue_size) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse queue size '%s' for virtiofs"), + cache_size); + goto error; + } + + if (xattr) { + if ((val = virTristateSwitchTypeFromString(xattr)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown xattr value '%s'"), xattr); + goto error; + } + def->xattr = val; + } + + if (cache) { + if ((val = virDomainFSCacheModeTypeFromString(cache)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse cache mode '%s' for virtiofs"), + cache); + goto error; + } + def->cache = val; + } + + if (cache_size && virStrToLong_ull(cache_size, NULL, 10, &def->cache_size) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse cache size '%s' for virtiofs"), + cache_size); + goto error; + } + + if (virScaleInteger(&def->cache_size, cache_unit, + 1024, ULLONG_MAX) < 0) + goto error; + def->cache_size = VIR_DIV_UP(def->cache_size, 1024); + + if (posix_lock) { + if ((val = virTristateSwitchTypeFromString(posix_lock)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown posix lock value '%s'"), posix_lock); + goto error; + } + def->posix_lock = val; + } + + if (flock) { + if ((val = virTristateSwitchTypeFromString(flock)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown flock value '%s'"), flock); + goto error; + } + def->flock = val; + } } if (format) { @@ -24998,6 +25103,7 @@ virDomainFSDefFormat(virBufferPtr buf, const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy); const char *src = def->src->path; g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) driverBuf = VIR_BUFFER_INIT_CHILD(buf); if (!type) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -25021,7 +25127,11 @@ virDomainFSDefFormat(virBufferPtr buf, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); + virBufferAdjustIndent(&driverBuf, 2); if (def->fsdriver) { + g_auto(virBuffer) lockAttrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) cacheAttrBuf = VIR_BUFFER_INITIALIZER; + virBufferAsprintf(&driverAttrBuf, " type='%s'", fsdriver); if (def->format) @@ -25032,11 +25142,45 @@ virDomainFSDefFormat(virBufferPtr buf, if (def->wrpolicy) virBufferAsprintf(&driverAttrBuf, " wrpolicy='%s'", wrpolicy); + if (def->queue_size) + virBufferAsprintf(&driverAttrBuf, " queue='%llu'", def->queue_size); + + if (def->xattr) { + virBufferAsprintf(&driverAttrBuf, " xattr='%s'", + virTristateSwitchTypeToString(def->xattr)); + } + + virBufferEscapeString(&driverBuf, "<binary>%s</binary>\n", def->binary); + + if (def->cache) { + virBufferAsprintf(&cacheAttrBuf, " mode='%s'", + virDomainFSCacheModeTypeToString(def->cache)); + } + + if (def->cache_size) { + virBufferAsprintf(&cacheAttrBuf, " size='%llu' unit='KiB'", + def->cache_size); + } + + virXMLFormatElement(&driverBuf, "cache", &cacheAttrBuf, NULL); + + if (def->posix_lock) { + virBufferAsprintf(&lockAttrBuf, " posix='%s'", + virTristateSwitchTypeToString(def->posix_lock)); + } + + if (def->flock) { + virBufferAsprintf(&lockAttrBuf, " flock='%s'", + virTristateSwitchTypeToString(def->flock)); + } + + virXMLFormatElement(&driverBuf, "lock", &lockAttrBuf, NULL); } + virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio); - virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverBuf); switch (def->type) { case VIR_DOMAIN_FS_TYPE_MOUNT: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ee95ac653..b90ccbdba8 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -802,6 +802,14 @@ typedef enum { VIR_DOMAIN_FS_MODEL_LAST } virDomainFSModel; +typedef enum { + VIR_DOMAIN_FS_CACHE_MODE_DEFAULT = 0, + VIR_DOMAIN_FS_CACHE_MODE_NONE, + VIR_DOMAIN_FS_CACHE_MODE_ALWAYS, + + VIR_DOMAIN_FS_CACHE_MODE_LAST +} virDomainFSCacheMode; + struct _virDomainFSDef { int type; int fsdriver; /* enum virDomainFSDriverType */ @@ -817,6 +825,13 @@ struct _virDomainFSDef { unsigned long long space_hard_limit; /* in bytes */ unsigned long long space_soft_limit; /* in bytes */ bool symlinksResolved; + char *binary; + unsigned long long queue_size; + virTristateSwitch xattr; + virDomainFSCacheMode cache; + unsigned long long cache_size; + virTristateSwitch posix_lock; + virTristateSwitch flock; virDomainVirtioOptionsPtr virtio; virObjectPtr privateData; }; @@ -3425,6 +3440,7 @@ VIR_ENUM_DECL(virDomainFSDriver); VIR_ENUM_DECL(virDomainFSAccessMode); VIR_ENUM_DECL(virDomainFSWrpolicy); VIR_ENUM_DECL(virDomainFSModel); +VIR_ENUM_DECL(virDomainFSCacheMode); VIR_ENUM_DECL(virDomainNet); VIR_ENUM_DECL(virDomainNetBackend); VIR_ENUM_DECL(virDomainNetVirtioTxMode); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 907640b684..75f145a9de 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -389,6 +389,7 @@ virDomainDiskSourceFormat; virDomainDiskTranslateSourcePool; virDomainFeatureTypeFromString; virDomainFeatureTypeToString; +virDomainFSCacheModeTypeToString; virDomainFSDefFree; virDomainFSDefNew; virDomainFSDriverTypeToString; diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml index b02eb5cb2b..3a578ae126 100644 --- a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml +++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.xml @@ -26,7 +26,11 @@ <controller type='usb' index='0' model='none'/> <controller type='pci' index='0' model='pci-root'/> <filesystem type='mount' accessmode='passthrough'> - <driver type='virtiofs'/> + <driver type='virtiofs' queue='1024' xattr='on'> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='2097152' unit='KiB'/> + <lock posix='off' flock='off'/> + </driver> <source dir='/path'/> <target dir='mount_tag'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> diff --git a/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml index 8a4b1c7c0b..fb9c4cc6c3 100644 --- a/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml +++ b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.xml @@ -61,7 +61,9 @@ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x3'/> </controller> <filesystem type='mount' accessmode='passthrough'> - <driver type='virtiofs'/> + <driver type='virtiofs'> + <binary>/usr/libexec/virtiofsd</binary> + </driver> <source dir='/path'/> <target dir='mount_tag'/> <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:06 +0100, Ján Tomko wrote:
Add more elements for tuning the virtiofsd daemon and the vhost-user-fs device:
<driver type='virtiofs' queue='1024' xattr='on'> <binary>/usr/libexec/virtiofsd</binary> <cache mode='always' size='2097152' unit='KiB'/> <lock posix='off' flock='off'/> </driver>
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.html.in | 18 ++- docs/schemas/domaincommon.rng | 51 ++++++ src/conf/domain_conf.c | 146 +++++++++++++++++- src/conf/domain_conf.h | 16 ++ src/libvirt_private.syms | 1 + .../vhost-user-fs-fd-memory.xml | 6 +- .../vhost-user-fs-hugepages.xml | 4 +- 7 files changed, 238 insertions(+), 4 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 21f2a92ed6..cfdb1a7a9a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3922,10 +3922,15 @@ <readonly/> </filesystem> <filesystem type='mount' accessmode='passthrough'> - <driver type='virtiofs'/> + <driver type='virtiofs queue='1024' xattr='on''> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='2097152' unit='KiB'/> + <lock posix='off' flock='off'/> + </driver> <source dir='/path'/> <target dir='mount_tag'> </filesystem> + ... </devices> ...</pre> @@ -4046,6 +4051,17 @@ <a href="#elementsVirtio">Virtio-specific options</a> can also be set. (<span class="since">Since 3.5.0</span>) </li> + <li> + For <code>virtiofs</code>, the <code>queue</code> attribute can be used + to specify the queue size,
The queue size is ambiguous. Is that in bytes?
+ <code>xattr</code> enables the use of filesystem + extended attributes. The <code>binary</code> sub-element contains the path + to the virtiofs daemon.
I heard that there are ideas to rewrite the virtiofs daemon after some time. Should we also expose a 'type' or model or something to prepare for the inevitable break of command line options between those two?
+ Caching can be tuned via the <code>cache</code> element, possible <code>mode</code> + values being <code>none</code> and <code>always</code>.
Size is not mentioned.
+ Locking can be controlled via the <code>lock</code> + element - attributes <code>posix</code> and <code>flock</code> both accepting + values <code>yes</code> or <code>no</code>. (<span class="since">Since 6.1.0</span>) + </li> </ul> </dd>
[...]
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 94e1fd64b5..e4f20bb0bf 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c
[...]
@@ -11193,12 +11210,39 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } else if (virXMLNodeNameEqual(cur, "readonly")) { def->readonly = true; } else if (virXMLNodeNameEqual(cur, "driver")) { + xmlNodePtr child; + if (!fsdriver) fsdriver = virXMLPropString(cur, "type"); if (!wrpolicy) wrpolicy = virXMLPropString(cur, "wrpolicy"); if (!format) format = virXMLPropString(cur, "format"); + if (!queue_size) + queue_size = virXMLPropString(cur, "queue"); + if (!xattr) + xattr = virXMLPropString(cur, "xattr"); + + child = cur->children; + while (child != NULL) { + if (virXMLNodeNameEqual(child, "cache")) { + if (!cache) + cache = virXMLPropString(child, "mode"); + if (!cache_size) + cache_size = virXMLPropString(child, "size"); + if (!cache_unit) + cache_unit = virXMLPropString(child, "unit"); + } else if (virXMLNodeNameEqual(child, "lock")) { + if (!posix_lock) + posix_lock = virXMLPropString(child, "posix"); + if (!flock) + flock = virXMLPropString(child, "flock"); + } else if (virXMLNodeNameEqual(child, "binary")) { + if (!binary) + binary = virXMLNodeContentString(child); + }
Please use XPath queries instead of this ancient method.
+ child = child->next; + }
if (virDomainVirtioOptionsParseXML(cur, &def->virtio) < 0) goto error; @@ -11208,11 +11252,72 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, }
if (fsdriver) { + int val; + if ((def->fsdriver = virDomainFSDriverTypeFromString(fsdriver)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown fs driver type '%s'"), fsdriver); goto error; } + + if (binary) + def->binary = virFileSanitizePath(binary); + + if (queue_size && virStrToLong_ull(queue_size, NULL, 10, &def->queue_size) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse queue size '%s' for virtiofs"), + cache_size); + goto error; + } + + if (xattr) { + if ((val = virTristateSwitchTypeFromString(xattr)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown xattr value '%s'"), xattr); + goto error; + } + def->xattr = val; + } + + if (cache) { + if ((val = virDomainFSCacheModeTypeFromString(cache)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse cache mode '%s' for virtiofs"), + cache); + goto error; + } + def->cache = val; + } + + if (cache_size && virStrToLong_ull(cache_size, NULL, 10, &def->cache_size) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("cannot parse cache size '%s' for virtiofs"), + cache_size); + goto error; + } + + if (virScaleInteger(&def->cache_size, cache_unit, + 1024, ULLONG_MAX) < 0) + goto error; + def->cache_size = VIR_DIV_UP(def->cache_size, 1024);
virDomainParseScaledValue
+ + if (posix_lock) { + if ((val = virTristateSwitchTypeFromString(posix_lock)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown posix lock value '%s'"), posix_lock); + goto error; + } + def->posix_lock = val; + } + + if (flock) { + if ((val = virTristateSwitchTypeFromString(flock)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown flock value '%s'"), flock); + goto error; + } + def->flock = val; + } }
if (format) { @@ -24998,6 +25103,7 @@ virDomainFSDefFormat(virBufferPtr buf, const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy); const char *src = def->src->path; g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) driverBuf = VIR_BUFFER_INIT_CHILD(buf);
if (!type) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -25021,7 +25127,11 @@ virDomainFSDefFormat(virBufferPtr buf, virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2); + virBufferAdjustIndent(&driverBuf, 2); if (def->fsdriver) { + g_auto(virBuffer) lockAttrBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) cacheAttrBuf = VIR_BUFFER_INITIALIZER; + virBufferAsprintf(&driverAttrBuf, " type='%s'", fsdriver);
if (def->format) @@ -25032,11 +25142,45 @@ virDomainFSDefFormat(virBufferPtr buf, if (def->wrpolicy) virBufferAsprintf(&driverAttrBuf, " wrpolicy='%s'", wrpolicy);
+ if (def->queue_size)
if (def->queue_size > 0)
+ virBufferAsprintf(&driverAttrBuf, " queue='%llu'", def->queue_size); + + if (def->xattr) {
if (def->xattr != VIR_TRISTATE_SWITCH_ABSENT) {
+ virBufferAsprintf(&driverAttrBuf, " xattr='%s'", + virTristateSwitchTypeToString(def->xattr)); + } + + virBufferEscapeString(&driverBuf, "<binary>%s</binary>\n", def->binary); + + if (def->cache) {
!= VIR_DOMAIN_FS_CACHE_MODE_DEFAULT
+ virBufferAsprintf(&cacheAttrBuf, " mode='%s'", + virDomainFSCacheModeTypeToString(def->cache)); + } + + if (def->cache_size) {
0
+ virBufferAsprintf(&cacheAttrBuf, " size='%llu' unit='KiB'", + def->cache_size); + } + + virXMLFormatElement(&driverBuf, "cache", &cacheAttrBuf, NULL); + + if (def->posix_lock) {
!= VIR_TRISTATE_SWITCH_ABSENT
+ virBufferAsprintf(&lockAttrBuf, " posix='%s'", + virTristateSwitchTypeToString(def->posix_lock)); + } + + if (def->flock) {
!= VIR_TRISTATE_SWITCH_ABSENT
+ virBufferAsprintf(&lockAttrBuf, " flock='%s'", + virTristateSwitchTypeToString(def->flock)); + } + + virXMLFormatElement(&driverBuf, "lock", &lockAttrBuf, NULL); }
+ virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);
- virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL); + virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverBuf);
switch (def->type) { case VIR_DOMAIN_FS_TYPE_MOUNT:

On Thu, Jan 23, 2020 at 18:46:06 +0100, Ján Tomko wrote:
Add more elements for tuning the virtiofsd daemon and the vhost-user-fs device:
<driver type='virtiofs' queue='1024' xattr='on'> <binary>/usr/libexec/virtiofsd</binary> <cache mode='always' size='2097152' unit='KiB'/> <lock posix='off' flock='off'/> </driver>
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- docs/formatdomain.html.in | 18 ++- docs/schemas/domaincommon.rng | 51 ++++++ src/conf/domain_conf.c | 146 +++++++++++++++++- src/conf/domain_conf.h | 16 ++ src/libvirt_private.syms | 1 + .../vhost-user-fs-fd-memory.xml | 6 +- .../vhost-user-fs-hugepages.xml | 4 +- 7 files changed, 238 insertions(+), 4 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 21f2a92ed6..cfdb1a7a9a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3922,10 +3922,15 @@ <readonly/> </filesystem> <filesystem type='mount' accessmode='passthrough'> - <driver type='virtiofs'/> + <driver type='virtiofs queue='1024' xattr='on''> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='2097152' unit='KiB'/> + <lock posix='off' flock='off'/>
So while looking at the rest of the series, I've noticed that the locking options are actually for the daemon and not for the device, while caching is passed to the device. This means that we mix semantically different options here and additionally with a possible rewrite of the daemon the daemon-based options may become obsolete. I'd suggest you add them into a container along with a tag of which version or name of virtiofsd is used.

Add a 'virtiofs_debug' option for tuning whether to run virtiofsd in debug mode. Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf | 7 +++++++ src/qemu/qemu_conf.c | 2 ++ src/qemu/qemu_conf.h | 1 + src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 12 insertions(+) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 557b6f38f8..32d79f20db 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -116,6 +116,7 @@ module Libvirtd_qemu = let nvram_entry = str_array_entry "nvram" let debug_level_entry = int_entry "gluster_debug_level" + | bool_entry "virtiofs_debug" let memory_entry = str_entry "memory_backing_dir" diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index b6805ffc41..84f01a126d 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -809,6 +809,13 @@ # #gluster_debug_level = 9 +# virtiofs debug +# +# Whether to pass the debug option to virtiofsd command line. +# Possible values are 0 or 1. +# +#virtiofs_debug = 1 + # To enhance security, QEMU driver is capable of creating private namespaces # for each domain started. Well, so far only "mount" namespace is supported. If # enabled it means qemu process is unable to see all the devices on the system, diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index b62dd1df52..3ff02988ad 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -801,6 +801,8 @@ virQEMUDriverConfigLoadDebugEntry(virQEMUDriverConfigPtr cfg, { if (virConfGetValueUInt(conf, "gluster_debug_level", &cfg->glusterDebugLevel) < 0) return -1; + if (virConfGetValueBool(conf, "virtiofs_debug", &cfg->virtiofsDebug) < 0) + return -1; return 0; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index b9401635d7..4162d06bf4 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -202,6 +202,7 @@ struct _virQEMUDriverConfig { virFirmwarePtr *firmwares; size_t nfirmwares; unsigned int glusterDebugLevel; + bool virtiofsDebug; char *memoryBackingDir; diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in index dd90edf687..7290a0004f 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -98,6 +98,7 @@ module Test_libvirtd_qemu = } { "stdio_handler" = "logd" } { "gluster_debug_level" = "9" } +{ "virtiofs_debug" = "1" } { "namespaces" { "1" = "mount" } } -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:07 +0100, Ján Tomko wrote:
Add a 'virtiofs_debug' option for tuning whether to run virtiofsd in debug mode.
IMO the option should be "virtiofsd_debug" so that it's really clear that it's meant for the daemon. In case of gluster which you put it close to the option is actually for the client.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf | 7 +++++++ src/qemu/qemu_conf.c | 2 ++ src/qemu/qemu_conf.h | 1 + src/qemu/test_libvirtd_qemu.aug.in | 1 + 5 files changed, 12 insertions(+)
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index 557b6f38f8..32d79f20db 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -116,6 +116,7 @@ module Libvirtd_qemu = let nvram_entry = str_array_entry "nvram"
let debug_level_entry = int_entry "gluster_debug_level" + | bool_entry "virtiofs_debug"
let memory_entry = str_entry "memory_backing_dir"
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index b6805ffc41..84f01a126d 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -809,6 +809,13 @@ # #gluster_debug_level = 9
+# virtiofs debug +# +# Whether to pass the debug option to virtiofsd command line.
I'd make it more obvious that this actually enables debugging of the daemon.
+# Possible values are 0 or 1. +# +#virtiofs_debug = 1 + # To enhance security, QEMU driver is capable of creating private namespaces # for each domain started. Well, so far only "mount" namespace is supported. If # enabled it means qemu process is unable to see all the devices on the system,

Reject unsupported configurations. Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_domain.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index eb8e82b545..4db0075b89 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8276,8 +8276,37 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, return -1; case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: - /* TODO: vhost-user-fs-pci */ - return 0; + if (!fs->binary) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("missing virtiofs binary")); + return -1; + } + 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) { + 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")); + return -1; + } + if (fs->format != VIR_STORAGE_FILE_NONE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtiofs does not support format")); + return -1; + } + if (def->mem.access != VIR_DOMAIN_MEMORY_ACCESS_SHARED) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtiofs requires shared memory")); + return -1; + } + break; case VIR_DOMAIN_FS_DRIVER_TYPE_LAST: default: -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:08 +0100, Ján Tomko wrote:
Reject unsupported configurations.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_domain.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index eb8e82b545..4db0075b89 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8276,8 +8276,37 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, return -1;
case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: - /* TODO: vhost-user-fs-pci */ - return 0; + if (!fs->binary) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("missing virtiofs binary"));
"missing virtiofs binary path" perhaps? Also the schema documents that the path is optional and the documentation never mentions that the path must be provided. I also didn't find any filling of a default, thus one of these is wrong.
+ return -1; + } + 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) { + 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")); + return -1; + } + if (fs->format != VIR_STORAGE_FILE_NONE) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtiofs does not support format")); + return -1; + }
The schema should also reject this.
+ if (def->mem.access != VIR_DOMAIN_MEMORY_ACCESS_SHARED) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtiofs requires shared memory")); + return -1; + } + break;
case VIR_DOMAIN_FS_DRIVER_TYPE_LAST: default:
Except for the issue with the path to the virtiofs binary this patch looks okay.

Start virtiofsd for each <filesystem> device using it. Pre-create the socket for communication with QEMU and pass it to virtiofsd. Note that virtiofsd needs to run as root. https://bugzilla.redhat.com/show_bug.cgi?id=1694166 Introduced by QEMU commit TBD, pull request here: https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg05389.html Signed-off-by: Ján Tomko <jtomko@redhat.com> --- po/POTFILES.in | 1 + src/qemu/Makefile.inc.am | 2 + src/qemu/qemu_domain.c | 3 + src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_extdevice.c | 19 +++ src/qemu/qemu_virtiofs.c | 241 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_virtiofs.h | 37 ++++++ tests/qemuxml2argvtest.c | 6 + 8 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 src/qemu/qemu_virtiofs.c create mode 100644 src/qemu/qemu_virtiofs.h diff --git a/po/POTFILES.in b/po/POTFILES.in index e266871907..4ea646e127 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -169,6 +169,7 @@ @SRCDIR@/src/qemu/qemu_tpm.c @SRCDIR@/src/qemu/qemu_vhost_user.c @SRCDIR@/src/qemu/qemu_vhost_user_gpu.c +@SRCDIR@/src/qemu/qemu_virtiofs.c @SRCDIR@/src/remote/remote_daemon.c @SRCDIR@/src/remote/remote_daemon_config.c @SRCDIR@/src/remote/remote_daemon_dispatch.c diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am index 967f6e75a2..77786526ea 100644 --- a/src/qemu/Makefile.inc.am +++ b/src/qemu/Makefile.inc.am @@ -67,6 +67,8 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_vhost_user.h \ qemu/qemu_vhost_user_gpu.c \ qemu/qemu_vhost_user_gpu.h \ + qemu/qemu_virtiofs.c \ + qemu/qemu_virtiofs.h \ qemu/qemu_checkpoint.c \ qemu/qemu_checkpoint.h \ qemu/qemu_backup.c \ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4db0075b89..19b3eb0fab 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1442,6 +1442,9 @@ qemuDomainFSPrivateNew(void) static void qemuDomainFSPrivateDispose(void *obj G_GNUC_UNUSED) { + qemuDomainFSPrivatePtr priv = obj; + + g_free(priv->vhostuser_fs_sock); } static virClassPtr qemuDomainVideoPrivateClass; diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 21ece23177..ea50c687d4 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -568,7 +568,7 @@ typedef qemuDomainFSPrivate *qemuDomainFSPrivatePtr; struct _qemuDomainFSPrivate { virObject parent; - int dummy; + char *vhostuser_fs_sock; }; diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 463f76c21a..1f4b605eb3 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -20,11 +20,13 @@ #include <config.h> +#include "qemu_command.h" #include "qemu_extdevice.h" #include "qemu_vhost_user_gpu.h" #include "qemu_domain.h" #include "qemu_tpm.h" #include "qemu_slirp.h" +#include "qemu_virtiofs.h" #include "viralloc.h" #include "virlog.h" @@ -184,6 +186,16 @@ qemuExtDevicesStart(virQEMUDriverPtr driver, return -1; } + for (i = 0; i < def->nfss; i++) { + virDomainFSDefPtr fs = def->fss[i]; + + if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) { + if (qemuVirtioFSStart(driver, vm, fs) < 0) + return -1; + } + } + + return ret; } @@ -215,6 +227,13 @@ qemuExtDevicesStop(virQEMUDriverPtr driver, if (slirp) qemuSlirpStop(slirp, vm, driver, net, false); } + + for (i = 0; i < def->nfss; i++) { + virDomainFSDefPtr fs = def->fss[i]; + + if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) + qemuVirtioFSStop(driver, vm, fs); + } } diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c new file mode 100644 index 0000000000..1a3bfd53f5 --- /dev/null +++ b/src/qemu/qemu_virtiofs.c @@ -0,0 +1,241 @@ +/* + * qemu_virtiofs.c: virtiofs support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "qemu_command.h" +#include "qemu_conf.h" +#include "qemu_extdevice.h" +#include "qemu_security.h" +#include "qemu_virtiofs.h" +#include "virpidfile.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + + +char * +qemuVirtioFSCreatePidFilename(virQEMUDriverConfigPtr cfg, + const virDomainDef *def, + const char *alias) +{ + g_autofree char *shortName = NULL; + g_autofree char *name = NULL; + + if (!(shortName = virDomainDefGetShortName(def))) + return NULL; + + name = g_strdup_printf("%s-%s-virtiofsd", shortName, alias); + + return virPidFileBuildPath(cfg->stateDir, name); +} + + +char * +qemuVirtioFSCreateSocketFilename(virDomainObjPtr vm, + const char *alias) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + + return virFileBuildPath(priv->libDir, alias, "-virtiofsd.sock"); +} + + +static int +qemuVirtioFSOpenChardev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + const char *socket_path) +{ + virDomainChrSourceDefPtr chrdev = virDomainChrSourceDefNew(NULL); + virDomainChrDef chr = { .source = chrdev }; + VIR_AUTOCLOSE fd = -1; + int ret = -1; + + chrdev->type = VIR_DOMAIN_CHR_TYPE_UNIX; + chrdev->data.nix.listen = true; + chrdev->data.nix.path = g_strdup(socket_path); + + if (qemuSecuritySetDaemonSocketLabel(driver->securityManager, vm->def) < 0) + goto cleanup; + fd = qemuOpenChrChardevUNIXSocket(chrdev); + if (fd < 0) { + ignore_value(qemuSecurityClearSocketLabel(driver->securityManager, vm->def)); + goto cleanup; + } + if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0) + goto cleanup; + + if (qemuSecuritySetChardevLabel(driver, vm, &chr) < 0) + goto cleanup; + + ret = fd; + fd = -1; + + cleanup: + virObjectUnref(chrdev); + return ret; +} + +static virCommandPtr +qemuVirtioFSBuildCommandLine(virQEMUDriverConfigPtr cfg, + virDomainFSDefPtr fs, + int *fd) +{ + g_autoptr(virCommand) cmd = NULL; + g_auto(virBuffer) opts = VIR_BUFFER_INITIALIZER; + + if (!(cmd = virCommandNew(fs->binary))) + return NULL; + + virCommandAddArg(cmd, "--syslog"); + virCommandAddArgFormat(cmd, "--fd=%d", *fd); + virCommandPassFD(cmd, *fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT); + *fd = -1; + + virCommandAddArg(cmd, "-o"); + virBufferAsprintf(&opts, "source=%s,", fs->src->path); + if (fs->cache) + virBufferAsprintf(&opts, "cache=%s,", virDomainFSCacheModeTypeToString(fs->cache)); + if (fs->xattr) + virBufferAsprintf(&opts, "%sxattr,", fs->xattr == VIR_TRISTATE_SWITCH_OFF ? "no_" : ""); + if (fs->flock) + virBufferAsprintf(&opts, "%sflock,", fs->flock == VIR_TRISTATE_SWITCH_OFF ? "no_" : ""); + if (fs->posix_lock) + virBufferAsprintf(&opts, "%sposix_lock,", fs->posix_lock == VIR_TRISTATE_SWITCH_OFF ? "no_" : ""); + virBufferTrim(&opts, ",", -1); + + virCommandAddArgBuffer(cmd, &opts); + if (cfg->virtiofsDebug) + virCommandAddArg(cmd, "-d"); + + return g_steal_pointer(&cmd); +} + +int +qemuVirtioFSStart(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autoptr(virCommand) cmd = NULL; + g_autofree char *socket_path = NULL; + g_autofree char *pidfile = NULL; + char errbuf[1024] = { 0 }; + pid_t pid = (pid_t) -1; + VIR_AUTOCLOSE errfd = -1; + VIR_AUTOCLOSE fd = -1; + int exitstatus = 0; + int cmdret = 0; + int ret = -1; + int rc; + + if (!(pidfile = qemuVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias))) + goto cleanup; + + if (!(socket_path = qemuVirtioFSCreateSocketFilename(vm, fs->info.alias))) + goto cleanup; + + if ((fd = qemuVirtioFSOpenChardev(driver, vm, socket_path)) < 0) + goto cleanup; + + if (!(cmd = qemuVirtioFSBuildCommandLine(cfg, fs, &fd))) + goto cleanup; + + virCommandSetPidFile(cmd, pidfile); + virCommandSetErrorFD(cmd, &errfd); + virCommandDaemonize(cmd); + + if (qemuExtDeviceLogCommand(driver, vm, cmd, "virtiofsd") < 0) + goto cleanup; + + cmdret = virCommandRun(cmd, &exitstatus); + + if (cmdret < 0 || exitstatus != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not start 'virtiofsd'. exitstatus: %d"), exitstatus); + goto error; + } + + rc = virPidFileReadPath(pidfile, &pid); + if (rc < 0) { + virReportSystemError(-rc, + _("Unable to read virtiofsd pidfile '%s'"), + pidfile); + goto error; + } + + if (virProcessKill(pid, 0) != 0) { + if (saferead(errfd, errbuf, sizeof(errbuf) - 1) < 0) { + virReportSystemError(errno, "%s", + _("virtiofsd died unexpectedly")); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("virtiofsd died and reported: %s"), errbuf); + } + goto error; + } + + QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = g_steal_pointer(&socket_path); + ret = 0; + + cleanup: + if (socket_path) + unlink(socket_path); + return ret; + + error: + if (pid != -1) + virProcessKillPainfully(pid, true); + if (pidfile) + unlink(pidfile); + goto cleanup; +} + + +void +qemuVirtioFSStop(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autofree char *pidfile = NULL; + virErrorPtr orig_err; + pid_t pid = -1; + int rc; + + virErrorPreserveLast(&orig_err); + + if (!(pidfile = qemuVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias))) + goto cleanup; + + rc = virPidFileReadPathIfAlive(pidfile, &pid, NULL); + if (rc >= 0 && pid != (pid_t) -1) + virProcessKillPainfully(pid, true); + + if (unlink(pidfile) < 0 && + errno != ENOENT) { + virReportSystemError(errno, + _("Unable to remove stale pidfile %s"), + pidfile); + } + + if (QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock) + unlink(QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock); + + cleanup: + virErrorRestore(&orig_err); +} diff --git a/src/qemu/qemu_virtiofs.h b/src/qemu/qemu_virtiofs.h new file mode 100644 index 0000000000..ffaeee0275 --- /dev/null +++ b/src/qemu/qemu_virtiofs.h @@ -0,0 +1,37 @@ +/* + * qemu_virtiofs.h: virtiofs support + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + + +char * +qemuVirtioFSCreatePidFilename(virQEMUDriverConfigPtr cfg, + const virDomainDef *def, + const char *alias); +char * +qemuVirtioFSCreateSocketFilename(virDomainObjPtr vm, + const char *alias); + +int +qemuVirtioFSStart(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs); +void +qemuVirtioFSStop(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs); diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b923590930..5a517a4982 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -496,6 +496,12 @@ testCompareXMLToArgv(const void *data) } } + for (i = 0; i < vm->def->nfss; i++) { + virDomainFSDefPtr fs = vm->def->fss[i]; + char *s = g_strdup_printf("/tmp/lib/domain--1-guest/fs%zu.vhost-fs.sock", i); + QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = s; + } + if (vm->def->vsock) { virDomainVsockDefPtr vsock = vm->def->vsock; qemuDomainVsockPrivatePtr vsockPriv = -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:09 +0100, Ján Tomko wrote:
Start virtiofsd for each <filesystem> device using it.
Pre-create the socket for communication with QEMU and pass it to virtiofsd.
Note that virtiofsd needs to run as root.
https://bugzilla.redhat.com/show_bug.cgi?id=1694166
Introduced by QEMU commit TBD, pull request here: https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg05389.html
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- po/POTFILES.in | 1 + src/qemu/Makefile.inc.am | 2 + src/qemu/qemu_domain.c | 3 + src/qemu/qemu_domain.h | 2 +- src/qemu/qemu_extdevice.c | 19 +++ src/qemu/qemu_virtiofs.c | 241 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_virtiofs.h | 37 ++++++ tests/qemuxml2argvtest.c | 6 + 8 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 src/qemu/qemu_virtiofs.c create mode 100644 src/qemu/qemu_virtiofs.h
[...]
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 4db0075b89..19b3eb0fab 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -1442,6 +1442,9 @@ qemuDomainFSPrivateNew(void) static void qemuDomainFSPrivateDispose(void *obj G_GNUC_UNUSED)
'obj' is no longer unused.
{ + qemuDomainFSPrivatePtr priv = obj; + + g_free(priv->vhostuser_fs_sock); }
[...]
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index 463f76c21a..1f4b605eb3 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c
[...]
@@ -184,6 +186,16 @@ qemuExtDevicesStart(virQEMUDriverPtr driver, return -1; }
Not required but I'd be grateful if you get rid of the pointless 'ret' variable in this function. Context in this patch made me question how that actually works.
+ for (i = 0; i < def->nfss; i++) { + virDomainFSDefPtr fs = def->fss[i]; + + if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) { + if (qemuVirtioFSStart(driver, vm, fs) < 0) + return -1; + } + } + + return ret; }
@@ -215,6 +227,13 @@ qemuExtDevicesStop(virQEMUDriverPtr driver, if (slirp) qemuSlirpStop(slirp, vm, driver, net, false); } + + for (i = 0; i < def->nfss; i++) { + virDomainFSDefPtr fs = def->fss[i]; + + if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) + qemuVirtioFSStop(driver, vm, fs);
Okay, hot(un)plug of VIR_DOMAIN_DEVICE_FS devices is not supported.
+ } }
diff --git a/src/qemu/qemu_virtiofs.c b/src/qemu/qemu_virtiofs.c new file mode 100644 index 0000000000..1a3bfd53f5 --- /dev/null +++ b/src/qemu/qemu_virtiofs.c @@ -0,0 +1,241 @@
[...]
+static virCommandPtr +qemuVirtioFSBuildCommandLine(virQEMUDriverConfigPtr cfg, + virDomainFSDefPtr fs, + int *fd) +{ + g_autoptr(virCommand) cmd = NULL; + g_auto(virBuffer) opts = VIR_BUFFER_INITIALIZER; + + if (!(cmd = virCommandNew(fs->binary))) + return NULL; + + virCommandAddArg(cmd, "--syslog");
I'm not entirely sure how the virtiofsd logs, but logging into the syslog seems to be suboptimal. I think we should log into a fd/file same way as qemu does. Specifically I'm worried about the possibility to identify/match the daemon to the corresponding VM. The binary itself does not have any identifying data of the VM name and such so it might be actually hard to match up which daemon caused which log entry. Specifically since pid numbers are considered internal implementation in libvirt.
+ virCommandAddArgFormat(cmd, "--fd=%d", *fd); + virCommandPassFD(cmd, *fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT); + *fd = -1; + + virCommandAddArg(cmd, "-o"); + virBufferAsprintf(&opts, "source=%s,", fs->src->path); + if (fs->cache) + virBufferAsprintf(&opts, "cache=%s,", virDomainFSCacheModeTypeToString(fs->cache)); + if (fs->xattr) + virBufferAsprintf(&opts, "%sxattr,", fs->xattr == VIR_TRISTATE_SWITCH_OFF ? "no_" : ""); + if (fs->flock) + virBufferAsprintf(&opts, "%sflock,", fs->flock == VIR_TRISTATE_SWITCH_OFF ? "no_" : ""); + if (fs->posix_lock) + virBufferAsprintf(&opts, "%sposix_lock,", fs->posix_lock == VIR_TRISTATE_SWITCH_OFF ? "no_" : "");
No ternaries please. Also properly expand the conditions as I've commented in the XML patch.
+ virBufferTrim(&opts, ",", -1); + + virCommandAddArgBuffer(cmd, &opts); + if (cfg->virtiofsDebug) + virCommandAddArg(cmd, "-d"); + + return g_steal_pointer(&cmd); +} + +int +qemuVirtioFSStart(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autoptr(virCommand) cmd = NULL; + g_autofree char *socket_path = NULL; + g_autofree char *pidfile = NULL; + char errbuf[1024] = { 0 }; + pid_t pid = (pid_t) -1; + VIR_AUTOCLOSE errfd = -1; + VIR_AUTOCLOSE fd = -1; + int exitstatus = 0; + int cmdret = 0; + int ret = -1; + int rc; + + if (!(pidfile = qemuVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias))) + goto cleanup; + + if (!(socket_path = qemuVirtioFSCreateSocketFilename(vm, fs->info.alias))) + goto cleanup; + + if ((fd = qemuVirtioFSOpenChardev(driver, vm, socket_path)) < 0) + goto cleanup; + + if (!(cmd = qemuVirtioFSBuildCommandLine(cfg, fs, &fd))) + goto cleanup; + + virCommandSetPidFile(cmd, pidfile); + virCommandSetErrorFD(cmd, &errfd);
Is it possible to use virCommandSetErrorBuffer instead? That would solve all of the reading and pipes.
+ virCommandDaemonize(cmd); + + if (qemuExtDeviceLogCommand(driver, vm, cmd, "virtiofsd") < 0) + goto cleanup; + + cmdret = virCommandRun(cmd, &exitstatus); + + if (cmdret < 0 || exitstatus != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not start 'virtiofsd'. exitstatus: %d"), exitstatus);
nit: exitstatus might not been updated thus reporting 0 might be confusing.
+ goto error; + } + + rc = virPidFileReadPath(pidfile, &pid); + if (rc < 0) { + virReportSystemError(-rc, + _("Unable to read virtiofsd pidfile '%s'"), + pidfile); + goto error; + } + + if (virProcessKill(pid, 0) != 0) {
Please heap-allocate 'errbuf' here.
+ if (saferead(errfd, errbuf, sizeof(errbuf) - 1) < 0) { + virReportSystemError(errno, "%s", + _("virtiofsd died unexpectedly")); + } else { + virReportError(VIR_ERR_OPERATION_FAILED, + _("virtiofsd died and reported: %s"), errbuf); + } + goto error; + } + + QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = g_steal_pointer(&socket_path); + ret = 0; + + cleanup: + if (socket_path) + unlink(socket_path); + return ret; + + error: + if (pid != -1) + virProcessKillPainfully(pid, true); + if (pidfile) + unlink(pidfile); + goto cleanup; +} + + +void +qemuVirtioFSStop(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainFSDefPtr fs) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + g_autofree char *pidfile = NULL; + virErrorPtr orig_err; + pid_t pid = -1; + int rc; + + virErrorPreserveLast(&orig_err); + + if (!(pidfile = qemuVirtioFSCreatePidFilename(cfg, vm->def, fs->info.alias))) + goto cleanup; + + rc = virPidFileReadPathIfAlive(pidfile, &pid, NULL); + if (rc >= 0 && pid != (pid_t) -1) + virProcessKillPainfully(pid, true);
Is there any caching on the daemon side which could be thrown away on an unclean shutdown?
+ + if (unlink(pidfile) < 0 && + errno != ENOENT) { + virReportSystemError(errno, + _("Unable to remove stale pidfile %s"), + pidfile); + } + + if (QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock) + unlink(QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock); + + cleanup: + virErrorRestore(&orig_err); +}
[...]
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b923590930..5a517a4982 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -496,6 +496,12 @@ testCompareXMLToArgv(const void *data) } }
+ for (i = 0; i < vm->def->nfss; i++) { + virDomainFSDefPtr fs = vm->def->fss[i];
I don't think you should do this for non-virtiofs cases.
+ char *s = g_strdup_printf("/tmp/lib/domain--1-guest/fs%zu.vhost-fs.sock", i); + QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = s; + } + if (vm->def->vsock) { virDomainVsockDefPtr vsock = vm->def->vsock; qemuDomainVsockPrivatePtr vsockPriv = -- 2.21.0

Format the 'vhost-user-fs' device on the QEMU command line. https://bugzilla.redhat.com/show_bug.cgi?id=1694166 Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_command.c | 47 ++++++++++++++++++- ...vhost-user-fs-fd-memory.x86_64-latest.args | 38 +++++++++++++++ ...vhost-user-fs-hugepages.x86_64-latest.args | 46 ++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 974c2b79af..31573860dd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2581,6 +2581,47 @@ qemuBuildDisksCommandLine(virCommandPtr cmd, } +static int +qemuBuildVHostUserFsCommandLine(virCommandPtr cmd, + virDomainFSDef *fs, + const virDomainDef *def G_GNUC_UNUSED, + qemuDomainObjPrivatePtr priv) +{ + g_autofree char *chardev_alias = NULL; + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + const char *tag = fs->dst; + + chardev_alias = g_strdup_printf("chr-vu-%s", fs->info.alias); + + virCommandAddArg(cmd, "-chardev"); + virBufferAddLit(&opt, "socket"); + virBufferAsprintf(&opt, ",id=%s", chardev_alias); + virBufferEscapeString(&opt, ",path=%s", QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock); + virCommandAddArg(cmd, virBufferContentAndReset(&opt)); + + virCommandAddArg(cmd, "-device"); + + if (qemuBuildVirtioDevStr(&opt, "vhost-user-fs", priv->qemuCaps, + VIR_DOMAIN_DEVICE_FS, fs) < 0) + return -1; + + virBufferAsprintf(&opt, ",chardev=%s", chardev_alias); + if (fs->queue_size) + virBufferAsprintf(&opt, ",queue-size=%llu", fs->queue_size); + virBufferEscapeString(&opt, ",tag=%s", tag); + if (fs->cache_size) + virBufferAsprintf(&opt, ",cache-size=%lluK", fs->cache_size); + if (qemuBuildVirtioOptionsStr(&opt, fs->virtio, priv->qemuCaps) < 0) + return -1; + + if (qemuBuildDeviceAddressStr(&opt, def, &fs->info, priv->qemuCaps) < 0) + return -1; + + virCommandAddArg(cmd, virBufferContentAndReset(&opt)); + return 0; +} + + static char * qemuBuildFSStr(virDomainFSDefPtr fs) { @@ -2673,7 +2714,7 @@ static int qemuBuildFilesystemCommandLine(virCommandPtr cmd, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - qemuDomainObjPrivatePtr priv G_GNUC_UNUSED) + qemuDomainObjPrivatePtr priv) { size_t i; @@ -2688,7 +2729,9 @@ qemuBuildFilesystemCommandLine(virCommandPtr cmd, break; case VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS: - /* TODO: vhost-user-fs-pci */ + /* vhost-user-fs-pci */ + if (qemuBuildVHostUserFsCommandLine(cmd, def->fss[i], def, priv) < 0) + return -1; break; case VIR_DOMAIN_FS_DRIVER_TYPE_LOOP: diff --git a/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args new file mode 100644 index 0000000000..5b992b8c62 --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args @@ -0,0 +1,38 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-guest/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-guest/master-key.aes \ +-machine pc,accel=kvm,usb=off,dump-guest-core=off \ +-m 14336 \ +-overcommit mem-lock=off \ +-smp 2,sockets=2,cores=1,threads=1 \ +-object memory-backend-file,id=ram-node0,\ +mem-path=/var/lib/libvirt/qemu/ram/libvirt/qemu/-1-guest/ram-node0,share=yes,\ +size=15032385536 \ +-numa node,nodeid=0,cpus=0-1,memdev=ram-node0 \ +-uuid 126f2720-6f8e-45ab-a886-ec9277079a67 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-chardev socket,id=chr-vu-fs0,path=/tmp/lib/domain--1-guest/fs0.vhost-fs.sock \ +-device vhost-user-fs-pci,chardev=chr-vu-fs0,queue-size=1024,tag=mount_tag,\ +cache-size=2097152K,bus=pci.0,addr=0x2 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args new file mode 100644 index 0000000000..3137d97e1f --- /dev/null +++ b/tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args @@ -0,0 +1,46 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-guest/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-guest/master-key.aes \ +-machine q35,accel=tcg,usb=off,dump-guest-core=off \ +-m 2048 \ +-overcommit mem-lock=off \ +-smp 2,sockets=2,cores=1,threads=1 \ +-object memory-backend-file,id=ram-node0,prealloc=yes,\ +mem-path=/dev/hugepages2M/libvirt/qemu/-1-guest,share=yes,size=2147483648 \ +-numa node,nodeid=0,cpus=0-1,memdev=ram-node0 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\ +addr=0x1 \ +-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \ +-device pcie-root-port,port=0xa,chassis=3,id=pci.3,bus=pcie.0,addr=0x1.0x2 \ +-device pcie-root-port,port=0xb,chassis=4,id=pci.4,bus=pcie.0,addr=0x1.0x3 \ +-blockdev '{"driver":"file","filename":"/var/lib/libvirt/images/guest.qcow2",\ +"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2",\ +"file":"libvirt-1-storage"}' \ +-device virtio-blk-pci,scsi=off,bus=pci.4,addr=0x0,drive=libvirt-1-format,\ +id=virtio-disk0,bootindex=1 \ +-chardev socket,id=chr-vu-fs0,path=/tmp/lib/domain--1-guest/fs0.vhost-fs.sock \ +-device vhost-user-fs-pci,chardev=chr-vu-fs0,tag=mount_tag,bus=pci.1,addr=0x0 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 5a517a4982..0b9acb2891 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3040,6 +3040,9 @@ mymain(void) DO_TEST_CAPS_VER("launch-security-sev", "2.12.0"); + DO_TEST_CAPS_LATEST("vhost-user-fs-fd-memory"); + DO_TEST_CAPS_LATEST("vhost-user-fs-hugepages"); + DO_TEST("riscv64-virt", QEMU_CAPS_DEVICE_VIRTIO_MMIO); DO_TEST("riscv64-virt-pci", -- 2.21.0

On Thu, Jan 23, 2020 at 18:46:10 +0100, Ján Tomko wrote:
Format the 'vhost-user-fs' device on the QEMU command line.
Rather than posting this bugzilla link to a not very descriptive bug it would be worthwhile to describe what the device actually does and how it integrates with the daemon.
Signed-off-by: Ján Tomko <jtomko@redhat.com> --- src/qemu/qemu_command.c | 47 ++++++++++++++++++- ...vhost-user-fs-fd-memory.x86_64-latest.args | 38 +++++++++++++++ ...vhost-user-fs-hugepages.x86_64-latest.args | 46 ++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-fd-memory.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/vhost-user-fs-hugepages.x86_64-latest.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 974c2b79af..31573860dd 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2581,6 +2581,47 @@ qemuBuildDisksCommandLine(virCommandPtr cmd, }
+static int +qemuBuildVHostUserFsCommandLine(virCommandPtr cmd, + virDomainFSDef *fs, + const virDomainDef *def G_GNUC_UNUSED, + qemuDomainObjPrivatePtr priv) +{ + g_autofree char *chardev_alias = NULL; + g_auto(virBuffer) opt = VIR_BUFFER_INITIALIZER; + const char *tag = fs->dst; + + chardev_alias = g_strdup_printf("chr-vu-%s", fs->info.alias);
I don't like to see another alias generated in the command line generator and then thrown away. Unfortunately it's still a common practice.
+ + virCommandAddArg(cmd, "-chardev"); + virBufferAddLit(&opt, "socket"); + virBufferAsprintf(&opt, ",id=%s", chardev_alias); + virBufferEscapeString(&opt, ",path=%s", QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock); + virCommandAddArg(cmd, virBufferContentAndReset(&opt)); + + virCommandAddArg(cmd, "-device"); + + if (qemuBuildVirtioDevStr(&opt, "vhost-user-fs", priv->qemuCaps, + VIR_DOMAIN_DEVICE_FS, fs) < 0) + return -1; + + virBufferAsprintf(&opt, ",chardev=%s", chardev_alias); + if (fs->queue_size) + virBufferAsprintf(&opt, ",queue-size=%llu", fs->queue_size); + virBufferEscapeString(&opt, ",tag=%s", tag);
fs->dst is user-provided and not validated. It must be escaped on the command line.
+ if (fs->cache_size) + virBufferAsprintf(&opt, ",cache-size=%lluK", fs->cache_size);
Hmm, so only cache size and queue is relevant for the device itself. I think the options in the XML should reflect that. I'll mention this in the XML schema patch.
+ if (qemuBuildVirtioOptionsStr(&opt, fs->virtio, priv->qemuCaps) < 0) + return -1; + + if (qemuBuildDeviceAddressStr(&opt, def, &fs->info, priv->qemuCaps) < 0) + return -1; + + virCommandAddArg(cmd, virBufferContentAndReset(&opt)); + return 0; +} + + static char * qemuBuildFSStr(virDomainFSDefPtr fs) { @@ -2673,7 +2714,7 @@ static int qemuBuildFilesystemCommandLine(virCommandPtr cmd, const virDomainDef *def, virQEMUCapsPtr qemuCaps, - qemuDomainObjPrivatePtr priv G_GNUC_UNUSED) + qemuDomainObjPrivatePtr priv) { size_t i;

Add a document describing the usage of virtiofs. --- docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/kbase/virtiofs.rst diff --git a/docs/kbase.html.in b/docs/kbase.html.in index c156414c41..7d6caf3cb1 100644 --- a/docs/kbase.html.in +++ b/docs/kbase.html.in @@ -29,6 +29,9 @@ <dt><a href="kbase/backing_chains.html">Backing chain management</a></dt> <dd>Explanation of how disk backing chain specification impacts libvirt's behaviour and basic troubleshooting steps of disk problems.</dd> + + <dt><a href="kbase/virtiofs.html">Virtio-FS</a></dt> + <dd>Share a filesystem between the guest and the host</dd> </dl> </div> diff --git a/docs/kbase/virtiofs.rst b/docs/kbase/virtiofs.rst new file mode 100644 index 0000000000..83351e0a28 --- /dev/null +++ b/docs/kbase/virtiofs.rst @@ -0,0 +1,153 @@ +============================ +Sharing files with Virtio-FS +============================ + +=== 8< delete before merging 8< === +NOTE: if you're looking at this note, this is just a proposal. +See the up-to-date version on: https://libvirt.org/kbase/virtiofs.html +=== 8< --------------------- 8< === + +.. contents:: + +========= +Virtio-FS +========= + +Virtio-FS is a delicious delicacy aiming to provide an easy-to-configure +way of sharing filesystems between the host and the virtual machine. + +See https://virtio-fs.gitlab.io/ + +========== +Host setup +========== + +The host-side virtiofsd daemon, like other vhost-user backed devices, +requres shared memory between the host and the guest. As of QEMU 4.2, this +requires specifying a NUMA topology for the guest and explicitly specifying +a memory backend. Multiple options are available: + +Either of the following: + +1. Use file-backed memory + +Configure the directory where the files backing the memory will be stored +with the ``memory_backing_dir`` option in ``/etc/libvirt/qemu.conf`` + +:: + + # This directory is used for memoryBacking source if configured as file. + # NOTE: big files will be stored here + memory_backing_dir = "/dev/shm/" + +2. Use hugepage-backed memory + +Make sure there are enough huge pages allocated for the requested guest memory. +For exmaple, for one guest with 2 GiB of RAM backed by 2 MiB hugepages: + +:: + + # virsh allocpages 2M 1024 + +=========== +Guest setup +=========== + +1. Specify the NUMA topology + +in the domain XML of the guest. +For the simplest one-node topology for a guest with 2GiB of RAM and 8 vCPUs: + +:: + + <domain> + ... + <cpu ...> + <numa> + <cell id='0' cpus='0-7' memory='2' unit='GiB' memAccess='shared'/> + </numa> + </cpu> + ... + </domain> + +Note that the CPU element might already be specified and only one is allowed. + +2. Specify the memory backend + +Either of the following: + +2.1. File-backed memory + +:: + + <domain> + ... + <memoryBacking> + <access mode='shared'/> + </memoryBacking> + ... + </domain> + +This will create a file in the directory specified in ``qemu.conf`` + +2.2. Hugepage-backed memory + +:: + + <domain> + ... + <memoryBacking> + <hugepages> + <page size='2' unit='M'/> + </hugepages> + <access mode='shared'/> + </memoryBacking> + ... + </domain> + +3. Add the ``vhost-user-fs`` QEMU device via the ``filesystem`` element + +:: + + <domain> + ... + <devices> + ... + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'> + <binary>/usr/libexec/virtiofsd</binary> + </driver> + <source dir='/path'/> + <target dir='mount_tag'/> + </filesystem> + ... + </devices> + </domain> + +Note that despite its name, the ``target dir`` is actually a mount tag and does +not have to correspond to the desired mount point in the guest. + +So far, ``passthrough`` is the only supported access mode and it requires +running the ``virtiofsd`` daemon as root. + +4. Boot the guest and mount the filesystem + +:: + + guest# mount -t virtiofs mount_tag /mnt/mount/path + +Note: this requires virtiofs support in the guest kernel (Linux v5.4 or later) + +=================== +Optional parameters +=================== + +More optional elements can be specified + +:: + + <driver type='virtiofs' queue='1024' xattr='on'> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='1024' unit='GiB'/> + <lock posix_lock='on' flock='on'/> + </driver> -- 2.21.0

On 1/23/20 11:46 AM, Ján Tomko wrote:
Add a document describing the usage of virtiofs. --- docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/kbase/virtiofs.rst
+=== 8< delete before merging 8< === +NOTE: if you're looking at this note, this is just a proposal. +See the up-to-date version on: https://libvirt.org/kbase/virtiofs.html +=== 8< --------------------- 8< ===
I'm assuming this will be updated ;)
+ +.. contents:: + +========= +Virtio-FS +========= + +Virtio-FS is a delicious delicacy aiming to provide an easy-to-configure
Fun language, but diverges from the official description...
+way of sharing filesystems between the host and the virtual machine. + +See https://virtio-fs.gitlab.io/
...that you find here: "Virtio-fs is a shared file system that lets virtual machines access a directory tree on the host. Unlike existing approaches, it is designed to offer local file system semantics and performance." I'm not opposed to a fun turn of a phrase in what is otherwise dry technical documentation, but wonder if it helps our case here.
+ +2. Use hugepage-backed memory + +Make sure there are enough huge pages allocated for the requested guest memory. +For exmaple, for one guest with 2 GiB of RAM backed by 2 MiB hugepages:
example -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org

On Thu, Jan 23, 2020 at 03:58:43PM -0600, Eric Blake wrote:
On 1/23/20 11:46 AM, Ján Tomko wrote:
Add a document describing the usage of virtiofs. --- docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/kbase/virtiofs.rst
+=== 8< delete before merging 8< === +NOTE: if you're looking at this note, this is just a proposal. +See the up-to-date version on: https://libvirt.org/kbase/virtiofs.html +=== 8< --------------------- 8< ===
I'm assuming this will be updated ;)
+ +.. contents:: + +========= +Virtio-FS +========= + +Virtio-FS is a delicious delicacy aiming to provide an easy-to-configure
Fun language, but diverges from the official description...
+way of sharing filesystems between the host and the virtual machine. + +See https://virtio-fs.gitlab.io/
...that you find here: "Virtio-fs is a shared file system that lets virtual machines access a directory tree on the host. Unlike existing approaches, it is designed to offer local file system semantics and performance."
I'm not opposed to a fun turn of a phrase in what is otherwise dry technical documentation, but wonder if it helps our case here.
Oops, I totally forgot about that placeholder text. Jano
+ +2. Use hugepage-backed memory + +Make sure there are enough huge pages allocated for the requested guest memory. +For exmaple, for one guest with 2 GiB of RAM backed by 2 MiB hugepages:
example
-- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org

On Thu, Jan 23, 2020 at 18:46:11 +0100, Ján Tomko wrote:
Add a document describing the usage of virtiofs. --- docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/kbase/virtiofs.rst
The XML documentation added to formatdomain.html is really lacking. At the very least this document should be linked from there.
diff --git a/docs/kbase.html.in b/docs/kbase.html.in index c156414c41..7d6caf3cb1 100644 --- a/docs/kbase.html.in +++ b/docs/kbase.html.in @@ -29,6 +29,9 @@ <dt><a href="kbase/backing_chains.html">Backing chain management</a></dt> <dd>Explanation of how disk backing chain specification impacts libvirt's behaviour and basic troubleshooting steps of disk problems.</dd> + + <dt><a href="kbase/virtiofs.html">Virtio-FS</a></dt> + <dd>Share a filesystem between the guest and the host</dd> </dl> </div>
diff --git a/docs/kbase/virtiofs.rst b/docs/kbase/virtiofs.rst new file mode 100644 index 0000000000..83351e0a28 --- /dev/null +++ b/docs/kbase/virtiofs.rst @@ -0,0 +1,153 @@ +============================ +Sharing files with Virtio-FS +============================ + +=== 8< delete before merging 8< === +NOTE: if you're looking at this note, this is just a proposal. +See the up-to-date version on: https://libvirt.org/kbase/virtiofs.html +=== 8< --------------------- 8< === + +.. contents:: + +========= +Virtio-FS +========= + +Virtio-FS is a delicious delicacy aiming to provide an easy-to-configure +way of sharing filesystems between the host and the virtual machine. + +See https://virtio-fs.gitlab.io/ + +========== +Host setup +========== + +The host-side virtiofsd daemon, like other vhost-user backed devices, +requres shared memory between the host and the guest. As of QEMU 4.2, this +requires specifying a NUMA topology for the guest and explicitly specifying +a memory backend. Multiple options are available: + +Either of the following: + +1. Use file-backed memory + +Configure the directory where the files backing the memory will be stored +with the ``memory_backing_dir`` option in ``/etc/libvirt/qemu.conf`` + +:: + + # This directory is used for memoryBacking source if configured as file. + # NOTE: big files will be stored here + memory_backing_dir = "/dev/shm/" + +2. Use hugepage-backed memory + +Make sure there are enough huge pages allocated for the requested guest memory. +For exmaple, for one guest with 2 GiB of RAM backed by 2 MiB hugepages: + +:: + + # virsh allocpages 2M 1024 + +=========== +Guest setup +=========== + +1. Specify the NUMA topology + +in the domain XML of the guest. +For the simplest one-node topology for a guest with 2GiB of RAM and 8 vCPUs: + +:: + + <domain> + ... + <cpu ...> + <numa> + <cell id='0' cpus='0-7' memory='2' unit='GiB' memAccess='shared'/> + </numa> + </cpu> + ... + </domain> + +Note that the CPU element might already be specified and only one is allowed. + +2. Specify the memory backend + +Either of the following: + +2.1. File-backed memory + +:: + + <domain> + ... + <memoryBacking> + <access mode='shared'/> + </memoryBacking> + ... + </domain> + +This will create a file in the directory specified in ``qemu.conf`` + +2.2. Hugepage-backed memory + +:: + + <domain> + ... + <memoryBacking> + <hugepages> + <page size='2' unit='M'/> + </hugepages> + <access mode='shared'/> + </memoryBacking> + ... + </domain> + +3. Add the ``vhost-user-fs`` QEMU device via the ``filesystem`` element + +:: + + <domain> + ... + <devices> + ... + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'> + <binary>/usr/libexec/virtiofsd</binary> + </driver> + <source dir='/path'/> + <target dir='mount_tag'/> + </filesystem> + ... + </devices> + </domain> + +Note that despite its name, the ``target dir`` is actually a mount tag and does +not have to correspond to the desired mount point in the guest.
In that case it should perhaps also have a different attribute.
+ +So far, ``passthrough`` is the only supported access mode and it requires +running the ``virtiofsd`` daemon as root. + +4. Boot the guest and mount the filesystem + +:: + + guest# mount -t virtiofs mount_tag /mnt/mount/path + +Note: this requires virtiofs support in the guest kernel (Linux v5.4 or later) + +=================== +Optional parameters +=================== + +More optional elements can be specified + +:: + + <driver type='virtiofs' queue='1024' xattr='on'> + <binary>/usr/libexec/virtiofsd</binary> + <cache mode='always' size='1024' unit='GiB'/> + <lock posix_lock='on' flock='on'/> + </driver> -- 2.21.0

On Fri, Jan 24, 2020 at 10:41:32AM +0100, Peter Krempa wrote:
On Thu, Jan 23, 2020 at 18:46:11 +0100, Ján Tomko wrote:
Add a document describing the usage of virtiofs. --- docs/kbase.html.in | 3 + docs/kbase/virtiofs.rst | 153 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 docs/kbase/virtiofs.rst
[...]
+3. Add the ``vhost-user-fs`` QEMU device via the ``filesystem`` element + +:: + + <domain> + ... + <devices> + ... + <filesystem type='mount' accessmode='passthrough'> + <driver type='virtiofs'> + <binary>/usr/libexec/virtiofsd</binary> + </driver> + <source dir='/path'/> + <target dir='mount_tag'/> + </filesystem> + ... + </devices> + </domain> + +Note that despite its name, the ``target dir`` is actually a mount tag and does +not have to correspond to the desired mount point in the guest.
In that case it should perhaps also have a different attribute.
I was considering that, however we already use it the same way for 9pfs. https://www.redhat.com/archives/libvir-list/2019-November/msg01150.html Jano

On Thu, Jan 23, 2020 at 5:49 PM Ján Tomko <jtomko@redhat.com> wrote:
v1: https://www.redhat.com/archives/libvir-list/2019-November/msg00005.html
https://bugzilla.redhat.com/show_bug.cgi?id=1694166
Ján Tomko (10): conf: use virXMLFormatElement in virDomainFSDefFormat qemu: add QEMU_CAPS_VHOST_USER_FS schema: wrap fsDriver in a choice group conf: qemu: add virtiofs fsdriver type conf: add virtiofs-related elements and attributes qemu: add virtiofs_debug to qemu.conf qemu: validate virtiofs filesystems qemu: add code for handling virtiofsd qemu: build vhost-user-fs device command line docs: add virtiofs kbase
Thanks for adding virtiofsd parameters (like the debug flag, xattr, posix file locking, etc). This series looks functionally complete to me: Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
participants (4)
-
Eric Blake
-
Ján Tomko
-
Peter Krempa
-
Stefan Hajnoczi