[PATCH v3 0/3] add support for QEMU 9pfs 'multidevs' option

QEMU 4.2 added a new option 'multidevs' for 9pfs. The following patch adds support for this new option to libvirt. In short, what is this about: to distinguish files uniquely from each other in general, numeric file IDs are typically used for comparison, which in practice is the combination of a file's device ID and the file's inode number. Unfortunately 9p protocol's QID field used for this purpose, currently is too small to fit both the device ID and inode number in, which hence is a problem if one 9pfs export contains multiple devices and may thus lead to misbheaviours on guest (e.g. with SAMBA file servers) in that case due to potential file ID collisions. To mitigate this problem with 9pfs a 'multidevs' option was introduced in QEMU 4.2 for defining how to deal with this, e.g. multidevs=remap will cause QEMU's 9pfs implementation to remap all inodes from host side to different inode numbers on guest side in a way that prevents file ID collisions. NOTE: In the libvirt docs changes of this libvirt patch I simply assumed "since 6.2.0". So the final libvirt version number would need to be adjusted in that text if necessary. See QEMU discussion with following Message-ID for details: 8a2ffe17fda3a86b9a5a437e1245276881f1e235.1567680121.git.qemu_oss@crudebyte.com v2->v3: * Rebased to master (SHA-1 e4bf03b8ff). * Auto sense QEMU capability for command line option fsdev.multidevs instead of checking for QEMU version 4.2. [patch 1] * Auto regenerated capabilities data for all archs (fixes capability test). [patch 1] * Added XML test. [patch 2] * Added argv test. [patch 3] Message-ID of v2: cover.1584723662.git.qemu_oss@crudebyte.com Christian Schoenebeck (3): qemu: capabilities: add QEMU_CAPS_VIRTFS_MULTIDEVS conf: add 'multidevs' option qemu: add support for 'multidevs' option docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 ++++ .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml -- 2.20.1

The QEMU 9pfs 'multidevs' option exists since QEMU 4.2. Probe QEMU's command line set though to check whether this option is really available, and if yes enable this new QEMU_CAPS_VIRTFS_MULTIDEVS capability on libvirt side. Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.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 + tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml | 1 + 8 files changed, 9 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a95a60c36a..5514f8eabf 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -567,6 +567,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "query-named-block-nodes.flat", "blockdev-snapshot.allow-write-only-overlay", "blockdev-reopen", + "virtfs-multidevs", ); @@ -3156,6 +3157,7 @@ static struct virQEMUCapsCommandLineProps virQEMUCapsCommandLine[] = { { "chardev", "fd", QEMU_CAPS_CHARDEV_FD_PASS }, { "overcommit", NULL, QEMU_CAPS_OVERCOMMIT }, { "smp-opts", "dies", QEMU_CAPS_SMP_DIES }, + { "fsdev", "multidevs", QEMU_CAPS_VIRTFS_MULTIDEVS }, }; static int diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index f0961e273c..bd9f9f3537 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -548,6 +548,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */ QEMU_CAPS_QMP_QUERY_NAMED_BLOCK_NODES_FLAT, /* query-named-block-nodes supports the 'flat' option */ QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY, /* blockdev-snapshot has the 'allow-write-only-overlay' feature */ QEMU_CAPS_BLOCKDEV_REOPEN, /* 'blockdev-reopen' qmp command is supported */ + QEMU_CAPS_VIRTFS_MULTIDEVS, /* fsdev.multidevs */ 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 640ce29c8c..4874721305 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.aarch64.xml @@ -179,6 +179,7 @@ <flag name='rng-builtin'/> <flag name='virtio-net.failover'/> <flag name='vhost-user-fs'/> + <flag name='virtfs-multidevs'/> <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 37776e1bbe..e2df6e3af0 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.s390x.xml @@ -138,6 +138,7 @@ <flag name='smp-dies'/> <flag name='rng-builtin'/> <flag name='vhost-user-fs'/> + <flag name='virtfs-multidevs'/> <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 83e804ea36..d8b0de46cd 100644 --- a/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_4.2.0.x86_64.xml @@ -223,6 +223,7 @@ <flag name='rng-builtin'/> <flag name='virtio-net.failover'/> <flag name='vhost-user-fs'/> + <flag name='virtfs-multidevs'/> <version>4002000</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100242</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml index e52c60607d..3a695fbe79 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml @@ -181,6 +181,7 @@ <flag name='virtio-net.failover'/> <flag name='cpu.kvm-no-adjvtime'/> <flag name='vhost-user-fs'/> + <flag name='virtfs-multidevs'/> <version>4002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>61700241</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml index 85fdb21c56..2c194301db 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml @@ -189,6 +189,7 @@ <flag name='vhost-user-fs'/> <flag name='query-named-block-nodes.flat'/> <flag name='blockdev-snapshot.allow-write-only-overlay'/> + <flag name='virtfs-multidevs'/> <version>4002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>42900241</microcodeVersion> diff --git a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml index d773f7e356..95fa0813dd 100644 --- a/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml @@ -226,6 +226,7 @@ <flag name='vhost-user-fs'/> <flag name='query-named-block-nodes.flat'/> <flag name='blockdev-snapshot.allow-write-only-overlay'/> + <flag name='virtfs-multidevs'/> <version>4002050</version> <kvmVersion>0</kvmVersion> <microcodeVersion>43100241</microcodeVersion> -- 2.20.1

