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,