[libvirt] [PATCH] Implement support for virtio plan9fs filesystem passthrough in QEMU

Daniel P. Berrange berrange at redhat.com
Wed Jul 21 11:27:06 UTC 2010


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 3e35c57..23e418b 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1205,6 +1205,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... */
@@ -1987,6 +1989,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;
@@ -2324,6 +2330,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++) {
@@ -2713,6 +2728,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=mapped");
+    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)
 {
@@ -4274,6 +4347,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 ca4559f..68f10eb 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -91,6 +91,7 @@ enum qemud_cmd_flags {
     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_NODEFCONFIG   = (1LL << 37), /* -nodefconfig */
+    QEMUD_CMD_FLAG_FSDEV         = (1LL << 38), /* -fstype filesystem passthrough */
 };
 
 /* Main driver state */
@@ -175,6 +176,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__,           \
@@ -235,9 +237,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 24002b8..10d1342 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -357,6 +357,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.1.1




More information about the libvir-list mailing list