On a Monday in 2020, Christian Schoenebeck wrote:
The QEMU 9pfs 'multidevs' option exists since QEMU 4.2. Probe QEMU's command line set though to check whether this option is really available, and if yes enable this new QEMU_CAPS_VIRTFS_MULTIDEVS capability on libvirt side.
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.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 + tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml | 1 + 8 files changed, 9 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a95a60c36a..5514f8eabf 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -567,6 +567,7 @@ VIR_ENUM_IMPL(virQEMUCaps, "query-named-block-nodes.flat", "blockdev-snapshot.allow-write-only-overlay", "blockdev-reopen", + "virtfs-multidevs",
since we probe the 'fsdev' command line option and use the -fsdev command line option, I renamed the capability to QEMU_CAPS_FSDEV_MULTIDEVS and its text variant to fsdev.multidevs Jano
);

On Montag, 6. April 2020 13:59:24 CEST Ján Tomko wrote:
On a Monday in 2020, Christian Schoenebeck wrote:
The QEMU 9pfs 'multidevs' option exists since QEMU 4.2. Probe QEMU's command line set though to check whether this option is really available, and if yes enable this new QEMU_CAPS_VIRTFS_MULTIDEVS capability on libvirt side.
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.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 + tests/qemucapabilitiesdata/caps_5.0.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_5.0.0.x86_64.xml | 1 + 8 files changed, 9 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index a95a60c36a..5514f8eabf 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -567,6 +567,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
"query-named-block-nodes.flat", "blockdev-snapshot.allow-write-only-overlay", "blockdev-reopen",
+ "virtfs-multidevs",
since we probe the 'fsdev' command line option and use the -fsdev command line option, I renamed the capability to QEMU_CAPS_FSDEV_MULTIDEVS and its text variant to fsdev.multidevs
Sure, fine with me! Best regards, Christian Schoenebeck

