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 | 1 + 5 files changed, 131 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 16d2f44..511b9de 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1188,6 +1188,8 @@ static unsigned long long qemudComputeCmdFlags(const char *help, flags |= QEMUD_CMD_FLAG_NO_KVM_PIT; if (strstr(help, "-tdf")) flags |= QEMUD_CMD_FLAG_TDF; + 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... */ @@ -1969,6 +1971,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; @@ -2248,6 +2254,15 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) if (qemuDomainPCIAddressSetNextAddr(addrs, &def->disks[i]->info) < 0) 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; + } for (i = 0; i < def->nnets ; i++) { if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) @@ -2646,6 +2661,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"); + 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) { @@ -4176,6 +4249,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 0f8a1b3..81ae3e2 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -90,6 +90,7 @@ enum qemud_cmd_flags { QEMUD_CMD_FLAG_NO_KVM_PIT = (1LL << 34), /* -no-kvm-pit-reinjection supported */ QEMUD_CMD_FLAG_TDF = (1LL << 35), /* -tdf flag (user-mode pit catchup) */ QEMUD_CMD_FLAG_PCI_CONFIGFD = (1LL << 36), /* pci-assign.configfd */ + QEMUD_CMD_FLAG_FSDEV = (1LL << 37), /* -fstype filesystem passthrough */ }; /* Main driver state */ @@ -173,6 +174,7 @@ typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; # 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__, \ @@ -233,9 +235,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..42c26a2 --- /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 -nodefaults -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -fsdev local,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=0x4 -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 9e4d5bf..4eb7ad8 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -335,6 +335,7 @@ mymain(int argc, char **argv) DO_TEST("watchdog-device", QEMUD_CMD_FLAG_DEVICE); DO_TEST("sound", 0); DO_TEST("sound-device", QEMUD_CMD_FLAG_DEVICE); + DO_TEST("fs9p", QEMUD_CMD_FLAG_DEVICE | QEMUD_CMD_FLAG_FSDEV); DO_TEST("hostdev-usb-address", 0); DO_TEST("hostdev-usb-address-device", QEMUD_CMD_FLAG_DEVICE); -- 1.6.6.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list