Add new attribute wrpolicy to <driver> element

This introduces new attribute wrpolicy with only supported
value as immediate. This will be an optional
attribute with no defaults. This helps specify whether
to skip the host page cache.

When wrpolicy is specified, meaning when wrpolicy=immediate
a writeback is explicitly initiated for the dirty pages in
the host page cache as part of the guest file write operation.

Usage:
<filesystem type='mount' accessmode='passthrough'>
  <driver type='path' wrpolicy='immediate'/>
  <source dir='/export/to/guest'/>
  <target dir='mount_tag'/>
</filesystem>

Currently this only works with type='mount' for the QEMU/KVM driver.

Signed-off-by: Deepak C Shetty <deepakcs@linux.vnet.ibm.com>
This commit is contained in:
Deepak C Shetty 2012-01-17 18:14:18 +05:30 committed by Eric Blake
parent 9619d8a62e
commit d9e0d8204b
12 changed files with 75 additions and 11 deletions

View File

@ -1396,7 +1396,7 @@
&lt;target dir='/'/&gt; &lt;target dir='/'/&gt;
&lt;/filesystem&gt; &lt;/filesystem&gt;
&lt;filesystem type='mount' accessmode='passthrough'&gt; &lt;filesystem type='mount' accessmode='passthrough'&gt;
&lt;driver type='path'/&gt; &lt;driver type='path' wrpolicy='immediate'/&gt;
&lt;source dir='/export/to/guest'/&gt; &lt;source dir='/export/to/guest'/&gt;
&lt;target dir='/import/from/host'/&gt; &lt;target dir='/import/from/host'/&gt;
&lt;readonly/&gt; &lt;readonly/&gt;
@ -1423,7 +1423,12 @@
sub-element <code>driver</code>, with an sub-element <code>driver</code>, with an
attribute <code>type='path'</code> attribute <code>type='path'</code>
or <code>type='handle'</code> <span class="since">(since or <code>type='handle'</code> <span class="since">(since
0.9.7)</span>. 0.9.7)</span>. The driver block has an optional attribute
<code>wrpolicy</code> that further controls interaction with
the host page cache; omitting the attribute gives default behavior,
while the value <code>immediate</code> means that a host writeback
is immediately triggered for all pages touched during a guest file
write operation <span class="since">(since 0.9.10)</span>.
</dd> </dd>
<dt><code>type='template'</code></dt> <dt><code>type='template'</code></dt>
<dd> <dd>

View File

@ -1162,6 +1162,11 @@
<value>handle</value> <value>handle</value>
</choice> </choice>
</attribute> </attribute>
<optional>
<attribute name="wrpolicy">
<value>immediate</value>
</attribute>
</optional>
<empty/> <empty/>
</element> </element>
</optional> </optional>

View File