Introduce new 'multidevs' option for filesystem. <filesystem type='mount' accessmode='mapped' multidevs='remap'> <source dir='/path'/> <target dir='mount_tag'> </filesystem> This option prevents misbehaviours on guest if a qemu 9pfs export contains multiple devices, due to the potential file ID collisions this otherwise may cause. Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> --- docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 7 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 28e779b90a..43e8a557c0 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3967,7 +3967,7 @@ <source name='my-vm-template'/> <target dir='/'/> </filesystem> - <filesystem type='mount' accessmode='passthrough'> + <filesystem type='mount' accessmode='passthrough' multidevs='remap'> <driver type='path' wrpolicy='immediate'/> <source dir='/export/to/guest'/> <target dir='/import/from/host'/> @@ -4092,6 +4092,44 @@ for more details. </p> + <p> + The filesystem element has an optional attribute <code>multidevs</code> + which specifies how to deal with a filesystem export containing more than + one device, in order to avoid file ID collisions on guest when using 9pfs + (<span class="since">since 6.2.0, requires QEMU 4.2</span>). + This attribute is not available for virtiofs. The possible values are: + </p> + + <dl> + <dt><code>default</code></dt> + <dd> + Use QEMU's default setting (which currently is <code>warn</code>). + </dd> + <dt><code>remap</code></dt> + <dd> + This setting allows guest to access multiple devices per export without + encountering misbehaviours. Inode numbers from host are automatically + remapped on guest to actively prevent file ID collisions if guest + accesses one export containing multiple devices. + </dd> + <dt><code>forbid</code></dt> + <dd> + Only allow to access one device per export by guest. Attempts to access + additional devices on the same export will cause the individual + filesystem access by guest to fail with an error and being logged (once) + as error on host side. + </dd> + <dt><code>warn</code></dt> + <dd> + This setting resembles the behaviour of 9pfs prior to QEMU 4.2, that is + no action is performed to prevent any potential file ID collisions if an + export contains multiple devices, with the only exception: a warning is + logged (once) on host side now. This setting may lead to misbehaviours + on guest side if more than one device is exported per export, due to the + potential file ID collisions this may cause on guest side in that case. + </dd> + </dl> + </dd> <p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 5de17593c1..6bfb8e8d27 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2700,6 +2700,16 @@ </choice> </attribute> </optional> + <optional> + <attribute name="multidevs"> + <choice> + <value>default</value> + <value>remap</value> + <value>forbid</value> + <value>warn</value> + </choice> + </attribute> + </optional> <optional> <element name='readonly'> <empty/> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 27bc5a797b..011d244ed6 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -502,6 +502,14 @@ VIR_ENUM_IMPL(virDomainFSModel, "virtio-non-transitional", ); +VIR_ENUM_IMPL(virDomainFSMultidevs, + VIR_DOMAIN_FS_MULTIDEVS_LAST, + "default", + "remap", + "forbid", + "warn", +); + VIR_ENUM_IMPL(virDomainFSCacheMode, VIR_DOMAIN_FS_CACHE_MODE_LAST, "default", @@ -11385,6 +11393,7 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, g_autofree char *usage = NULL; g_autofree char *units = NULL; g_autofree char *model = NULL; + g_autofree char *multidevs = NULL; ctxt->node = node; @@ -11423,6 +11432,17 @@ virDomainFSDefParseXML(virDomainXMLOptionPtr xmlopt, } } + multidevs = virXMLPropString(node, "multidevs"); + if (multidevs) { + if ((def->multidevs = virDomainFSMultidevsTypeFromString(multidevs)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown multidevs '%s'"), multidevs); + goto error; + } + } else { + def->multidevs = VIR_DOMAIN_FS_MULTIDEVS_DEFAULT; + } + if (virDomainParseScaledValue("./space_hard_limit[1]", NULL, ctxt, &def->space_hard_limit, 1, ULLONG_MAX, false) < 0) @@ -25380,6 +25400,7 @@ virDomainFSDefFormat(virBufferPtr buf, const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode); const char *fsdriver = virDomainFSDriverTypeToString(def->fsdriver); const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy); + const char *multidevs = virDomainFSMultidevsTypeToString(def->multidevs); const char *src = def->src->path; g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) driverBuf = VIR_BUFFER_INIT_CHILD(buf); @@ -25398,6 +25419,12 @@ virDomainFSDefFormat(virBufferPtr buf, return -1; } + if (!multidevs) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected multidevs %d"), def->multidevs); + return -1; + } + virBufferAsprintf(buf, "<filesystem type='%s' accessmode='%s'", type, accessmode); @@ -25405,6 +25432,8 @@ virDomainFSDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " model='%s'", virDomainFSModelTypeToString(def->model)); } + if (def->multidevs) + virBufferAsprintf(buf, " multidevs='%s'", multidevs); virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 33875d942f..2038b54c32 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -796,6 +796,18 @@ typedef enum { VIR_DOMAIN_FS_WRPOLICY_LAST } virDomainFSWrpolicy; +/* How to handle exports containing multiple devices. */ +typedef enum { + VIR_DOMAIN_FS_MULTIDEVS_DEFAULT = 0, /* Use QEMU's default setting */ + VIR_DOMAIN_FS_MULTIDEVS_REMAP, /* Remap inodes from host to guest */ + VIR_DOMAIN_FS_MULTIDEVS_FORBID, /* Prohibit more than one device */ + VIR_DOMAIN_FS_MULTIDEVS_WARN, /* Just log a warning if multiple devices */ + + VIR_DOMAIN_FS_MULTIDEVS_LAST +} virDomainFSMultidevs; + +VIR_ENUM_DECL(virDomainFSMultidevs); + typedef enum { VIR_DOMAIN_FS_MODEL_DEFAULT = 0, VIR_DOMAIN_FS_MODEL_VIRTIO, @@ -820,6 +832,7 @@ struct _virDomainFSDef { int wrpolicy; /* enum virDomainFSWrpolicy */ int format; /* virStorageFileFormat */ int model; /* virDomainFSModel */ + int multidevs; /* virDomainFSMultidevs */ unsigned long long usage; /* in bytes */ virStorageSourcePtr src; char *dst; diff --git a/tests/qemuxml2argvdata/virtio-9p-multidevs.xml b/tests/qemuxml2argvdata/virtio-9p-multidevs.xml new file mode 100644 index 0000000000..7a3b865415 --- /dev/null +++ b/tests/qemuxml2argvdata/virtio-9p-multidevs.xml @@ -0,0 +1,53 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <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'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <filesystem type='mount' accessmode='mapped' multidevs='remap'> + <source dir='/export/fs0'/> + <target dir='fs0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </filesystem> + <filesystem type='mount' accessmode='mapped' multidevs='forbid'> + <source dir='/export/fs1'/> + <target dir='fs1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </filesystem> + <filesystem type='mount' accessmode='mapped' multidevs='warn'> + <source dir='/export/fs2'/> + <target dir='fs2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </filesystem> + <serial type='pty'> + <target type='isa-serial' port='0'> + <model name='isa-serial'/> + </target> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml b/tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml new file mode 100644 index 0000000000..4ea75ff8e3 --- /dev/null +++ b/tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml @@ -0,0 +1,56 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>qemu64</model> + </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='piix3-uhci'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <filesystem type='mount' accessmode='mapped' multidevs='remap'> + <source dir='/export/fs0'/> + <target dir='fs0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </filesystem> + <filesystem type='mount' accessmode='mapped' multidevs='forbid'> + <source dir='/export/fs1'/> + <target dir='fs1'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </filesystem> + <filesystem type='mount' accessmode='mapped' multidevs='warn'> + <source dir='/export/fs2'/> + <target dir='fs2'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </filesystem> + <serial type='pty'> + <target type='isa-serial' port='0'> + <model name='isa-serial'/> + </target> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index a0d27fdcf8..b4c83fccca 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1485,6 +1485,8 @@ mymain(void) DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-kvm-q35-4.2", "x86_64"); DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-q35-4.2", "x86_64"); + DO_TEST_CAPS_LATEST("virtio-9p-multidevs"); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.20.1

This option prevents misbehaviours on guest if a qemu 9pfs export contains multiple devices, due to the potential file ID collisions this otherwise may cause. Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> --- src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 +++++ .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + 4 files changed, 66 insertions(+) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d1b689dfd3..5b774973b7 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2632,6 +2632,13 @@ qemuBuildFSStr(virDomainFSDefPtr fs) } else if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_SQUASH) { virBufferAddLit(&opt, ",security_model=none"); } + if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_REMAP) { + virBufferAddLit(&opt, ",multidevs=remap"); + } else if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_FORBID) { + virBufferAddLit(&opt, ",multidevs=forbid"); + } else if (fs->multidevs == VIR_DOMAIN_FS_MULTIDEVS_WARN) { + virBufferAddLit(&opt, ",multidevs=warn"); + } } else if (fs->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_HANDLE) { /* removed since qemu 4.0.0 see v3.1.0-29-g93aee84f57 */ virBufferAddLit(&opt, "handle"); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index adda17a49f..21a01f2908 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -8569,6 +8569,13 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, _("only supports mount filesystem type")); return -1; } + if (fs->multidevs != VIR_DOMAIN_FS_MODEL_DEFAULT && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTFS_MULTIDEVS)) + { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("multidevs is not supported with this QEMU binary")); + return -1; + } switch ((virDomainFSDriverType) fs->fsdriver) { case VIR_DOMAIN_FS_DRIVER_TYPE_DEFAULT: @@ -8621,6 +8628,11 @@ qemuDomainDeviceDefValidateFS(virDomainFSDefPtr fs, _("virtiofs is not supported with this QEMU binary")); return -1; } + if (fs->multidevs != VIR_DOMAIN_FS_MULTIDEVS_DEFAULT) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtiofs does not support multidevs")); + return -1; + } if (qemuDomainDefValidateVirtioFSSharedMemory(def) < 0) return -1; break; diff --git a/tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args b/tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args new file mode 100644 index 0000000000..5a2e1fafe1 --- /dev/null +++ b/tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args @@ -0,0 +1,45 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu-system-x86_64 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object secret,id=masterKey0,format=raw,\ +file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ +-machine pc,accel=tcg,usb=off,dump-guest-core=off \ +-cpu qemu64 \ +-m 214 \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-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 \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-fsdev local,security_model=mapped,multidevs=remap,id=fsdev-fs0,\ +path=/export/fs0 \ +-device virtio-9p-pci,id=fs0,fsdev=fsdev-fs0,mount_tag=fs0,bus=pci.0,addr=0x2 \ +-fsdev local,security_model=mapped,multidevs=forbid,id=fsdev-fs1,\ +path=/export/fs1 \ +-device virtio-9p-pci,id=fs1,fsdev=fsdev-fs1,mount_tag=fs1,bus=pci.0,addr=0x3 \ +-fsdev local,security_model=mapped,multidevs=warn,id=fsdev-fs2,\ +path=/export/fs2 \ +-device virtio-9p-pci,id=fs2,fsdev=fsdev-fs2,mount_tag=fs2,bus=pci.0,addr=0x4 \ +-chardev pty,id=charserial0 \ +-device isa-serial,chardev=charserial0,id=serial0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0xc \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 4d44286b5a..e0fc3ddf67 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -3122,6 +3122,8 @@ mymain(void) DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-kvm-q35-4.2", "x86_64"); DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-q35-4.2", "x86_64"); + DO_TEST_CAPS_LATEST("virtio-9p-multidevs"); + if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL) virFileDeleteTree(fakerootdir); -- 2.20.1

