Jim Meyering wrote:
Hi John, I tried to apply that, but failed miserably, since all of the following was recently redone to use virBufferVSprintf rather than snprintf.
Yea I suspected the code was likely seeing some motion. Thanks for bringing it forward.
And it's a good thing, because with the changes below, there was potential buffer overrun: nc could end up larger than PATH_MAX.
You are correct. I mistook the return value of snprintf() in the case of truncation.
One remaining bit that I haven't done: add tests for this, exercising e.g., - cachemode - !cachemode && (disk->shared && !disk->readonly) - !cachemode && (!disk->shared || disk->readonly)
That logic should be correct as it exists in the patch, namely we'll generate a "cache=*" flag in the case cachemode was specified explicitly in the xml definition or for the preexisting case of (shared && !readonly). Here if both happen to be true the explicit xml cache tag takes precedence. But with the existing code we need to remove the clause of: @@ -1007,18 +1025,34 @@ int qemudBuildCommandLine(virConnectPtr if (bootable && disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) virBufferAddLit(&opt, ",boot=on"); - if (disk->shared && !disk->readonly) - virBufferAddLit(&opt, ",cache=off"); if (disk->driverType) virBufferVSprintf(&opt, ",fmt=%s", disk->driverType); As this results in generation of a "cache=*" twice on the qemu cmdline, and possibly of different dispositions. With this change I think it is good to go. The attached patch incorporates the above modification. -john -- john.cooper@xxxxxxxxxx
domain_conf.c | 34 ++++++++++++++++++++++++++-------- domain_conf.h | 16 ++++++++++++++++ qemu_conf.c | 43 ++++++++++++++++++++++++++++++++++++++----- qemu_conf.h | 3 ++- 4 files changed, 82 insertions(+), 14 deletions(-) ================================================================= --- a/src/domain_conf.h +++ b/src/domain_conf.h @@ -81,6 +81,21 @@ enum virDomainDiskBus { VIR_DOMAIN_DISK_BUS_LAST }; +/* summary of all possible host open file cache modes + */ +typedef enum { + VIR_DOMAIN_DISK_CACHE_UNSPECIFIED, /* reserved */ + VIR_DOMAIN_DISK_CACHE_OFF, + VIR_DOMAIN_DISK_CACHE_ON, + VIR_DOMAIN_DISK_CACHE_DISABLE, + VIR_DOMAIN_DISK_CACHE_WRITEBACK, + VIR_DOMAIN_DISK_CACHE_WRITETHRU, + + VIR_DOMAIN_DISK_CACHE_LAST + } virDomainDiskCache; + +VIR_ENUM_DECL(virDomainDiskCache) + /* Stores the virtual disk configuration */ typedef struct _virDomainDiskDef virDomainDiskDef; typedef virDomainDiskDef *virDomainDiskDefPtr; @@ -92,6 +107,7 @@ struct _virDomainDiskDef { char *dst; char *driverName; char *driverType; + int cachemode; unsigned int readonly : 1; unsigned int shared : 1; int slotnum; /* pci slot number for unattach */ ================================================================= --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -1,7 +1,7 @@ /* * config.c: VM configuration management * - * Copyright (C) 2006, 2007, 2008 Red Hat, Inc. + * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -399,7 +399,9 @@ int qemudExtractVersionInfo(const char * if (strstr(help, "-domid")) flags |= QEMUD_CMD_FLAG_DOMID; if (strstr(help, "-drive")) - flags |= QEMUD_CMD_FLAG_DRIVE; + flags |= QEMUD_CMD_FLAG_DRIVE | + (strstr(help, "cache=writethrough|writeback|none") ? + QEMUD_CMD_FLAG_DRIVE_CACHEMODE : 0); if (strstr(help, "boot=on")) flags |= QEMUD_CMD_FLAG_DRIVE_BOOT; if (version >= 9000) @@ -591,6 +593,22 @@ qemudNetworkIfaceConnect(virConnectPtr c return NULL; } +VIR_ENUM_DECL(qemu_cache_map) + +/* map from internal cache mode to qemu cache arg text + * + * Note: currently this replicates virDomainDiskCache, but will need to + * error flag potential new entries in virDomainDiskCache which are + * not supported by qemu (raising exceptions as appropriate). + */ +VIR_ENUM_IMPL(qemu_cache_map, VIR_DOMAIN_DISK_CACHE_LAST, + "", /* reserved -- mode not specified */ + "off", /* deprecated; use "none" */ + "on", /* obsolete; use "writethrough" */ + "none", + "writeback", + "writethrough") + static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev, char *buf, int buflen) @@ -1007,11 +1025,27 @@ int qemudBuildCommandLine(virConnectPtr if (bootable && disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) virBufferAddLit(&opt, ",boot=on"); - if (disk->shared && !disk->readonly) - virBufferAddLit(&opt, ",cache=off"); if (disk->driverType) virBufferVSprintf(&opt, ",fmt=%s", disk->driverType); + unsigned int qf; + int cachemode = disk->cachemode; + if (cachemode) { + if (qemudExtractVersionInfo(vm->def->emulator, NULL, &qf) < 0) + ; /* error reported */ + else if (!(qf & QEMUD_CMD_FLAG_DRIVE_CACHEMODE) + && cachemode == VIR_DOMAIN_DISK_CACHE_WRITETHRU) + cachemode = VIR_DOMAIN_DISK_CACHE_ON; + else if (qf & QEMUD_CMD_FLAG_DRIVE_CACHEMODE + && cachemode == VIR_DOMAIN_DISK_CACHE_ON) + cachemode = VIR_DOMAIN_DISK_CACHE_WRITETHRU; + } + if (cachemode || (disk->shared && !disk->readonly)) + virBufferVSprintf(&opt, ",cache=%s", + (cachemode + ? qemu_cache_mapTypeToString(cachemode) + : "off")); + if (virBufferError(&opt)) { virReportOOMError(conn); goto error; @@ -1577,4 +1611,3 @@ cleanup: VIR_FREE(xml); return ret; } - ================================================================= --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -1,7 +1,7 @@ /* * config.h: VM configuration management * - * Copyright (C) 2006, 2007 Red Hat, Inc. + * Copyright (C) 2006, 2007, 2009 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -53,6 +53,7 @@ enum qemud_cmd_flags { * since it had a design bug blocking the entire monitor console */ QEMUD_CMD_FLAG_MIGRATE_QEMU_TCP = (1 << 10), /* New migration syntax after merge to QEMU with TCP transport */ QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC = (1 << 11), /* New migration syntax after merge to QEMU with EXEC transport */ + QEMUD_CMD_FLAG_DRIVE_CACHEMODE = (1 << 12), /* Is the -cache option available */ }; /* Main driver state */ ================================================================= --- a/src/domain_conf.c +++ b/src/domain_conf.c @@ -1,7 +1,7 @@ /* * domain_conf.c: domain XML processing * - * Copyright (C) 2006-2008 Red Hat, Inc. + * Copyright (C) 2006-2009 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -551,6 +551,17 @@ int virDomainDiskCompare(virDomainDiskDe #ifndef PROXY + +/* map from xml cache tag to internal cache mode + */ +VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST, + "", /* reserved -- mode not specified */ + "off", + "on", + "none", + "writeback", + "writethrough"); + /* Parse the XML definition for a disk * @param node XML nodeset to parse for disk definition */ @@ -567,6 +578,8 @@ virDomainDiskDefParseXML(virConnectPtr c char *source = NULL; char *target = NULL; char *bus = NULL; + char *cachetag = NULL; + int cm; if (VIR_ALLOC(def) < 0) { virReportOOMError(conn); @@ -616,6 +629,12 @@ virDomainDiskDefParseXML(virConnectPtr c (xmlStrEqual(cur->name, BAD_CAST "driver"))) { driverName = virXMLPropString(cur, "name"); driverType = virXMLPropString(cur, "type"); + cachetag = virXMLPropString(cur, "cache"); + if (cachetag) { + if ((cm = virDomainDiskCacheTypeFromString(cachetag)) != -1) + def->cachemode = cm; + VIR_FREE(cachetag); + } } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { def->readonly = 1; } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { @@ -2770,14 +2789,13 @@ virDomainDiskDefFormat(virConnectPtr con type, device); if (def->driverName) { + virBufferVSprintf(buf, " <driver name='%s'", def->driverName); if (def->driverType) - virBufferVSprintf(buf, - " <driver name='%s' type='%s'/>\n", - def->driverName, def->driverType); - else - virBufferVSprintf(buf, - " <driver name='%s'/>\n", - def->driverName); + virBufferVSprintf(buf, " type='%s'", def->driverType); + if (def->cachemode) + virBufferVSprintf(buf, " cache='%s'", + virDomainDiskCacheTypeToString(def->cachemode)); + virBufferVSprintf(buf, "/>\n"); } if (def->src) {
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list