diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 6bb5721a74..de9b480ac2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1396,7 +1396,7 @@ <target dir='/'/> </filesystem> <filesystem type='mount' accessmode='passthrough'> - <driver type='path'/> + <driver type='path' wrpolicy='immediate'/> <source dir='/export/to/guest'/> <target dir='/import/from/host'/> <readonly/> @@ -1423,7 +1423,12 @@ sub-element driver, with an attribute type='path' or type='handle' (since - 0.9.7). + 0.9.7). The driver block has an optional attribute + wrpolicy that further controls interaction with + the host page cache; omitting the attribute gives default behavior, + while the value immediate means that a host writeback + is immediately triggered for all pages touched during a guest file + write operation (since 0.9.10).
type='template'
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 27b9a1f046..2041dfbbc2 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -1162,6 +1162,11 @@ handle + + + immediate + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 96a4669fc3..f97014eef4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -266,6 +266,9 @@ VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST, "mapped", "squash") +VIR_ENUM_IMPL(virDomainFSWrpolicy, VIR_DOMAIN_FS_WRPOLICY_LAST, + "default", + "immediate") VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, "user", @@ -3460,6 +3463,7 @@ virDomainFSDefParseXML(xmlNodePtr node, char *source = NULL; char *target = NULL; char *accessmode = NULL; + char *wrpolicy = NULL; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -3509,6 +3513,7 @@ virDomainFSDefParseXML(xmlNodePtr node, def->readonly = 1; } else if ((fsdriver == NULL) && (xmlStrEqual(cur->name, BAD_CAST "driver"))) { fsdriver = virXMLPropString(cur, "type"); + wrpolicy = virXMLPropString(cur, "wrpolicy"); } } cur = cur->next; @@ -3522,6 +3527,16 @@ virDomainFSDefParseXML(xmlNodePtr node, } } + if (wrpolicy) { + if ((def->wrpolicy = virDomainFSWrpolicyTypeFromString(wrpolicy)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown filesystem write policy '%s'"), wrpolicy); + goto error; + } + } else { + def->wrpolicy = VIR_DOMAIN_FS_WRPOLICY_DEFAULT; + } + if (source == NULL) { virDomainReportError(VIR_ERR_NO_SOURCE, target ? "%s" : NULL, target); @@ -3548,6 +3563,7 @@ cleanup: VIR_FREE(target); VIR_FREE(source); VIR_FREE(accessmode); + VIR_FREE(wrpolicy); return def; @@ -10166,6 +10182,7 @@ virDomainFSDefFormat(virBufferPtr buf, const char *type = virDomainFSTypeToString(def->type); const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode); const char *fsdriver = virDomainFSDriverTypeTypeToString(def->fsdriver); + const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy); if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -10185,7 +10202,14 @@ virDomainFSDefFormat(virBufferPtr buf, type, accessmode); if (def->fsdriver) { - virBufferAsprintf(buf, " \n", fsdriver); + virBufferAsprintf(buf, " wrpolicy) { + virBufferAsprintf(buf, " wrpolicy='%s'", wrpolicy); + } + + virBufferAddLit(buf, "/>\n"); } if (def->src) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f3c45be07c..b121f9c17e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -491,12 +491,21 @@ enum virDomainFSAccessMode { VIR_DOMAIN_FS_ACCESSMODE_LAST }; +/* Filesystem Write policy */ +enum virDomainFSWrpolicy { + VIR_DOMAIN_FS_WRPOLICY_DEFAULT = 0, + VIR_DOMAIN_FS_WRPOLICY_IMMEDIATE, + + VIR_DOMAIN_FS_WRPOLICY_LAST +}; + typedef struct _virDomainFSDef virDomainFSDef; typedef virDomainFSDef *virDomainFSDefPtr; struct _virDomainFSDef { int type; int fsdriver; int accessmode; + int wrpolicy; /* enum virDomainFSWrpolicy */ char *src; char *dst; unsigned int readonly : 1; @@ -1985,6 +1994,7 @@ VIR_ENUM_DECL(virDomainControllerModelUSB) VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainFSDriverType) VIR_ENUM_DECL(virDomainFSAccessMode) +VIR_ENUM_DECL(virDomainFSWrpolicy) 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 faab0e252a..df8e4b0eec 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -316,6 +316,8 @@ virDomainDiskTypeToString; virDomainFSDefFree; virDomainFSTypeFromString; virDomainFSTypeToString; +virDomainFSWrpolicyTypeFromString; +virDomainFSWrpolicyTypeToString; virDomainFindByID; virDomainFindByName; virDomainFindByUUID; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index e9ae44d325..0a1c9aa384 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1,7 +1,7 @@ /* * qemu_capabilities.c: QEMU capabilities generation * - * Copyright (C) 2006-2011 Red Hat, Inc. + * Copyright (C) 2006-2012 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -149,6 +149,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "blk-sg-io", "drive-copy-on-read", "cpu-host", + "fsdev-writeout", ); struct qemu_feature_flags { @@ -1090,6 +1091,8 @@ qemuCapsComputeCmdFlags(const char *help, qemuCapsSet(flags, QEMU_CAPS_FSDEV); if (strstr(fsdev, "readonly")) qemuCapsSet(flags, QEMU_CAPS_FSDEV_READONLY); + if (strstr(fsdev, "writeout")) + qemuCapsSet(flags, QEMU_CAPS_FSDEV_WRITEOUT); } if (strstr(help, "-smbios type")) qemuCapsSet(flags, QEMU_CAPS_SMBIOS_TYPE); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index d69f854a2d..1d4d10e59d 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -1,7 +1,7 @@ /* * qemu_capabilities.h: QEMU capabilities generation * - * Copyright (C) 2006-2011 Red Hat, Inc. + * Copyright (C) 2006-2012 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -122,6 +122,7 @@ enum qemuCapsFlags { QEMU_CAPS_VIRTIO_BLK_SG_IO = 81, /* support for SG_IO commands, reportedly added in 0.11 */ QEMU_CAPS_DRIVE_COPY_ON_READ = 82, /* -drive copy-on-read */ QEMU_CAPS_CPU_HOST = 83, /* support for -cpu host */ + QEMU_CAPS_FSDEV_WRITEOUT = 84, /* -fsdev writeout supported */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index eccbe01638..3bbe9cf639 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2138,6 +2138,7 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs, { virBuffer opt = VIR_BUFFER_INITIALIZER; const char *driver = qemuDomainFSDriverTypeToString(fs->fsdriver); + const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy); if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) { qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -2170,6 +2171,17 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs, goto error; } } + + if (fs->wrpolicy) { + if (qemuCapsGet(qemuCaps, QEMU_CAPS_FSDEV_WRITEOUT)) { + virBufferAsprintf(&opt, ",writeout=%s", wrpolicy); + } else { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("filesystem writeout not supported")); + goto error; + } + } + virBufferAsprintf(&opt, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias); virBufferAsprintf(&opt, ",path=%s", fs->src); diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 164707df56..8802271d39 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -666,7 +666,8 @@ mymain(void) QEMU_CAPS_FSDEV_READONLY, QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SG_IO, - QEMU_CAPS_CPU_HOST); + QEMU_CAPS_CPU_HOST, + QEMU_CAPS_FSDEV_WRITEOUT); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args index 857981052f..f244114f04 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.args @@ -4,10 +4,10 @@ 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=0x3 \ --fsdev local,security_model=mapped,id=fsdev-fs1,\ +-fsdev local,security_model=mapped,writeout=immediate,id=fsdev-fs1,\ path=/export/to/guest2 -device virtio-9p-pci,id=fs1,fsdev=fsdev-fs1,\ mount_tag=/import/from/host2,bus=pci.0,addr=0x4 \ --fsdev handle,id=fsdev-fs2,\ +-fsdev handle,writeout=immediate,id=fsdev-fs2,\ path=/export/to/guest3 -device virtio-9p-pci,id=fs2,fsdev=fsdev-fs2,\ mount_tag=/import/from/host3,bus=pci.0,addr=0x5 \ -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml index 07d7e8abe3..e31db4879c 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-fs9p.xml @@ -25,12 +25,12 @@ - + - + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index d1834f59d3..5cec86bed4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -651,7 +651,8 @@ mymain(void) DO_TEST("sound-device", false, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_HDA_DUPLEX); DO_TEST("fs9p", false, - QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_FSDEV); + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_FSDEV, + QEMU_CAPS_FSDEV_WRITEOUT); DO_TEST("hostdev-usb-address", false, NONE); DO_TEST("hostdev-usb-address-device", false,