On Montag, 30. März 2020 20:27:00 CEST Christian Schoenebeck wrote:
v2->v3:
* Rebased to master (SHA-1 e4bf03b8ff).
* Auto sense QEMU capability for command line option fsdev.multidevs instead of checking for QEMU version 4.2. [patch 1]
* Auto regenerated capabilities data for all archs (fixes capability test). [patch 1]
* Added XML test. [patch 2]
* Added argv test. [patch 3]
Message-ID of v2: cover.1584723662.git.qemu_oss@crudebyte.com
Christian Schoenebeck (3): qemu: capabilities: add QEMU_CAPS_VIRTFS_MULTIDEVS conf: add 'multidevs' option qemu: add support for 'multidevs' option
docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 ++++ .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml
Never mind about this version; it would no longer merge against master. :/ I'll post a v4 with merge conflicts being resolved. Best regards, Christian Schoenebeck

On a Friday in 2020, Christian Schoenebeck wrote:
On Montag, 30. März 2020 20:27:00 CEST Christian Schoenebeck wrote:
v2->v3:
* Rebased to master (SHA-1 e4bf03b8ff).
* Auto sense QEMU capability for command line option fsdev.multidevs instead of checking for QEMU version 4.2. [patch 1]
* Auto regenerated capabilities data for all archs (fixes capability test). [patch 1]
* Added XML test. [patch 2]
* Added argv test. [patch 3]
Message-ID of v2: cover.1584723662.git.qemu_oss@crudebyte.com
Christian Schoenebeck (3): qemu: capabilities: add QEMU_CAPS_VIRTFS_MULTIDEVS conf: add 'multidevs' option qemu: add support for 'multidevs' option
docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 ++++ .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml
Never mind about this version; it would no longer merge against master. :/
I'll post a v4 with merge conflicts being resolved.
No need to do that, I already have it applied and rebased Jano
Best regards, Christian Schoenebeck