@ -266,6 +266,9 @@ VIR_ENUM_IMPL(virDomainFSAccessMode, VIR_DOMAIN_FS_ACCESSMODE_LAST,
"mapped", "mapped",
"squash") "squash")
VIR_ENUM_IMPL(virDomainFSWrpolicy, VIR_DOMAIN_FS_WRPOLICY_LAST,
"default",
"immediate")
VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST, VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"user", "user",
@ -3460,6 +3463,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
char *source = NULL; char *source = NULL;
char *target = NULL; char *target = NULL;
char *accessmode = NULL; char *accessmode = NULL;
char *wrpolicy = NULL;
if (VIR_ALLOC(def) < 0) { if (VIR_ALLOC(def) < 0) {
virReportOOMError(); virReportOOMError();
@ -3509,6 +3513,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
def->readonly = 1; def->readonly = 1;
} else if ((fsdriver == NULL) && (xmlStrEqual(cur->name, BAD_CAST "driver"))) { } else if ((fsdriver == NULL) && (xmlStrEqual(cur->name, BAD_CAST "driver"))) {
fsdriver = virXMLPropString(cur, "type"); fsdriver = virXMLPropString(cur, "type");
wrpolicy = virXMLPropString(cur, "wrpolicy");
} }
} }
cur = cur->next; 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) { if (source == NULL) {
virDomainReportError(VIR_ERR_NO_SOURCE, virDomainReportError(VIR_ERR_NO_SOURCE,
target ? "%s" : NULL, target); target ? "%s" : NULL, target);
@ -3548,6 +3563,7 @@ cleanup:
VIR_FREE(target); VIR_FREE(target);
VIR_FREE(source); VIR_FREE(source);
VIR_FREE(accessmode); VIR_FREE(accessmode);
VIR_FREE(wrpolicy);
return def; return def;
@ -10166,6 +10182,7 @@ virDomainFSDefFormat(virBufferPtr buf,
const char *type = virDomainFSTypeToString(def->type); const char *type = virDomainFSTypeToString(def->type);
const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode); const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode);
const char *fsdriver = virDomainFSDriverTypeTypeToString(def->fsdriver); const char *fsdriver = virDomainFSDriverTypeTypeToString(def->fsdriver);
const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy);
if (!type) { if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@ -10185,7 +10202,14 @@ virDomainFSDefFormat(virBufferPtr buf,
type, accessmode); type, accessmode);
if (def->fsdriver) { if (def->fsdriver) {
virBufferAsprintf(buf, " <driver type='%s'/>\n", fsdriver); virBufferAsprintf(buf, " <driver type='%s'", fsdriver);
/* Don't generate anything if wrpolicy is set to default */
if (def->wrpolicy) {
virBufferAsprintf(buf, " wrpolicy='%s'", wrpolicy);
}
virBufferAddLit(buf, "/>\n");
} }
if (def->src) { if (def->src) {

View File

@ -491,12 +491,21 @@ enum virDomainFSAccessMode {
VIR_DOMAIN_FS_ACCESSMODE_LAST 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 struct _virDomainFSDef virDomainFSDef;
typedef virDomainFSDef *virDomainFSDefPtr; typedef virDomainFSDef *virDomainFSDefPtr;
struct _virDomainFSDef { struct _virDomainFSDef {
int type; int type;
int fsdriver; int fsdriver;
int accessmode; int accessmode;
int wrpolicy; /* enum virDomainFSWrpolicy */
char *src; char *src;
char *dst; char *dst;
unsigned int readonly : 1; unsigned int readonly : 1;
@ -1985,6 +1994,7 @@ VIR_ENUM_DECL(virDomainControllerModelUSB)
VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainFS)
VIR_ENUM_DECL(virDomainFSDriverType) VIR_ENUM_DECL(virDomainFSDriverType)
VIR_ENUM_DECL(virDomainFSAccessMode) VIR_ENUM_DECL(virDomainFSAccessMode)
VIR_ENUM_DECL(virDomainFSWrpolicy)
VIR_ENUM_DECL(virDomainNet) VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainNetBackend) VIR_ENUM_DECL(virDomainNetBackend)
VIR_ENUM_DECL(virDomainNetVirtioTxMode) VIR_ENUM_DECL(virDomainNetVirtioTxMode)

View File

@ -316,6 +316,8 @@ virDomainDiskTypeToString;
virDomainFSDefFree; virDomainFSDefFree;
virDomainFSTypeFromString; virDomainFSTypeFromString;
virDomainFSTypeToString; virDomainFSTypeToString;
virDomainFSWrpolicyTypeFromString;
virDomainFSWrpolicyTypeToString;
virDomainFindByID; virDomainFindByID;
virDomainFindByName; virDomainFindByName;
virDomainFindByUUID; virDomainFindByUUID;

View File

@ -1,7 +1,7 @@
/* /*
* qemu_capabilities.c: QEMU capabilities generation * 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 * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * 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", "blk-sg-io",
"drive-copy-on-read", "drive-copy-on-read",
"cpu-host", "cpu-host",
"fsdev-writeout",
); );
struct qemu_feature_flags { struct qemu_feature_flags {
@ -1090,6 +1091,8 @@ qemuCapsComputeCmdFlags(const char *help,
qemuCapsSet(flags, QEMU_CAPS_FSDEV); qemuCapsSet(flags, QEMU_CAPS_FSDEV);
if (strstr(fsdev, "readonly")) if (strstr(fsdev, "readonly"))
qemuCapsSet(flags, QEMU_CAPS_FSDEV_READONLY); qemuCapsSet(flags, QEMU_CAPS_FSDEV_READONLY);
if (strstr(fsdev, "writeout"))
qemuCapsSet(flags, QEMU_CAPS_FSDEV_WRITEOUT);
} }
if (strstr(help, "-smbios type")) if (strstr(help, "-smbios type"))
qemuCapsSet(flags, QEMU_CAPS_SMBIOS_TYPE); qemuCapsSet(flags, QEMU_CAPS_SMBIOS_TYPE);

View File

@ -1,7 +1,7 @@
/* /*
* qemu_capabilities.h: QEMU capabilities generation * 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 * Copyright (C) 2006 Daniel P. Berrange
* *
* This library is free software; you can redistribute it and/or * 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_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_DRIVE_COPY_ON_READ = 82, /* -drive copy-on-read */
QEMU_CAPS_CPU_HOST = 83, /* support for -cpu host */ 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 */ QEMU_CAPS_LAST, /* this must always be the last item */
}; };

View File

@ -2138,6 +2138,7 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs,
{ {
virBuffer opt = VIR_BUFFER_INITIALIZER; virBuffer opt = VIR_BUFFER_INITIALIZER;
const char *driver = qemuDomainFSDriverTypeToString(fs->fsdriver); const char *driver = qemuDomainFSDriverTypeToString(fs->fsdriver);
const char *wrpolicy = virDomainFSWrpolicyTypeToString(fs->wrpolicy);
if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) { if (fs->type != VIR_DOMAIN_FS_TYPE_MOUNT) {
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@ -2170,6 +2171,17 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs,
goto error; 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, ",id=%s%s", QEMU_FSDEV_HOST_PREFIX, fs->info.alias);
virBufferAsprintf(&opt, ",path=%s", fs->src); virBufferAsprintf(&opt, ",path=%s", fs->src);

View File

@ -666,7 +666,8 @@ mymain(void)
QEMU_CAPS_FSDEV_READONLY, QEMU_CAPS_FSDEV_READONLY,
QEMU_CAPS_VIRTIO_BLK_SCSI, QEMU_CAPS_VIRTIO_BLK_SCSI,
QEMU_CAPS_VIRTIO_BLK_SG_IO, 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; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View File

@ -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,\ /dev/HostVG/QEMUGuest1 -fsdev local,security_model=passthrough,id=fsdev-fs0,\
path=/export/to/guest -device virtio-9p-pci,id=fs0,fsdev=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 \ 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,\ path=/export/to/guest2 -device virtio-9p-pci,id=fs1,fsdev=fsdev-fs1,\
mount_tag=/import/from/host2,bus=pci.0,addr=0x4 \ 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,\ path=/export/to/guest3 -device virtio-9p-pci,id=fs2,fsdev=fsdev-fs2,\
mount_tag=/import/from/host3,bus=pci.0,addr=0x5 \ mount_tag=/import/from/host3,bus=pci.0,addr=0x5 \
-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x6

View File

@ -25,12 +25,12 @@
<target dir='/import/from/host'/> <target dir='/import/from/host'/>
</filesystem> </filesystem>
<filesystem accessmode='mapped'> <filesystem accessmode='mapped'>
<driver type='path'/> <driver type='path' wrpolicy='immediate'/>
<source dir='/export/to/guest2'/> <source dir='/export/to/guest2'/>
<target dir='/import/from/host2'/> <target dir='/import/from/host2'/>
</filesystem> </filesystem>
<filesystem> <filesystem>
<driver type='handle'/> <driver type='handle' wrpolicy='immediate'/>
<source dir='/export/to/guest3'/> <source dir='/export/to/guest3'/>
<target dir='/import/from/host3'/> <target dir='/import/from/host3'/>
</filesystem> </filesystem>

View File

@ -651,7 +651,8 @@ mymain(void)
DO_TEST("sound-device", false, DO_TEST("sound-device", false,
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_HDA_DUPLEX); QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_HDA_DUPLEX);
DO_TEST("fs9p", false, 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", false, NONE);
DO_TEST("hostdev-usb-address-device", false, DO_TEST("hostdev-usb-address-device", false,