Rebased version of my original patch, changing to use 'passthrough'
security model by default. Support for other models can be added
in a follow up patch
Make use of the existing <filesystem> element to support plan9fs
filesystem passthrough in the QEMU driver
<filesystem type='mount'>
<source dir='/export/to/guest'/>
<target dir='/import/from/host'/>
</filesystem>
NB, the target is not actually a directory, it is merely a arbitrary
string tag that is exported to the guest as a hint for where to mount
it.
---
src/qemu/qemu_conf.c | 96 +++++++++++++++++++++++++
src/qemu/qemu_conf.h | 5 ++
tests/qemuxml2argvdata/qemuxml2argv-fs9p.args | 1 +
tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml | 28 +++++++
tests/qemuxml2argvtest.c | 2 +
5 files changed, 132 insertions(+), 0 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fs9p.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 7a37c70..18a302a 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1212,6 +1212,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_TDF;
if (strstr(help, ",menu=on"))
flags |= QEMUD_CMD_FLAG_BOOT_MENU;
+ if (strstr(help, "-fsdev"))
+ flags |= QEMUD_CMD_FLAG_FSDEV;
/* Keep disabled till we're actually ready to turn on netdev mode
* The plan is todo it in 0.13.0 QEMU, but lets wait & see... */
@@ -2008,6 +2010,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long
qemuCmdFlags)
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE))
return 0;
+ for (i = 0; i < def->nfss ; i++) {
+ if (virAsprintf(&def->fss[i]->info.alias, "fs%d", i) < 0)
+ goto no_memory;
+ }
for (i = 0; i < def->nsounds ; i++) {
if (virAsprintf(&def->sounds[i]->info.alias, "sound%d", i)
< 0)
goto no_memory;
@@ -2371,6 +2377,15 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
qemuDomainPCIAddressSetPtr addrs)
goto error;
}
}
+ for (i = 0; i < def->nfss ; i++) {
+ if (def->fss[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ continue;
+
+ /* Only support VirtIO-9p-pci so far. If that changes,
+ * we might need to skip devices here */
+ if (qemuDomainPCIAddressSetNextAddr(addrs, &def->fss[i]->info) < 0)
+ goto error;
+ }
/* Network interfaces */
for (i = 0; i < def->nnets ; i++) {
@@ -2761,6 +2776,64 @@ error:
}
+char *qemuBuildFSStr(virDomainFSDefPtr fs,
+ unsigned long long qemuCmdFlags ATTRIBUTE_UNUSED)
+{
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+
+ if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("can only passthrough directories"));
+ goto error;
+ }
+
+ virBufferAddLit(&opt, "local,security_model=passthrough");
+ virBufferVSprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX,
fs->info.alias);
+ virBufferVSprintf(&opt, ",path=%s", fs->src);
+
+ if (virBufferError(&opt)) {
+ virReportOOMError();
+ goto error;
+ }
+
+ return virBufferContentAndReset(&opt);
+
+error:
+ virBufferFreeAndReset(&opt);
+ return NULL;
+}
+
+
+char *
+qemuBuildFSDevStr(virDomainFSDefPtr fs)
+{
+ virBuffer opt = VIR_BUFFER_INITIALIZER;
+
+ if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("can only passthrough directories"));
+ goto error;
+ }
+
+ virBufferAddLit(&opt, "virtio-9p-pci");
+ virBufferVSprintf(&opt, ",id=%s", fs->info.alias);
+ virBufferVSprintf(&opt, ",fsdev=%s%s", QEMU_FSDEV_HOST_PREFIX,
fs->info.alias);
+ virBufferVSprintf(&opt, ",mount_tag=%s", fs->dst);
+ qemuBuildDeviceAddressStr(&opt, &fs->info);
+
+ if (virBufferError(&opt)) {
+ virReportOOMError();
+ goto error;
+ }
+
+ return virBufferContentAndReset(&opt);
+
+error:
+ virBufferFreeAndReset(&opt);
+ return NULL;
+}
+
+
char *
qemuBuildControllerDevStr(virDomainControllerDefPtr def)
{
@@ -4377,6 +4450,29 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
+ if (qemuCmdFlags & QEMUD_CMD_FLAG_FSDEV) {
+ for (i = 0 ; i < def->nfss ; i++) {
+ char *optstr;
+ virDomainFSDefPtr fs = def->fss[i];
+
+ ADD_ARG_LIT("-fsdev");
+ if (!(optstr = qemuBuildFSStr(fs, qemuCmdFlags)))
+ goto error;
+ ADD_ARG(optstr);
+
+ ADD_ARG_LIT("-device");
+ if (!(optstr = qemuBuildFSDevStr(fs)))
+ goto error;
+ ADD_ARG(optstr);
+ }
+ } else {
+ if (def->nfss) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("filesystem passthrough not supported by this
QEMU"));
+ goto error;
+ }
+ }
+
if (!def->nnets) {
/* If we have -device, then we set -nodefault already */
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 2c9e608..fbd89de 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -93,6 +93,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on support */
QEMUD_CMD_FLAG_ENABLE_KQEMU = (1LL << 39), /* -enable-kqemu flag */
+ QEMUD_CMD_FLAG_FSDEV = (1LL << 40), /* -fstype filesystem passthrough
*/
};
/* Main driver state */
@@ -188,6 +189,7 @@ struct _qemuDomainCmdlineDef {
# define QEMU_DRIVE_HOST_PREFIX "drive-"
# define QEMU_VIRTIO_SERIAL_PREFIX "virtio-serial"
+# define QEMU_FSDEV_HOST_PREFIX "fsdev-"
# define qemuReportError(code, ...) \
virReportErrorHelper(NULL, VIR_FROM_QEMU, code, __FILE__, \
@@ -248,9 +250,12 @@ char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
int bootable,
unsigned long long qemuCmdFlags);
+char *qemuBuildFSStr(virDomainFSDefPtr fs,
+ unsigned long long qemuCmdFlags);
/* Current, best practice */
char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk);
+char * qemuBuildFSDevStr(virDomainFSDefPtr fs);
/* Current, best practice */
char * qemuBuildControllerDevStr(virDomainControllerDefPtr def);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args
b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args
new file mode 100644
index 0000000..995ffc0
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args
@@ -0,0 +1 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214
-smp 1 -nographic -nodefconfig -nodefaults -monitor unix:/tmp/test-monitor,server,nowait
-no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -fsdev
local,security_model=passthrough,id=fsdev-fs0,path=/export/to/guest -device
virtio-9p-pci,id=fs0,fsdev=fsdev-fs0,mount_tag=/import/from/host,bus=pci.0,addr=0x2 -usb
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml
b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml
new file mode 100644
index 0000000..9072ead
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml
@@ -0,0 +1,28 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' 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</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <filesystem type='mount'>
+ <source dir='/export/to/guest'/>
+ <target dir='/import/from/host'/>
+ </filesystem>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 7b9df09..92d5b18 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -368,6 +368,8 @@ mymain(int argc, char **argv)
DO_TEST("sound", 0);
DO_TEST("sound-device", QEMUD_CMD_FLAG_DEVICE |
QEMUD_CMD_FLAG_NODEFCONFIG);
+ DO_TEST("fs9p", QEMUD_CMD_FLAG_DEVICE |
+ QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_FSDEV);
DO_TEST("hostdev-usb-address", 0);
DO_TEST("hostdev-usb-address-device", QEMUD_CMD_FLAG_DEVICE |
--
1.7.2.3