On Freitag, 3. April 2020 18:27:28 CEST you wrote:
On a Friday in 2020, Christian Schoenebeck wrote:
On Montag, 30. März 2020 20:27:00 CEST Christian Schoenebeck wrote:
v2->v3: * Rebased to master (SHA-1 e4bf03b8ff).
* Auto sense QEMU capability for command line option fsdev.multidevs
instead of checking for QEMU version 4.2. [patch 1]
* Auto regenerated capabilities data for all archs (fixes capability
test). [patch 1]
* Added XML test. [patch 2]
* Added argv test. [patch 3]
Message-ID of v2: cover.1584723662.git.qemu_oss@crudebyte.com
Christian Schoenebeck (3): qemu: capabilities: add QEMU_CAPS_VIRTFS_MULTIDEVS conf: add 'multidevs' option qemu: add support for 'multidevs' option
docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 ++++ .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 277 insertions(+), 1 deletion(-) create mode 100644
tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml
Never mind about this version; it would no longer merge against master. :/
I'll post a v4 with merge conflicts being resolved.
No need to do that, I already have it applied and rebased
Yeeehaaa! Thanks Ján, I appreciate it! :) Best regards, Christian Schoenebeck

On a Monday in 2020, Christian Schoenebeck wrote:
QEMU 4.2 added a new option 'multidevs' for 9pfs. The following patch adds support for this new option to libvirt.
In short, what is this about: to distinguish files uniquely from each other in general, numeric file IDs are typically used for comparison, which in practice is the combination of a file's device ID and the file's inode number. Unfortunately 9p protocol's QID field used for this purpose, currently is too small to fit both the device ID and inode number in, which hence is a problem if one 9pfs export contains multiple devices and may thus lead to misbheaviours on guest (e.g. with SAMBA file servers) in that case due to potential file ID collisions.
To mitigate this problem with 9pfs a 'multidevs' option was introduced in QEMU 4.2 for defining how to deal with this, e.g. multidevs=remap will cause QEMU's 9pfs implementation to remap all inodes from host side to different inode numbers on guest side in a way that prevents file ID collisions.
NOTE: In the libvirt docs changes of this libvirt patch I simply assumed "since 6.2.0". So the final libvirt version number would need to be adjusted in that text if necessary.
See QEMU discussion with following Message-ID for details: 8a2ffe17fda3a86b9a5a437e1245276881f1e235.1567680121.git.qemu_oss@crudebyte.com
v2->v3:
* Rebased to master (SHA-1 e4bf03b8ff).
* Auto sense QEMU capability for command line option fsdev.multidevs instead of checking for QEMU version 4.2. [patch 1]
* Auto regenerated capabilities data for all archs (fixes capability test). [patch 1]
* Added XML test. [patch 2]
* Added argv test. [patch 3]
Message-ID of v2: cover.1584723662.git.qemu_oss@crudebyte.com
Christian Schoenebeck (3): qemu: capabilities: add QEMU_CAPS_VIRTFS_MULTIDEVS conf: add 'multidevs' option qemu: add support for 'multidevs' option
docs/formatdomain.html.in | 40 ++++++++++++- docs/schemas/domaincommon.rng | 10 ++++ src/conf/domain_conf.c | 29 ++++++++++ src/conf/domain_conf.h | 13 +++++ src/qemu/qemu_capabilities.c | 2 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 7 +++ src/qemu/qemu_domain.c | 12 ++++ .../caps_4.2.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_4.2.0.s390x.xml | 1 + .../caps_4.2.0.x86_64.xml | 1 + .../caps_5.0.0.aarch64.xml | 1 + .../qemucapabilitiesdata/caps_5.0.0.ppc64.xml | 1 + .../caps_5.0.0.x86_64.xml | 1 + .../virtio-9p-multidevs.x86_64-latest.args | 45 +++++++++++++++ .../qemuxml2argvdata/virtio-9p-multidevs.xml | 53 ++++++++++++++++++ tests/qemuxml2argvtest.c | 2 + .../virtio-9p-multidevs.x86_64-latest.xml | 56 +++++++++++++++++++ tests/qemuxml2xmltest.c | 2 + 19 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/virtio-9p-multidevs.xml create mode 100644 tests/qemuxml2xmloutdata/virtio-9p-multidevs.x86_64-latest.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (2)
-
Christian Schoenebeck
-
Ján Tomko