[libvirt] [PATCH] opennebula: Fix potential memory/mutex leak in state driver startup
by Matthias Bolte
In case of an error the domains hash and the driver mutex may leak.
* src/opennebula/one_driver.c: free/destroy domains hash and driver
mutex in error cases
---
src/opennebula/one_driver.c | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c
index 19a335c..f461ff6 100644
--- a/src/opennebula/one_driver.c
+++ b/src/opennebula/one_driver.c
@@ -617,23 +617,26 @@ static int oneStartup(int privileged ATTRIBUTE_UNUSED){
return -1;
}
+ c_oneStart();
+ oneDriverLock(one_driver);
+
if (virDomainObjListInit(&one_driver->domains) < 0) {
- virMutexDestroy(&one_driver->lock);
- VIR_FREE(one_driver);
- return -1;
+ goto error;
}
- c_oneStart();
- oneDriverLock(one_driver);
one_driver->nextid=1;
if ((one_driver->caps = oneCapsInit()) == NULL) {
- oneDriverUnlock(one_driver);
- VIR_FREE(one_driver);
- return -1;
+ virReportOOMError(NULL);
+ goto error;
}
oneDriverUnlock(one_driver);
return 0;
+
+error:
+ oneDriverUnlock(one_driver);
+ oneShutdown();
+ return -1;
}
static int oneShutdown(void){
--
1.6.0.4
15 years, 1 month
[libvirt] [PATCH] Add a Python example that lists active ESX domains
by Matthias Bolte
It also demonstrates how to use the libvirt.openAuth() method.
* examples/python/Makefile.am: add esxlist.py to EXTRA_DIST
* examples/python/README: add some notes about esxlist.py
* examples/python/esxlist.py: the new example
---
examples/python/Makefile.am | 2 +-
examples/python/README | 19 +++++
examples/python/esxlist.py | 155 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 175 insertions(+), 1 deletions(-)
create mode 100755 examples/python/esxlist.py
diff --git a/examples/python/Makefile.am b/examples/python/Makefile.am
index 0742226..dcd2c24 100644
--- a/examples/python/Makefile.am
+++ b/examples/python/Makefile.am
@@ -1,3 +1,3 @@
EXTRA_DIST= \
README \
- dominfo.py domrestore.py domsave.py domstart.py
+ dominfo.py domrestore.py domsave.py domstart.py esxlist.py
diff --git a/examples/python/README b/examples/python/README
index 02c5bfb..f4db76c 100644
--- a/examples/python/README
+++ b/examples/python/README
@@ -8,7 +8,26 @@ domstart.py - create a domU from an XML description if the domU isn't
running yet
domsave.py - save all running domU's into a directory
domrestore.py - restore domU's from their saved files in a directory
+esxlist.py - list active domains of an VMware ESX host and print some info.
+ also demonstrates how to use the libvirt.openAuth() method
The XML files in this directory are examples of the XML format that libvirt
expects, and will have to be adapted for your setup. They are only needed
for domstart.py
+
+
+Some additional notes for the esxlist.py example:
+
+You may see remote errors complaining about missing certificates:
+
+ Cannot access CA certificate '/usr/local/etc/pki/CA/cacert.pem': No such file
+ or directory
+
+This is expected, libvirt tries to find network and storage drivers for ESX,
+but those are not implemented yet (November 2009). While searching for this
+drivers, libvirt may try to start a local libvirtd instance, but fails because
+of the missing certificates. It'll warn about that:
+
+ Failed to find the network: Is the daemon running?
+
+This is also expected and can be ignored.
diff --git a/examples/python/esxlist.py b/examples/python/esxlist.py
new file mode 100755
index 0000000..a0602e8
--- /dev/null
+++ b/examples/python/esxlist.py
@@ -0,0 +1,155 @@
+#! /usr/bin/python
+# esxlist - list active domains of an ESX host and print some info.
+# also demonstrates how to use the libvirt.openAuth() method
+
+import libvirt
+import sys
+import os
+import libxml2
+import getpass
+
+
+def usage():
+ print "Usage: %s HOSTNAME" % sys.argv[0]
+ print " List active domains of HOSTNAME and print some info"
+
+
+# This is the callback method passed to libvirt.openAuth() (see below).
+#
+# The credentials argument is a list of credentials that libvirt (actually
+# the ESX driver) would like to request. An element of this list is itself a
+# list containing 5 items (4 inputs, 1 output):
+# - the credential type, e.g. libvirt.VIR_CRED_AUTHNAME
+# - a prompt to be displayed to the user
+# - a challenge, the ESX driver sets this to the hostname to allow automatic
+# distinction between requests for ESX and vCenter credentials
+# - a default result for the request
+# - a place to store the actual result for the request
+#
+# The user_data argument is the user data item of the auth argument (see below)
+# passed to libvirt.openAuth().
+def request_credentials(credentials, user_data):
+ for credential in credentials:
+ if credential[0] == libvirt.VIR_CRED_AUTHNAME:
+ # prompt the user to input a authname. display the provided message
+ credential[4] = raw_input(credential[1] + ": ")
+
+ # if the user just hits enter raw_input() returns an empty string.
+ # in this case return the default result through the last item of
+ # the list
+ if len(credential[4]) == 0:
+ credential[4] = credential[3]
+ elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT:
+ # use the getpass module to prompt the user to input a password.
+ # display the provided message and return the result through the
+ # last item of the list
+ credential[4] = getpass.getpass(credential[1] + ": ")
+ else:
+ return -1
+
+ return 0
+
+
+def print_section(title):
+ print "\n%s" % title
+ print "=" * 60
+
+
+def print_entry(key, value):
+ print "%-10s %-10s" % (key, value)
+
+
+def print_xml(key, ctx, path):
+ res = ctx.xpathEval(path)
+
+ if res is None or len(res) == 0:
+ value = "Unknown"
+ else:
+ value = res[0].content
+
+ print_entry(key, value)
+
+ return value
+
+
+if len(sys.argv) != 2:
+ usage()
+ sys.exit(2)
+
+
+hostname = sys.argv[1]
+
+# Connect to libvirt
+uri = "esx://%s/?no_verify=1" % hostname
+
+# The auth argument is a list that contains 3 items:
+# - a list of supported credential types
+# - a callable that takes 2 arguments
+# - user data that will be passed to the callable as second argument
+#
+# In this example the supported credential types are VIR_CRED_AUTHNAME and
+# VIR_CRED_NOECHOPROMPT, the callable is the unbound method request_credentials
+# (see above) and the user data is None.
+#
+# libvirt (actually the ESX driver) will call the callable to request
+# credentials in order to log into the ESX host. The callable would also be
+# called if the connection URI would reference a vCenter to request credentials
+# in order to log into the vCenter
+auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT],
+ request_credentials, None]
+conn = libvirt.openAuth(uri, auth, 0)
+
+if conn is None:
+ print "Failed to open connection to %s" % hostname
+ sys.exit(1)
+
+state_names = { libvirt.VIR_DOMAIN_RUNNING : "running",
+ libvirt.VIR_DOMAIN_BLOCKED : "idle",
+ libvirt.VIR_DOMAIN_PAUSED : "paused",
+ libvirt.VIR_DOMAIN_SHUTDOWN : "in shutdown",
+ libvirt.VIR_DOMAIN_SHUTOFF : "shut off",
+ libvirt.VIR_DOMAIN_CRASHED : "crashed",
+ libvirt.VIR_DOMAIN_NOSTATE : "no state" }
+
+for id in conn.listDomainsID():
+ domain = conn.lookupByID(id)
+ info = domain.info()
+
+ print_section("Domain " + domain.name())
+ print_entry("ID:", id)
+ print_entry("UUID:", domain.UUIDString())
+ print_entry("State:", state_names[info[0]])
+ print_entry("MaxMem:", info[1])
+ print_entry("UsedMem:", info[2])
+ print_entry("VCPUs:", info[3])
+
+ # Read some info from the XML desc
+ print_section("Devices of " + domain.name())
+
+ xmldesc = domain.XMLDesc(0)
+ doc = libxml2.parseDoc(xmldesc)
+ ctx = doc.xpathNewContext()
+ devs = ctx.xpathEval("/domain/devices/*")
+ first = True
+
+ for d in devs:
+ ctx.setContextNode(d)
+
+ if not first:
+ print "------------------------------------------------------------"
+ else:
+ first = False
+
+ print_entry("Device", d.name)
+
+ type = print_xml("Type:", ctx, "@type")
+
+ if type == "file":
+ print_xml("Source:", ctx, "source/@file")
+ print_xml("Target:", ctx, "target/@dev")
+ elif type == "block":
+ print_xml("Source:", ctx, "source/@dev")
+ print_xml("Target:", ctx, "target/@dev")
+ elif type == "bridge":
+ print_xml("Source:", ctx, "source/@bridge")
+ print_xml("MAC Addr:", ctx, "mac/@address")
--
1.6.0.4
15 years, 1 month
[libvirt] [PATCH v2 0/2] CPU flags capabilities and domain configuration
by Jiri Denemark
Hi,
These are two initial patches for CPU flags/masks support for libvirt.
The first patch contains changes to schemas and describes semantics of
new elements and attributes.
The second patch introduces internal API functions for XML parsing and
formating.
Version 2 changes:
- feature names moved to a 'name' attribute of 'feature' element
- 'cpu' element in guest capabilities renamed as 'cpuselection'
- topology attributes restricted to positiveInteger
- move 'cpu' element above 'os' element in domain configuration schema
- feature names restricted to [a-zA-Z0-9\-_]+
- feature names are not internally converted to lower case
Jiri Denemark (2):
XML schema for CPU flags
XML parsing/formating code for CPU flags
docs/schemas/capability.rng | 46 ++++++-
docs/schemas/domain.rng | 62 ++++++++
include/libvirt/virterror.h | 1 +
src/Makefile.am | 9 +-
src/conf/capabilities.c | 31 ++++-
src/conf/capabilities.h | 6 +
src/conf/cpu_conf.c | 331 +++++++++++++++++++++++++++++++++++++++++++
src/conf/cpu_conf.h | 110 ++++++++++++++
src/conf/domain_conf.c | 15 ++
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 8 +
src/util/virterror.c | 3 +
12 files changed, 620 insertions(+), 4 deletions(-)
create mode 100644 src/conf/cpu_conf.c
create mode 100644 src/conf/cpu_conf.h
15 years, 1 month
[libvirt] [PATCH 0/9] Several bug fixes for the Power Hypervisor driver
by Matthias Bolte
After the last large patch has been applied I reviewed the whole driver
code and found several bugs and issues. Most important memory leaks and
two potential infinite loops.
I've no Power Hypervisor at hand, so I can't test this changes with an
actual system. Eduardo could you test this patches to make sure they
don't break existing functionality?
Matthias
15 years, 1 month
[libvirt] 3 patches to solve bug 524280
by Daniel Veillard
Basically dnsmasq limits itself by default to 150 leases maximum.
Which means we may inflict an arbitrary limit in the number of domains
running on a given host
https://bugzilla.redhat.com/show_bug.cgi?id=524280
The patches do 3 things:
- first introduce IPv4 and IPv6 parsing routines, generally useful
this could be used to double check input in other places too
- then when a DHCP range is defined use those routines to parse
the start and end, do some cheking and keep the range size in the
structure
- last when exec'ing dnsmasq compute the sum of all dhcp ranges
and pass the max lease option
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
15 years, 1 month
[libvirt] [PATCH] qemu: Allow cpu pinning for all logical CPUs, not just physical
by Cole Robinson
This is what virsh already expects when printing output, and what
'man cpuset' claims to support.
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
src/qemu/qemu_driver.c | 23 +++++++++++++----------
1 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1f3a0e4..5463951 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1222,7 +1222,7 @@ qemudInitCpus(virConnectPtr conn,
const char *migrateFrom) {
#if HAVE_SCHED_GETAFFINITY
cpu_set_t mask;
- int i, maxcpu = QEMUD_CPUMASK_LEN;
+ int i, hostcpus, maxcpu = QEMUD_CPUMASK_LEN;
virNodeInfo nodeinfo;
if (nodeGetInfo(conn, &nodeinfo) < 0)
@@ -1230,8 +1230,9 @@ qemudInitCpus(virConnectPtr conn,
/* setaffinity fails if you set bits for CPUs which
* aren't present, so we have to limit ourselves */
- if (maxcpu > nodeinfo.cpus)
- maxcpu = nodeinfo.cpus;
+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
+ if (maxcpu > hostcpus)
+ maxcpu = hostcpus;
CPU_ZERO(&mask);
if (vm->def->cpumask) {
@@ -3339,7 +3340,7 @@ qemudDomainPinVcpu(virDomainPtr dom,
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
cpu_set_t mask;
- int i, maxcpu;
+ int i, maxcpu, hostcpus;
virNodeInfo nodeinfo;
int ret = -1;
@@ -3371,13 +3372,14 @@ qemudDomainPinVcpu(virDomainPtr dom,
if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
goto cleanup;
+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
maxcpu = maplen * 8;
- if (maxcpu > nodeinfo.cpus)
- maxcpu = nodeinfo.cpus;
+ if (maxcpu > hostcpus)
+ maxcpu = hostcpus;
CPU_ZERO(&mask);
for (i = 0 ; i < maxcpu ; i++) {
- if ((cpumap[i/8] >> (i % 8)) & 1)
+ if (VIR_CPU_USABLE(cpumap, maplen, 0, i))
CPU_SET(i, &mask);
}
@@ -3409,7 +3411,7 @@ qemudDomainGetVcpus(virDomainPtr dom,
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
virNodeInfo nodeinfo;
- int i, v, maxcpu;
+ int i, v, maxcpu, hostcpus;
int ret = -1;
qemuDriverLock(driver);
@@ -3434,9 +3436,10 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (nodeGetInfo(dom->conn, &nodeinfo) < 0)
goto cleanup;
+ hostcpus = VIR_NODEINFO_MAXCPUS(nodeinfo);
maxcpu = maplen * 8;
- if (maxcpu > nodeinfo.cpus)
- maxcpu = nodeinfo.cpus;
+ if (maxcpu > hostcpus)
+ maxcpu = hostcpus;
/* Clamp to actual number of vcpus */
if (maxinfo > vm->nvcpupids)
--
1.6.5.1
15 years, 1 month
[libvirt] [PATCH] Cleanup whitespace in docs
by Matthew Booth
This patch is the result of running the following command in the
docs direct
sed -i 's/\t/ /g; s/\s*$//' *.html.in
* docs/api.html.in docs/api_extension.html.in docs/apps.html.in
docs/archnetwork.html.in docs/archstorage.html.in docs/bugs.html.in
docs/drvlxc.html.in docs/drvone.html.in docs/drvqemu.html.in
docs/drvxen.html.in docs/formatdomain.html.in
docs/formatnetwork.html.in
docs/formatsecret.html.in docs/formatstorage.html.in
docs/hacking.html.in
docs/hvsupport.html.in docs/index.html.in docs/news.html.in
docs/relatedlinks.html.in docs/sitemap.html.in: convert tabs into
8 spaces
and remove trailing whitespace
docs/api.html.in | 6 +-
docs/api_extension.html.in | 14 +-
docs/apps.html.in | 92 ++++++------
docs/archnetwork.html.in | 26 ++--
docs/archstorage.html.in | 16 +-
docs/bugs.html.in | 34 ++--
docs/drvlxc.html.in | 80 +++++-----
docs/drvone.html.in | 14 +-
docs/drvqemu.html.in | 28 ++--
docs/drvxen.html.in | 38 +++---
docs/formatdomain.html.in | 376
++++++++++++++++++++++----------------------
docs/formatnetwork.html.in | 158 +++++++++---------
docs/formatsecret.html.in | 8 +-
docs/formatstorage.html.in | 208 ++++++++++++------------
docs/hacking.html.in | 108 +++++++-------
docs/hvsupport.html.in | 2 +-
docs/index.html.in | 36 ++--
docs/news.html.in | 94 ++++++------
docs/relatedlinks.html.in | 22 ++--
docs/sitemap.html.in | 16 +-
20 files changed, 688 insertions(+), 688 deletions(-)
Matt
--
Matthew Booth, RHCA, RHCSS
Red Hat Engineering, Virtualisation Team
M: +44 (0)7977 267231
GPG ID: D33C3490
GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
15 years, 1 month
[libvirt] [PATCH] Use virBuffer when constructing QEMU character device command line
by Matthew Booth
This patch updates qemudBuildCommandLineChrDevStr to use a virBuffer instead of
a char[]. This is slightly tidier, and it makes it cleaner to (ap|pre)pend the
output in other command lines.
* src/qemu/qemu_conf.c: Update qemudBuildCommandLineChrDevStr to use a virBuffer
---
src/qemu/qemu_conf.c | 97 +++++++++++++++++++++++--------------------------
1 files changed, 46 insertions(+), 51 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 40613dd..052ae98 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1409,83 +1409,66 @@ qemuBuildHostNetStr(virConnectPtr conn,
return 0;
}
-static int qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
- char *buf,
- int buflen)
+static void qemudBuildCommandLineChrDevStr(virDomainChrDefPtr dev,
+ virBufferPtr buf)
{
switch (dev->type) {
case VIR_DOMAIN_CHR_TYPE_NULL:
- if (virStrcpy(buf, "null", buflen) == NULL)
- return -1;
+ virBufferAddLit(buf, "null");
break;
case VIR_DOMAIN_CHR_TYPE_VC:
- if (virStrcpy(buf, "vc", buflen) == NULL)
- return -1;
+ virBufferAddLit(buf, "vc");
break;
case VIR_DOMAIN_CHR_TYPE_PTY:
- if (virStrcpy(buf, "pty", buflen) == NULL)
- return -1;
+ virBufferAddLit(buf, "pty");
break;
case VIR_DOMAIN_CHR_TYPE_DEV:
- if (snprintf(buf, buflen, "%s",
- dev->data.file.path) >= buflen)
- return -1;
+ virBufferStrcat(buf, dev->data.file.path, NULL);
break;
case VIR_DOMAIN_CHR_TYPE_FILE:
- if (snprintf(buf, buflen, "file:%s",
- dev->data.file.path) >= buflen)
- return -1;
+ virBufferVSprintf(buf, "file:%s", dev->data.file.path);
break;
case VIR_DOMAIN_CHR_TYPE_PIPE:
- if (snprintf(buf, buflen, "pipe:%s",
- dev->data.file.path) >= buflen)
- return -1;
+ virBufferVSprintf(buf, "pipe:%s", dev->data.file.path);
break;
case VIR_DOMAIN_CHR_TYPE_STDIO:
- if (virStrcpy(buf, "stdio", buflen) == NULL)
- return -1;
+ virBufferAddLit(buf, "stdio");
break;
case VIR_DOMAIN_CHR_TYPE_UDP:
- if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
- dev->data.udp.connectHost,
- dev->data.udp.connectService,
- dev->data.udp.bindHost,
- dev->data.udp.bindService) >= buflen)
- return -1;
+ virBufferVSprintf(buf, "udp:%s:%s@%s:%s",
+ dev->data.udp.connectHost,
+ dev->data.udp.connectService,
+ dev->data.udp.bindHost,
+ dev->data.udp.bindService);
break;
case VIR_DOMAIN_CHR_TYPE_TCP:
if (dev->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET) {
- if (snprintf(buf, buflen, "telnet:%s:%s%s",
- dev->data.tcp.host,
- dev->data.tcp.service,
- dev->data.tcp.listen ? ",server,nowait" : "") >= buflen)
- return -1;
+ virBufferVSprintf(buf, "telnet:%s:%s%s",
+ dev->data.tcp.host,
+ dev->data.tcp.service,
+ dev->data.tcp.listen ? ",server,nowait" : "");
} else {
- if (snprintf(buf, buflen, "tcp:%s:%s%s",
- dev->data.tcp.host,
- dev->data.tcp.service,
- dev->data.tcp.listen ? ",server,nowait" : "") >= buflen)
- return -1;
+ virBufferVSprintf(buf, "tcp:%s:%s%s",
+ dev->data.tcp.host,
+ dev->data.tcp.service,
+ dev->data.tcp.listen ? ",server,nowait" : "");
}
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
- if (snprintf(buf, buflen, "unix:%s%s",
- dev->data.nix.path,
- dev->data.nix.listen ? ",server,nowait" : "") >= buflen)
- return -1;
+ virBufferVSprintf(buf, "unix:%s%s",
+ dev->data.nix.path,
+ dev->data.nix.listen ? ",server,nowait" : "");
break;
}
-
- return 0;
}
#define QEMU_SERIAL_PARAM_ACCEPTED_CHARS \
@@ -1773,13 +1756,17 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("-nographic");
if (monitor_chr) {
- char buf[4096];
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
- if (qemudBuildCommandLineChrDevStr(monitor_chr, buf, sizeof(buf)) < 0)
+ qemudBuildCommandLineChrDevStr(monitor_chr, &buf);
+ const char *argStr = virBufferContentAndReset(&buf);
+ if (argStr == NULL)
goto error;
ADD_ARG_LIT("-monitor");
- ADD_ARG_LIT(buf);
+ ADD_ARG_LIT(argStr);
+
+ VIR_FREE(argStr);
}
if (def->localtime)
@@ -2059,14 +2046,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("none");
} else {
for (i = 0 ; i < def->nserials ; i++) {
- char buf[4096];
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
virDomainChrDefPtr serial = def->serials[i];
- if (qemudBuildCommandLineChrDevStr(serial, buf, sizeof(buf)) < 0)
+ qemudBuildCommandLineChrDevStr(serial, &buf);
+ const char *argStr = virBufferContentAndReset(&buf);
+ if (argStr == NULL)
goto error;
ADD_ARG_LIT("-serial");
- ADD_ARG_LIT(buf);
+ ADD_ARG_LIT(argStr);
+
+ VIR_FREE(argStr);
}
}
@@ -2075,14 +2066,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("none");
} else {
for (i = 0 ; i < def->nparallels ; i++) {
- char buf[4096];
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
virDomainChrDefPtr parallel = def->parallels[i];
- if (qemudBuildCommandLineChrDevStr(parallel, buf, sizeof(buf)) < 0)
+ qemudBuildCommandLineChrDevStr(parallel, &buf);
+ const char *argStr = virBufferContentAndReset(&buf);
+ if (argStr == NULL)
goto error;
ADD_ARG_LIT("-parallel");
- ADD_ARG_LIT(buf);
+ ADD_ARG_LIT(argStr);
+
+ VIR_FREE(argStr);
}
}
--
1.6.2.5
15 years, 1 month
[libvirt] [PATCH] Cleanup virBuffer usage in qemdBuildCommandLine
by Matthew Booth
Dan Berrangé pointed out that using virBufferError() is preferred to checking
virBufferContentAndReset() for NULL return. Also, this allows ADD_ARG_LIT to be
replaced with ADD_ARG, skipping an intermediate variable.
* src/qemu_qemu_conf.c: Cleanup usage of virBuffer in qemudBuildCommandLine
---
src/qemu/qemu_conf.c | 15 ++++-----------
1 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index f010f4a..4a278e3 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2182,7 +2182,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
for (i = 0 ; i < def->nchannels ; i++) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
- const char *argStr;
char id[16];
virDomainChrDefPtr channel = def->channels[i];
@@ -2199,24 +2198,18 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
qemudBuildCommandLineChrDevChardevStr(channel, id, &buf);
- argStr = virBufferContentAndReset(&buf);
- if (argStr == NULL)
+ if (virBufferError(&buf))
goto error;
ADD_ARG_LIT("-chardev");
- ADD_ARG_LIT(argStr);
-
- VIR_FREE(argStr);
+ ADD_ARG(virBufferContentAndReset(&buf));
qemudBuildCommandLineChrDevTargetStr(channel, id, &buf);
- argStr = virBufferContentAndReset(&buf);
- if (argStr == NULL)
+ if (virBufferError(&buf))
goto error;
ADD_ARG_LIT("-net");
- ADD_ARG_LIT(argStr);
-
- VIR_FREE(argStr);
+ ADD_ARG(virBufferContentAndReset(&buf));
}
}
--
1.6.2.5
15 years, 1 month
[libvirt] [PATCH] add sentinel attribute
by Paolo Bonzini
This patch adds a (macro-wrapped) sentinel attribute to functions
that take a NULL-terminated variable argument list. This is a nice
debugging aid.
* src/internal.h (ATTRIBUTE_SENTINEL): New.
* src/util/buf.c (virBufferStrcat): Use it.
* src/util/ebtables.c (ebtablesAddRemoveRule): Use it.
* src/util/iptables.c (iptableAddRemoveRule: Use it.
* src/util/qparams.h (new_qparam_set, append_qparams): Use it.
---
src/internal.h | 11 +++++++++++
src/util/buf.h | 3 ++-
src/util/ebtables.c | 2 +-
src/util/iptables.c | 2 +-
src/util/qparams.h | 6 ++++--
5 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/src/internal.h b/src/internal.h
index bd1cfe6..09c19ea 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -93,6 +93,17 @@
#endif
/**
+ * ATTRIBUTE_SENTINEL:
+ *
+ * Macro to check for NULL-terminated varargs lists
+ */
+#ifndef ATTRIBUTE_SENTINEL
+#if __GNUC_PREREQ (4, 0)
+#define ATTRIBUTE_SENTINEL __attribute__((__sentinel__))
+#endif
+#endif
+
+/**
* ATTRIBUTE_FMT_PRINTF
*
* Macro used to check printf like functions, if compiling
diff --git a/src/util/buf.h b/src/util/buf.h
index 7d31cb2..94ee8a3 100644
--- a/src/util/buf.h
+++ b/src/util/buf.h
@@ -41,7 +41,8 @@ void virBufferAdd(const virBufferPtr buf, const char *str, int len);
void virBufferAddChar(const virBufferPtr buf, char c);
void virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
ATTRIBUTE_FMT_PRINTF(2, 3);
-void virBufferStrcat(const virBufferPtr buf, ...);
+void virBufferStrcat(const virBufferPtr buf, ...)
+ ATTRIBUTE_SENTINEL;
void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str);
void virBufferURIEncodeString (const virBufferPtr buf, const char *str);
diff --git a/src/util/ebtables.c b/src/util/ebtables.c
index 60427d7..20f3342 100644
--- a/src/util/ebtables.c
+++ b/src/util/ebtables.c
@@ -175,7 +175,7 @@ ebtRulesNew(const char *table,
return NULL;
}
-static int
+static int ATTRIBUTE_SENTINEL
ebtablesAddRemoveRule(ebtRules *rules, int action, const char *arg, ...)
{
va_list args;
diff --git a/src/util/iptables.c b/src/util/iptables.c
index 4562800..284f3c0 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -382,7 +382,7 @@ iptRulesNew(const char *table,
return NULL;
}
-static int
+static int ATTRIBUTE_SENTINEL
iptablesAddRemoveRule(iptRules *rules, int action, const char *arg, ...)
{
va_list args;
diff --git a/src/util/qparams.h b/src/util/qparams.h
index 1a92048..a2f5aa2 100644
--- a/src/util/qparams.h
+++ b/src/util/qparams.h
@@ -38,10 +38,12 @@ struct qparam_set {
};
/* New parameter set. */
-extern struct qparam_set *new_qparam_set (int init_alloc, ...);
+extern struct qparam_set *new_qparam_set (int init_alloc, ...)
+ ATTRIBUTE_SENTINEL;
/* Appending parameters. */
-extern int append_qparams (struct qparam_set *ps, ...);
+extern int append_qparams (struct qparam_set *ps, ...)
+ ATTRIBUTE_SENTINEL;
extern int append_qparam (struct qparam_set *ps,
const char *name, const char *value);
--
1.6.2.5
15 years, 1 month