[libvirt] PATCH: 0/11: Fully modular drivers and optional dlopen support

The following series of patches clean up our internal modularization to remove unneccessary dependancies between source files, and make everything follow a consistent pattern of XXXX.h declaring stuff in XXXX.c. Later in the series is plays some games with the linker scripts, and finally makes all hypervisor drivers fully modular, and optionally dlopen'able. The 10'th patch in this series is a pre-requisite to enable us to merge David's host device patches, since it lets us avoid GPL/LGPL compat issues from DBus/HAL. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

This patch updates the storage drivers to make full use of virStorageSourceList and thus removes the now uneeded virStringList code. No change since last time, just re-diffed for new CVS. internal.h | 12 --- libvirt.c | 40 ------------ storage_backend_fs.c | 46 +++++++------- storage_backend_logical.c | 3 storage_conf.c | 150 +++++++++++++++++++++++++++------------------- storage_conf.h | 1 6 files changed, 120 insertions(+), 132 deletions(-) Daniel diff -r 32908ef883dc src/internal.h --- a/src/internal.h Wed Oct 29 11:26:37 2008 +0000 +++ b/src/internal.h Wed Oct 29 11:29:16 2008 +0000 @@ -371,18 +371,6 @@ int __virDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long bandwidth); virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags); -typedef struct _virStringList virStringList; - -struct _virStringList { - char *val; - int len; - struct _virStringList *next; -}; - -char *__virStringListJoin(const virStringList *list, const char *pre, - const char *post, const char *sep); -void __virStringListFree(virStringList *list); - /** * Domain Event Notification */ diff -r 32908ef883dc src/libvirt.c --- a/src/libvirt.c Wed Oct 29 11:26:37 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 11:29:16 2008 +0000 @@ -5305,46 +5305,6 @@ - -/* Not for public use. Combines the elements of a virStringList - * into a single string. - */ -char *__virStringListJoin(const virStringList *list, const char *pre, - const char *post, const char *sep) -{ - size_t pre_len = strlen(pre); - size_t sep_len = strlen(sep); - size_t len = pre_len + strlen(post); - const virStringList *p; - char *retval; - - for (p = list; p; p = p->next) - len += p->len + sep_len; - if (VIR_ALLOC_N(retval, len+1) < 0) - return NULL; - strcpy(retval, pre); - len = pre_len; - for (p = list; p; p = p->next) { - strcpy(retval + len, p->val); - len += p->len; - strcpy(retval + len, sep); - len += sep_len; - } - strcpy(retval + len, post); - - return retval; -} - - -void __virStringListFree(virStringList *list) -{ - while (list) { - virStringList *p = list->next; - VIR_FREE(list); - list = p; - } -} - /* * Domain Event Notification */ diff -r 32908ef883dc src/storage_backend_fs.c --- a/src/storage_backend_fs.c Wed Oct 29 11:26:37 2008 +0000 +++ b/src/storage_backend_fs.c Wed Oct 29 11:29:16 2008 +0000 @@ -295,7 +295,7 @@ #if WITH_STORAGE_FS struct _virNetfsDiscoverState { const char *host; - virStringList *list; + virStoragePoolSourceList list; }; typedef struct _virNetfsDiscoverState virNetfsDiscoverState; @@ -307,8 +307,8 @@ void *data) { virNetfsDiscoverState *state = data; - virStringList *newItem; const char *name, *path; + virStoragePoolSource *src; path = groups[0]; @@ -325,24 +325,17 @@ return -1; } - /* Append new XML desc to list */ - - if (VIR_ALLOC(newItem) != 0) { - virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("new xml desc")); + if (VIR_REALLOC_N(state->list.sources, state->list.nsources+1) < 0) { + virStorageReportError(conn, VIR_ERR_NO_MEMORY, NULL); return -1; } + memset(state->list.sources + state->list.nsources, 0, sizeof(*state->list.sources)); - if (asprintf(&newItem->val, - "<source><host name='%s'/><dir path='%s'/></source>", - state->host, path) <= 0) { - virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s", _("asprintf failed")); - VIR_FREE(newItem); + src = state->list.sources + state->list.nsources++; + if (!(src->host.name = strdup(state->host)) || + !(src->dir = strdup(path))) return -1; - } - - newItem->len = strlen(newItem->val); - newItem->next = state->list; - state->list = newItem; + src->format = VIR_STORAGE_POOL_NETFS_NFS; return 0; } @@ -368,10 +361,18 @@ }; xmlDocPtr doc = NULL; xmlXPathContextPtr xpath_ctxt = NULL; - virNetfsDiscoverState state = { .host = NULL, .list = NULL }; + virNetfsDiscoverState state = { + .host = NULL, + .list = { + .type = VIR_STORAGE_POOL_NETFS, + .nsources = 0, + .sources = NULL + } + }; const char *prog[] = { SHOWMOUNT, "--no-headers", "--exports", NULL, NULL }; int exitstatus; char *retval = NULL; + unsigned int i; doc = xmlReadDoc((const xmlChar *)srcSpec, "srcSpec.xml", NULL, XML_PARSE_NOENT | XML_PARSE_NONET | @@ -400,18 +401,21 @@ &state, &exitstatus) < 0) goto cleanup; - retval = __virStringListJoin(state.list, SOURCES_START_TAG, - SOURCES_END_TAG, "\n"); + retval = virStoragePoolSourceListFormat(conn, &state.list); if (retval == NULL) { virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("retval")); goto cleanup; } cleanup: + for (i = 0; i < state.list.nsources; i++) + virStoragePoolSourceFree(&state.list.sources[i]); + + VIR_FREE(state.list.sources); + VIR_FREE(state.host); + xmlFreeDoc(doc); xmlXPathFreeContext(xpath_ctxt); - VIR_FREE(state.host); - __virStringListFree(state.list); return retval; } diff -r 32908ef883dc src/storage_backend_logical.c --- a/src/storage_backend_logical.c Wed Oct 29 11:26:37 2008 +0000 +++ b/src/storage_backend_logical.c Wed Oct 29 11:29:16 2008 +0000 @@ -295,6 +295,7 @@ dev = &thisSource->devices[thisSource->ndevice]; thisSource->ndevice++; + thisSource->format = VIR_STORAGE_POOL_LOGICAL_LVM2; memset(dev, 0, sizeof(*dev)); dev->path = pvname; @@ -331,6 +332,8 @@ int i; memset(&sourceList, 0, sizeof(sourceList)); + sourceList.type = VIR_STORAGE_POOL_LOGICAL; + if (virStorageBackendRunProgRegex(conn, NULL, prog, 1, regexes, vars, virStorageBackendLogicalFindPoolSourcesFunc, &sourceList, &exitstatus) < 0) diff -r 32908ef883dc src/storage_conf.c --- a/src/storage_conf.c Wed Oct 29 11:26:37 2008 +0000 +++ b/src/storage_conf.c Wed Oct 29 11:29:16 2008 +0000 @@ -472,6 +472,68 @@ return NULL; } +static int +virStoragePoolSourceFormat(virConnectPtr conn, + virBufferPtr buf, + virStorageBackendPoolOptionsPtr options, + virStoragePoolSourcePtr src) +{ + int i, j; + + virBufferAddLit(buf," <source>\n"); + if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_HOST) && + src->host.name) + virBufferVSprintf(buf," <host name='%s'/>\n", src->host.name); + + if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE) && + src->ndevice) { + for (i = 0 ; i < src->ndevice ; i++) { + if (src->devices[i].nfreeExtent) { + virBufferVSprintf(buf," <device path='%s'>\n", + src->devices[i].path); + for (j = 0 ; j < src->devices[i].nfreeExtent ; j++) { + virBufferVSprintf(buf, " <freeExtent start='%llu' end='%llu'/>\n", + src->devices[i].freeExtents[j].start, + src->devices[i].freeExtents[j].end); + } + virBufferAddLit(buf," </device>\n"); + } + else + virBufferVSprintf(buf, " <device path='%s'/>\n", + src->devices[i].path); + } + } + if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DIR) && + src->dir) + virBufferVSprintf(buf," <dir path='%s'/>\n", src->dir); + if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_ADAPTER) && + src->adapter) + virBufferVSprintf(buf," <adapter name='%s'/>\n", src->adapter); + if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_NAME) && + src->name) + virBufferVSprintf(buf," <name>%s</name>\n", src->name); + + if (options->formatToString) { + const char *format = (options->formatToString)(src->format); + if (!format) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + _("unknown pool format number %d"), + src->format); + return -1; + } + virBufferVSprintf(buf," <format type='%s'/>\n", format); + } + + + if (src->authType == VIR_STORAGE_POOL_AUTH_CHAP) + virBufferVSprintf(buf," <auth type='chap' login='%s' passwd='%s'>\n", + src->auth.chap.login, + src->auth.chap.passwd); + virBufferAddLit(buf," </source>\n"); + + return 0; +} + char * virStoragePoolDefFormat(virConnectPtr conn, @@ -480,7 +542,6 @@ virBuffer buf = VIR_BUFFER_INITIALIZER; const char *type; char uuid[VIR_UUID_STRING_BUFLEN]; - int i, j; options = virStorageBackendPoolOptionsForType(def->type); if (options == NULL) @@ -505,56 +566,8 @@ virBufferVSprintf(&buf," <available>%llu</available>\n", def->available); - virBufferAddLit(&buf," <source>\n"); - if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_HOST) && - def->source.host.name) - virBufferVSprintf(&buf," <host name='%s'/>\n", def->source.host.name); - - if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DEVICE) && - def->source.ndevice) { - for (i = 0 ; i < def->source.ndevice ; i++) { - if (def->source.devices[i].nfreeExtent) { - virBufferVSprintf(&buf," <device path='%s'>\n", - def->source.devices[i].path); - for (j = 0 ; j < def->source.devices[i].nfreeExtent ; j++) { - virBufferVSprintf(&buf, " <freeExtent start='%llu' end='%llu'/>\n", - def->source.devices[i].freeExtents[j].start, - def->source.devices[i].freeExtents[j].end); - } - virBufferAddLit(&buf," </device>\n"); - } - else - virBufferVSprintf(&buf, " <device path='%s'/>\n", - def->source.devices[i].path); - } - } - if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_DIR) && - def->source.dir) - virBufferVSprintf(&buf," <dir path='%s'/>\n", def->source.dir); - if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_ADAPTER) && - def->source.adapter) - virBufferVSprintf(&buf," <adapter name='%s'/>\n", def->source.adapter); - if ((options->flags & VIR_STORAGE_BACKEND_POOL_SOURCE_NAME) && - def->source.name) - virBufferVSprintf(&buf," <name>%s</name>\n", def->source.name); - - if (options->formatToString) { - const char *format = (options->formatToString)(def->source.format); - if (!format) { - virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, - _("unknown pool format number %d"), - def->source.format); - goto cleanup; - } - virBufferVSprintf(&buf," <format type='%s'/>\n", format); - } - - - if (def->source.authType == VIR_STORAGE_POOL_AUTH_CHAP) - virBufferVSprintf(&buf," <auth type='chap' login='%s' passwd='%s'>\n", - def->source.auth.chap.login, - def->source.auth.chap.passwd); - virBufferAddLit(&buf," </source>\n"); + if (virStoragePoolSourceFormat(conn, &buf, options, &def->source) < 0) + goto cleanup; virBufferAddLit(&buf," <target>\n"); @@ -1271,22 +1284,41 @@ return 0; } -char *virStoragePoolSourceListFormat(virConnectPtr conn ATTRIBUTE_UNUSED, +char *virStoragePoolSourceListFormat(virConnectPtr conn, virStoragePoolSourceListPtr def) { - int i, j; + virStorageBackendPoolOptionsPtr options; virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *type; + int i; - virBufferAddLit(&buf, "<sources>"); + options = virStorageBackendPoolOptionsForType(def->type); + if (options == NULL) + return NULL; + + type = virStorageBackendToString(def->type); + if (!type) { + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("unexpected pool type")); + goto cleanup; + } + + virBufferAddLit(&buf, "<sources>\n"); for (i = 0; i < def->nsources; i++) { - virBufferVSprintf(&buf, "<source><name>%s</name>", def->sources[i].name); - for (j = 0; j < def->sources[i].ndevice; j++) - virBufferVSprintf(&buf, "<device path='%s'/>", def->sources[i].devices[j].path); - virBufferAddLit(&buf, "</source>"); + virStoragePoolSourceFormat(conn, &buf, options, &def->sources[i]); } - virBufferAddLit(&buf, "</sources>"); + virBufferAddLit(&buf, "</sources>\n"); + + if (virBufferError(&buf)) + goto no_memory; return virBufferContentAndReset(&buf); + + no_memory: + virStorageReportError(conn, VIR_ERR_NO_MEMORY, NULL); + cleanup: + free(virBufferContentAndReset(&buf)); + return NULL; } diff -r 32908ef883dc src/storage_conf.h --- a/src/storage_conf.h Wed Oct 29 11:26:37 2008 +0000 +++ b/src/storage_conf.h Wed Oct 29 11:29:16 2008 +0000 @@ -252,6 +252,7 @@ typedef struct _virStoragePoolSourceList virStoragePoolSourceList; typedef virStoragePoolSourceList *virStoragePoolSourceListPtr; struct _virStoragePoolSourceList { + int type; unsigned int nsources; virStoragePoolSourcePtr sources; }; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:35:24PM +0000, Daniel P. Berrange wrote:
This patch updates the storage drivers to make full use of virStorageSourceList and thus removes the now uneeded virStringList code. No change since last time, just re-diffed for new CVS.
No problem, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

After Daniel's feedback that adding src/virterror.h is confusing, I've re-done the patch to instead add virterror_internal.h, making it clear that these function prototypes are related to virterror.c, but internal use only. That patch is basically moving them out of src/internal.h In addition it removes the leading __ prefix from virRaiseError since this symbol was never exported fromthe library. The diff is mis-leading - most of this is just the s/__// change. b/src/virterror_internal.h | 56 ++++++++++++++++++++++++++++++++ src/Makefile.am | 4 +- src/conf.c | 8 ++-- src/domain_conf.c | 5 +- src/hash.c | 17 +++++---- src/internal.h | 24 -------------- src/libvirt.c | 44 ++++++++++++------------- src/lxc_conf.c | 1 src/lxc_conf.h | 2 - src/lxc_container.c | 1 src/lxc_controller.c | 2 - src/lxc_driver.c | 2 - src/network_conf.c | 5 +- src/network_driver.c | 3 + src/nodeinfo.c | 16 ++++----- src/openvz_conf.c | 1 src/openvz_conf.h | 2 - src/openvz_driver.c | 2 - src/proxy_internal.c | 5 +- src/qemu_conf.c | 1 src/qemu_conf.h | 2 - src/qemu_driver.c | 1 src/qparams.c | 3 + src/remote_internal.c | 72 +++++++++++++++++++++--------------------- src/sexpr.c | 4 +- src/stats_linux.c | 6 +-- src/storage_backend.c | 2 - src/storage_backend_disk.c | 2 - src/storage_backend_fs.c | 2 - src/storage_backend_iscsi.c | 2 - src/storage_backend_logical.c | 2 - src/storage_conf.c | 2 - src/storage_conf.h | 2 - src/storage_driver.c | 2 - src/test.c | 4 +- src/util.c | 4 +- src/virterror.c | 57 ++++++++++++++++----------------- src/xen_internal.c | 25 +++++++------- src/xen_unified.c | 4 +- src/xend_internal.c | 3 + src/xm_internal.c | 3 + src/xml.c | 5 +- src/xmlrpc.c | 6 +-- src/xs_internal.c | 4 +- 44 files changed, 231 insertions(+), 189 deletions(-) Daniel diff -r 786626684900 src/Makefile.am --- a/src/Makefile.am Wed Oct 29 15:23:00 2008 +0000 +++ b/src/Makefile.am Wed Oct 29 20:09:48 2008 +0000 @@ -50,7 +50,7 @@ stats_linux.c stats_linux.h \ uuid.c uuid.h \ util.c util.h \ - virterror.c \ + virterror.c virterror_internal.h \ xml.c xml.h # Domain driver generic impl APIs @@ -149,7 +149,7 @@ driver.h \ hash.c hash.h \ internal.h \ - libvirt.c \ + libvirt.c libvirt_internal.h \ $(GENERIC_LIB_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ $(NETWORK_CONF_SOURCES) \ diff -r 786626684900 src/conf.c --- a/src/conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -18,7 +18,7 @@ #include <sys/stat.h> #include <fcntl.h> -#include "internal.h" +#include "virterror_internal.h" #include "buf.h" #include "conf.h" #include "util.h" @@ -96,13 +96,13 @@ /* Construct the string 'filename:line: info' if we have that. */ if (ctxt && ctxt->filename) { - __virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, + virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, info, ctxt->filename, NULL, ctxt->line, 0, "%s:%d: %s", ctxt->filename, ctxt->line, info); } else { - format = __virErrorMsg(error, info); - __virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, + format = virErrorMsg(error, info); + virRaiseError(NULL, NULL, NULL, VIR_FROM_CONF, error, VIR_ERR_ERROR, info, NULL, NULL, ctxt ? ctxt->line : 0, 0, format, info); diff -r 786626684900 src/domain_conf.c --- a/src/domain_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/domain_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -29,8 +29,7 @@ #include <fcntl.h> #include <dirent.h> -#include "internal.h" - +#include "virterror_internal.h" #include "domain_conf.h" #include "memory.h" #include "verify.h" @@ -142,7 +141,7 @@ "pci") #define virDomainReportError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms, diff -r 786626684900 src/hash.c --- a/src/hash.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/hash.c Wed Oct 29 20:09:48 2008 +0000 @@ -23,7 +23,8 @@ #include <string.h> #include <stdlib.h> #include <libxml/threads.h> -#include "internal.h" + +#include "virterror_internal.h" #include "hash.h" #include "memory.h" @@ -32,7 +33,7 @@ /* #define DEBUG_GROW */ #define virHashError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) /* @@ -732,8 +733,8 @@ virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName); virResetError(&conn->err); - if (__lastErr.conn == conn) - __lastErr.conn = NULL; + if (virLastErr.conn == conn) + virLastErr.conn = NULL; VIR_FREE(conn->name); @@ -862,8 +863,8 @@ if (conn->err.dom == domain) conn->err.dom = NULL; - if (__lastErr.dom == domain) - __lastErr.dom = NULL; + if (virLastErr.dom == domain) + virLastErr.dom = NULL; domain->magic = -1; domain->id = -1; VIR_FREE(domain->name); @@ -998,8 +999,8 @@ if (conn->err.net == network) conn->err.net = NULL; - if (__lastErr.net == network) - __lastErr.net = NULL; + if (virLastErr.net == network) + virLastErr.net = NULL; network->magic = -1; VIR_FREE(network->name); diff -r 786626684900 src/internal.h --- a/src/internal.h Wed Oct 29 15:23:00 2008 +0000 +++ b/src/internal.h Wed Oct 29 20:09:48 2008 +0000 @@ -295,30 +295,6 @@ }; -/************************************************************************ - * * - * API for error handling * - * * - ************************************************************************/ -extern virError __lastErr; -void __virRaiseError(virConnectPtr conn, - virDomainPtr dom, - virNetworkPtr net, - int domain, - int code, - virErrorLevel level, - const char *str1, - const char *str2, - const char *str3, - int int1, int int2, const char *msg, ...) - ATTRIBUTE_FORMAT(printf, 12, 13); -const char *__virErrorMsg(virErrorNumber error, const char *info); -void __virReportErrorHelper(virConnectPtr conn, int domcode, int errcode, - const char *filename ATTRIBUTE_UNUSED, - const char *funcname ATTRIBUTE_UNUSED, - long long linenr ATTRIBUTE_UNUSED, - const char *fmt, ...) - ATTRIBUTE_FORMAT(printf, 7, 8); /************************************************************************ * * diff -r 786626684900 src/libvirt.c --- a/src/libvirt.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 20:09:48 2008 +0000 @@ -31,7 +31,7 @@ #include <winsock2.h> #endif -#include "internal.h" +#include "virterror_internal.h" #include "driver.h" #include "uuid.h" @@ -325,9 +325,9 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); - __virRaiseError(conn, NULL, NULL, VIR_FROM_NONE, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + errmsg = virErrorMsg(error, info); + virRaiseError(conn, NULL, NULL, VIR_FROM_NONE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -346,9 +346,9 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); - __virRaiseError(conn, NULL, NULL, VIR_FROM_NONE, error, VIR_ERR_WARNING, - errmsg, info, NULL, 0, 0, errmsg, info); + errmsg = virErrorMsg(error, info); + virRaiseError(conn, NULL, NULL, VIR_FROM_NONE, error, VIR_ERR_WARNING, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -369,12 +369,12 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); + errmsg = virErrorMsg(error, info); if (error != VIR_ERR_INVALID_DOMAIN) { conn = domain->conn; } - __virRaiseError(conn, domain, NULL, VIR_FROM_DOM, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + virRaiseError(conn, domain, NULL, VIR_FROM_DOM, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -395,12 +395,12 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); + errmsg = virErrorMsg(error, info); if (error != VIR_ERR_INVALID_NETWORK) { conn = network->conn; } - __virRaiseError(conn, NULL, network, VIR_FROM_NET, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + virRaiseError(conn, NULL, network, VIR_FROM_NET, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -421,12 +421,12 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); + errmsg = virErrorMsg(error, info); if (error != VIR_ERR_INVALID_STORAGE_POOL) conn = pool->conn; - __virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -447,12 +447,12 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); + errmsg = virErrorMsg(error, info); if (error != VIR_ERR_INVALID_STORAGE_VOL) conn = vol->conn; - __virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR, - errmsg, info, NULL, 0, 0, errmsg, info); + virRaiseError(conn, NULL, NULL, VIR_FROM_STORAGE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); } /** @@ -855,13 +855,13 @@ /* If no global error was set, copy any error set in the connection object we're about to dispose of */ - if (__lastErr.code == VIR_ERR_OK) { - memcpy(&__lastErr, &ret->err, sizeof(ret->err)); + if (virLastErr.code == VIR_ERR_OK) { + memcpy(&virLastErr, &ret->err, sizeof(ret->err)); memset(&ret->err, 0, sizeof(ret->err)); } /* Still no error set, then raise a generic error */ - if (__lastErr.code == VIR_ERR_OK) + if (virLastErr.code == VIR_ERR_OK) virLibConnError (NULL, VIR_ERR_INTERNAL_ERROR, _("unable to open connection")); diff -r 786626684900 src/lxc_conf.c --- a/src/lxc_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/lxc_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -27,6 +27,7 @@ #include <sys/utsname.h> +#include "virterror_internal.h" #include "lxc_conf.h" /* Functions */ diff -r 786626684900 src/lxc_conf.h --- a/src/lxc_conf.h Wed Oct 29 15:23:00 2008 +0000 +++ b/src/lxc_conf.h Wed Oct 29 20:09:48 2008 +0000 @@ -50,7 +50,7 @@ virCapsPtr lxcCapsInit(void); #define lxcError(conn, dom, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_LXC, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_LXC, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) #endif /* LXC_CONF_H */ diff -r 786626684900 src/lxc_container.c --- a/src/lxc_container.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/lxc_container.c Wed Oct 29 20:09:48 2008 +0000 @@ -41,6 +41,7 @@ /* For MS_MOVE */ #include <linux/fs.h> +#include "virterror_internal.h" #include "lxc_container.h" #include "util.h" #include "memory.h" diff -r 786626684900 src/lxc_controller.c --- a/src/lxc_controller.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/lxc_controller.c Wed Oct 29 20:09:48 2008 +0000 @@ -34,7 +34,7 @@ #include <signal.h> #include <getopt.h> -#include "internal.h" +#include "virterror_internal.h" #include "util.h" #include "lxc_conf.h" diff -r 786626684900 src/lxc_driver.c --- a/src/lxc_driver.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/lxc_driver.c Wed Oct 29 20:09:48 2008 +0000 @@ -35,7 +35,7 @@ #include <unistd.h> #include <wait.h> -#include "internal.h" +#include "virterror_internal.h" #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" diff -r 786626684900 src/network_conf.c --- a/src/network_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/network_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -33,8 +33,7 @@ #include <string.h> #include <dirent.h> -#include "internal.h" - +#include "virterror_internal.h" #include "network_conf.h" #include "memory.h" #include "xml.h" @@ -50,7 +49,7 @@ "none", "nat", "route" ) #define virNetworkReportError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_NETWORK, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_NETWORK, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets, diff -r 786626684900 src/network_driver.c --- a/src/network_driver.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/network_driver.c Wed Oct 29 20:09:48 2008 +0000 @@ -44,6 +44,7 @@ #include <sys/wait.h> #include <sys/ioctl.h> +#include "virterror_internal.h" #include "network_driver.h" #include "network_conf.h" #include "driver.h" @@ -73,7 +74,7 @@ #define networkLog(level, msg...) fprintf(stderr, msg) #define networkReportError(conn, dom, net, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) diff -r 786626684900 src/nodeinfo.c --- a/src/nodeinfo.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/nodeinfo.c Wed Oct 29 20:09:48 2008 +0000 @@ -33,7 +33,7 @@ #include <sys/utsname.h> #endif -#include "internal.h" +#include "virterror_internal.h" #include "nodeinfo.h" #include "physmem.h" #include "util.h" @@ -63,7 +63,7 @@ while (*buf && c_isspace(*buf)) buf++; if (*buf != ':') { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "parsing cpuinfo processor"); return -1; @@ -76,7 +76,7 @@ while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "parsing cpuinfo cpu MHz"); return -1; @@ -92,7 +92,7 @@ while (*buf && c_isspace(*buf)) buf++; if (*buf != ':' || !buf[1]) { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "parsing cpuinfo cpu cores %c", *buf); return -1; @@ -105,7 +105,7 @@ } if (!nodeinfo->cpus) { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "no cpus found"); return -1; @@ -129,7 +129,7 @@ struct utsname info; if (uname(&info) < 0) { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "cannot extract machine type %s", strerror(errno)); return -1; @@ -148,7 +148,7 @@ int ret; FILE *cpuinfo = fopen(CPUINFO_PATH, "r"); if (!cpuinfo) { - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "cannot open %s %s", CPUINFO_PATH, strerror(errno)); return -1; @@ -165,7 +165,7 @@ } #else /* XXX Solaris will need an impl later if they port QEMU driver */ - __virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, + virRaiseError(conn, NULL, NULL, 0, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s:%s not implemented on this platform\n", __FILE__, __FUNCTION__); return -1; diff -r 786626684900 src/openvz_conf.c --- a/src/openvz_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/openvz_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -43,6 +43,7 @@ #include <sys/utsname.h> #include <sys/wait.h> +#include "virterror_internal.h" #include "openvz_conf.h" #include "uuid.h" #include "buf.h" diff -r 786626684900 src/openvz_conf.h --- a/src/openvz_conf.h Wed Oct 29 15:23:00 2008 +0000 +++ b/src/openvz_conf.h Wed Oct 29 20:09:48 2008 +0000 @@ -42,7 +42,7 @@ fprintf(stderr, "\n"); } #define openvzError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_OPENVZ, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_OPENVZ, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) diff -r 786626684900 src/openvz_driver.c --- a/src/openvz_driver.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/openvz_driver.c Wed Oct 29 20:09:48 2008 +0000 @@ -47,7 +47,7 @@ #include <stdio.h> #include <sys/wait.h> -#include "internal.h" +#include "virterror_internal.h" #include "openvz_driver.h" #include "event.h" #include "buf.h" diff -r 786626684900 src/proxy_internal.c --- a/src/proxy_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/proxy_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -21,7 +21,8 @@ #include <sys/un.h> #include <sys/wait.h> #include <string.h> -#include "internal.h" + +#include "virterror_internal.h" #include "driver.h" #include "proxy_internal.h" #include "util.h" @@ -93,7 +94,7 @@ ************************************************************************/ #define virProxyError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_PROXY, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_PROXY, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) /************************************************************************ diff -r 786626684900 src/qemu_conf.c --- a/src/qemu_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/qemu_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -40,6 +40,7 @@ #include <numa.h> #endif +#include "virterror_internal.h" #include "qemu_conf.h" #include "uuid.h" #include "buf.h" diff -r 786626684900 src/qemu_conf.h --- a/src/qemu_conf.h Wed Oct 29 15:23:00 2008 +0000 +++ b/src/qemu_conf.h Wed Oct 29 20:09:48 2008 +0000 @@ -70,7 +70,7 @@ #define qemudReportError(conn, dom, net, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_QEMU, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) diff -r 786626684900 src/qemu_driver.c --- a/src/qemu_driver.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/qemu_driver.c Wed Oct 29 20:09:48 2008 +0000 @@ -52,6 +52,7 @@ #include <sched.h> #endif +#include "virterror_internal.h" #include "qemu_driver.h" #include "qemu_conf.h" #include "c-ctype.h" diff -r 786626684900 src/qparams.c --- a/src/qparams.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/qparams.c Wed Oct 29 20:09:48 2008 +0000 @@ -26,12 +26,13 @@ #include <stdlib.h> #include <stdarg.h> +#include "virterror_internal.h" #include "buf.h" #include "memory.h" #include "qparams.h" #define qparam_report_oom(void) \ - __virReportErrorHelper(NULL, VIR_FROM_NONE, VIR_ERR_NO_MEMORY, \ + virReportErrorHelper(NULL, VIR_FROM_NONE, VIR_ERR_NO_MEMORY, \ __FILE__, __FUNCTION__, __LINE__, NULL) struct qparam_set * diff -r 786626684900 src/remote_internal.c --- a/src/remote_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/remote_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -73,7 +73,7 @@ # define AI_ADDRCONFIG 0 #endif -#include "internal.h" +#include "virterror_internal.h" #include "driver.h" #include "buf.h" #include "qparams.h" @@ -3675,7 +3675,7 @@ } else if (STRCASEEQ(authtype, "polkit")) { want = REMOTE_AUTH_POLKIT; } else { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown authentication type %s"), authtype); @@ -3686,7 +3686,7 @@ type = want; } if (type == REMOTE_AUTH_NONE) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("requested authentication type %s rejected"), authtype); @@ -3726,7 +3726,7 @@ break; default: - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unsupported authentication type %d"), @@ -3756,7 +3756,7 @@ host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV)) != 0) { - __virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_NO_MEMORY, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("Cannot resolve address %d: %s"), @@ -3765,7 +3765,7 @@ } if (VIR_ALLOC_N(addr, strlen(host) + 1 + strlen(port) + 1) < 0) { - __virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_NO_MEMORY, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "address"); @@ -3975,7 +3975,7 @@ /* Sets up the SASL library as a whole */ err = sasl_client_init(NULL); if (err != SASL_OK) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("failed to initialize SASL library: %d (%s)"), err, sasl_errstring(err, NULL, NULL)); @@ -3985,7 +3985,7 @@ /* Get local address in form IPADDR:PORT */ salen = sizeof(sa); if (getsockname(priv->sock, (struct sockaddr*)&sa, &salen) < 0) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("failed to get sock address %d (%s)"), errno, strerror(errno)); @@ -3997,7 +3997,7 @@ /* Get remote address in form IPADDR:PORT */ salen = sizeof(sa); if (getpeername(priv->sock, (struct sockaddr*)&sa, &salen) < 0) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("failed to get peer address %d (%s)"), errno, strerror(errno)); @@ -4023,7 +4023,7 @@ &saslconn); if (err != SASL_OK) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("Failed to create SASL client context: %d (%s)"), err, sasl_errstring(err, NULL, NULL)); @@ -4036,7 +4036,7 @@ cipher = gnutls_cipher_get(priv->session); if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", _("invalid cipher size for TLS session")); goto cleanup; @@ -4046,7 +4046,7 @@ DEBUG("Setting external SSF %d", ssf); err = sasl_setprop(saslconn, SASL_SSF_EXTERNAL, &ssf); if (err != SASL_OK) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("cannot set external SSF %d (%s)"), err, sasl_errstring(err, NULL, NULL)); @@ -4065,7 +4065,7 @@ err = sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops); if (err != SASL_OK) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_INTERNAL_ERROR, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("cannot set security props %d (%s)"), err, sasl_errstring(err, NULL, NULL)); @@ -4083,7 +4083,7 @@ mechlist = iret.mechlist; if (wantmech) { if (strstr(mechlist, wantmech) == NULL) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("SASL mechanism %s not supported by server"), @@ -4103,7 +4103,7 @@ &clientoutlen, &mech); if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("Failed to start SASL negotiation: %d (%s)"), err, sasl_errdetail(saslconn)); @@ -4120,7 +4120,7 @@ } if ((ncred = remoteAuthMakeCredentials(interact, &cred)) < 0) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", _("Failed to make auth credentials")); @@ -4137,7 +4137,7 @@ } else { msg = "No authentication callback available"; } - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", msg); goto cleanup; @@ -4145,7 +4145,7 @@ VIR_FREE(iret.mechlist); if (clientoutlen > REMOTE_AUTH_SASL_DATA_MAX) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("SASL negotiation data too long: %d bytes"), clientoutlen); @@ -4185,7 +4185,7 @@ &clientout, &clientoutlen); if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("Failed SASL step: %d (%s)"), err, sasl_errdetail(saslconn)); @@ -4199,7 +4199,7 @@ cred = NULL; } if ((ncred = remoteAuthMakeCredentials(interact, &cred)) < 0) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", _("Failed to make auth credentials")); goto cleanup; @@ -4214,7 +4214,7 @@ } else { msg = "No authentication callback available"; } - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", msg); goto cleanup; @@ -4262,7 +4262,7 @@ if (!priv->uses_tls) { err = sasl_getprop(saslconn, SASL_SSF, &val); if (err != SASL_OK) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("cannot query SASL ssf on connection %d (%s)"), err, sasl_errstring(err, NULL, NULL)); @@ -4271,7 +4271,7 @@ ssf = *(const int *)val; DEBUG("SASL SSF value %d", ssf); if (ssf < 56) { /* 56 == DES level, good for Kerberos */ - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("negotiation SSF %d was not strong enough"), ssf); goto cleanup; @@ -4325,7 +4325,7 @@ if (allowcb) { /* Run the authentication callback */ if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) { - __virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (in_open ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_AUTH_FAILED, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, "%s", _("Failed to collect auth credentials")); return -1; @@ -4509,7 +4509,7 @@ /* Check program, version, etc. are what we expect. */ if (hdr.prog != REMOTE_PROGRAM) { - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown program (received %x, expected %x)"), @@ -4517,7 +4517,7 @@ return -1; } if (hdr.vers != REMOTE_PROTOCOL_VERSION) { - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown protocol version (received %x, expected %x)"), @@ -4540,7 +4540,7 @@ goto retry_read; } if (hdr.proc != proc_nr) { - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown procedure (received %x, expected %x)"), @@ -4548,7 +4548,7 @@ return -1; } if (hdr.direction != REMOTE_REPLY) { - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown direction (received %x, expected %x)"), @@ -4556,7 +4556,7 @@ return -1; } if (hdr.serial != serial) { - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown serial (received %x, expected %x)"), hdr.serial, serial); @@ -4599,7 +4599,7 @@ return -1; default: - __virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, + virRaiseError (flags & REMOTE_CALL_IN_OPEN ? NULL : conn, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, VIR_ERR_ERROR, NULL, NULL, NULL, 0, 0, _("unknown status (received %x)"), hdr.status); @@ -4809,8 +4809,8 @@ { const char *errmsg; - errmsg = __virErrorMsg (code, info); - __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE, + errmsg = virErrorMsg (code, info); + virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE, code, VIR_ERR_ERROR, errmsg, info, NULL, 0, 0, errmsg, info); } @@ -4832,8 +4832,8 @@ errorMessage[0] = '\0'; } - errmsg = __virErrorMsg (code, errorMessage); - __virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE, + errmsg = virErrorMsg (code, errorMessage); + virRaiseError (conn, NULL, NULL, VIR_FROM_REMOTE, code, VIR_ERR_ERROR, errmsg, errorMessage, NULL, -1, -1, errmsg, errorMessage); @@ -4850,7 +4850,7 @@ dom = err->dom ? get_nonnull_domain (conn, *err->dom) : NULL; net = err->net ? get_nonnull_network (conn, *err->net) : NULL; - __virRaiseError (conn, dom, net, + virRaiseError (conn, dom, net, err->domain, err->code, err->level, err->str1 ? *err->str1 : NULL, err->str2 ? *err->str2 : NULL, @@ -4866,7 +4866,7 @@ /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, - * but if they do then virterror has been set. + * but if they do then virterror_internal.has been set. */ static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain) diff -r 786626684900 src/sexpr.c --- a/src/sexpr.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/sexpr.c Wed Oct 29 20:09:48 2008 +0000 @@ -18,13 +18,13 @@ #include "c-ctype.h" #include <errno.h> -#include "internal.h" +#include "virterror_internal.h" #include "sexpr.h" #include "util.h" #include "memory.h" #define virSexprError(code, fmt...) \ - __virReportErrorHelper(NULL, VIR_FROM_SEXPR, code, __FILE__, \ + virReportErrorHelper(NULL, VIR_FROM_SEXPR, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) /** diff -r 786626684900 src/stats_linux.c --- a/src/stats_linux.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/stats_linux.c Wed Oct 29 20:09:48 2008 +0000 @@ -24,7 +24,7 @@ #include <xs.h> #endif -#include "internal.h" +#include "virterror_internal.h" #include "util.h" #include "xen_unified.h" #include "stats_linux.h" @@ -48,13 +48,13 @@ char fullinfo[1000]; const char *errmsg; - errmsg = __virErrorMsg(error, info); + errmsg = virErrorMsg(error, info); if (func != NULL) { snprintf(fullinfo, sizeof (fullinfo) - 1, "%s: %s", func, info); fullinfo[sizeof (fullinfo) - 1] = 0; info = fullinfo; } - __virRaiseError(conn, NULL, NULL, VIR_FROM_STATS_LINUX, error, + virRaiseError(conn, NULL, NULL, VIR_FROM_STATS_LINUX, error, VIR_ERR_ERROR, errmsg, info, NULL, value, 0, errmsg, info, value); diff -r 786626684900 src/storage_backend.c --- a/src/storage_backend.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_backend.c Wed Oct 29 20:09:48 2008 +0000 @@ -41,7 +41,7 @@ #include <selinux/selinux.h> #endif -#include "internal.h" +#include "virterror_internal.h" #include "util.h" #include "memory.h" diff -r 786626684900 src/storage_backend_disk.c --- a/src/storage_backend_disk.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_backend_disk.c Wed Oct 29 20:09:48 2008 +0000 @@ -25,7 +25,7 @@ #include <string.h> #include <unistd.h> -#include "internal.h" +#include "virterror_internal.h" #include "storage_backend_disk.h" #include "util.h" #include "memory.h" diff -r 786626684900 src/storage_backend_fs.c --- a/src/storage_backend_fs.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_backend_fs.c Wed Oct 29 20:09:48 2008 +0000 @@ -40,7 +40,7 @@ #include <libxml/tree.h> #include <libxml/xpath.h> -#include "internal.h" +#include "virterror_internal.h" #include "storage_backend_fs.h" #include "storage_conf.h" #include "util.h" diff -r 786626684900 src/storage_backend_iscsi.c --- a/src/storage_backend_iscsi.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_backend_iscsi.c Wed Oct 29 20:09:48 2008 +0000 @@ -34,7 +34,7 @@ #include <unistd.h> #include <dirent.h> -#include "internal.h" +#include "virterror_internal.h" #include "storage_backend_iscsi.h" #include "util.h" #include "memory.h" diff -r 786626684900 src/storage_backend_logical.c --- a/src/storage_backend_logical.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_backend_logical.c Wed Oct 29 20:09:48 2008 +0000 @@ -31,7 +31,7 @@ #include <unistd.h> #include <fcntl.h> -#include "internal.h" +#include "virterror_internal.h" #include "storage_backend_logical.h" #include "storage_conf.h" #include "util.h" diff -r 786626684900 src/storage_conf.c --- a/src/storage_conf.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_conf.c Wed Oct 29 20:09:48 2008 +0000 @@ -38,7 +38,7 @@ #include <fcntl.h> #include <string.h> -#include "internal.h" +#include "virterror_internal.h" #include "storage_conf.h" #include "storage_backend.h" #include "xml.h" diff -r 786626684900 src/storage_conf.h --- a/src/storage_conf.h Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_conf.h Wed Oct 29 20:09:48 2008 +0000 @@ -262,7 +262,7 @@ } #define virStorageReportError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_STORAGE, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_STORAGE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) int virStoragePoolLoadAllConfigs(virConnectPtr conn, diff -r 786626684900 src/storage_driver.c --- a/src/storage_driver.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/storage_driver.c Wed Oct 29 20:09:48 2008 +0000 @@ -32,7 +32,7 @@ #include <errno.h> #include <string.h> -#include "internal.h" +#include "virterror_internal.h" #include "driver.h" #include "util.h" #include "storage_driver.h" diff -r 786626684900 src/test.c --- a/src/test.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/test.c Wed Oct 29 20:09:48 2008 +0000 @@ -30,6 +30,8 @@ #include <unistd.h> #include <sys/stat.h> + +#include "virterror_internal.h" #include "test.h" #include "buf.h" #include "util.h" @@ -113,7 +115,7 @@ #define testError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) static virCapsPtr diff -r 786626684900 src/util.c --- a/src/util.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/util.c Wed Oct 29 20:09:48 2008 +0000 @@ -47,7 +47,7 @@ #include <paths.h> #endif -#include "internal.h" +#include "virterror_internal.h" #include "event.h" #include "buf.h" #include "util.h" @@ -67,7 +67,7 @@ #ifndef PROXY #define ReportError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) int virFileStripSuffix(char *str, diff -r 786626684900 src/virterror.c --- a/src/virterror.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/virterror.c Wed Oct 29 20:09:48 2008 +0000 @@ -15,18 +15,17 @@ #include <string.h> #include <stdarg.h> -#include "internal.h" -#include "libvirt/virterror.h" +#include "virterror_internal.h" -virError __lastErr = /* the last error */ +virError virLastErr = /* the last error */ { .code = 0, .domain = 0, .message = NULL, .level = VIR_ERR_NONE, .conn = NULL, .dom = NULL, .str1 = NULL, .str2 = NULL, .str3 = NULL, .int1 = 0, .int2 = 0, .net = NULL }; -static virErrorFunc virErrorHandler = NULL; /* global error handler */ -static void *virUserData = NULL; /* associated data */ +virErrorFunc virErrorHandler = NULL; /* global error handler */ +void *virUserData = NULL; /* associated data */ /* - * Macro used to format the message as a string in __virRaiseError + * Macro used to format the message as a string in virRaiseError * and borrowed from libxml2. */ #define VIR_GET_VAR_STR(msg, str) { \ @@ -74,9 +73,9 @@ virErrorPtr virGetLastError(void) { - if (__lastErr.code == VIR_ERR_OK) + if (virLastErr.code == VIR_ERR_OK) return (NULL); - return (&__lastErr); + return (&virLastErr); } /* @@ -94,10 +93,10 @@ { if (to == NULL) return (-1); - if (__lastErr.code == VIR_ERR_OK) + if (virLastErr.code == VIR_ERR_OK) return (0); - memcpy(to, &__lastErr, sizeof(virError)); - return (__lastErr.code); + memcpy(to, &virLastErr, sizeof(virError)); + return (virLastErr.code); } /** @@ -126,7 +125,7 @@ void virResetLastError(void) { - virResetError(&__lastErr); + virResetError(&virLastErr); } /** @@ -331,7 +330,7 @@ } /** - * __virRaiseError: + * virRaiseError: * @conn: the connection to the hypervisor if available * @dom: the domain if available * @net: the network if available @@ -350,12 +349,12 @@ * immediately if a callback is found and store it for later handling. */ void -__virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, - int domain, int code, virErrorLevel level, - const char *str1, const char *str2, const char *str3, - int int1, int int2, const char *msg, ...) +virRaiseError(virConnectPtr conn, virDomainPtr dom, virNetworkPtr net, + int domain, int code, virErrorLevel level, + const char *str1, const char *str2, const char *str3, + int int1, int int2, const char *msg, ...) { - virErrorPtr to = &__lastErr; + virErrorPtr to = &virLastErr; void *userData = virUserData; virErrorFunc handler = virErrorHandler; char *str; @@ -414,7 +413,7 @@ } /** - * __virErrorMsg: + * virErrorMsg: * @error: the virErrorNumber * @info: usually the first parameter string * @@ -424,7 +423,7 @@ * Returns the constant string associated to @error */ const char * -__virErrorMsg(virErrorNumber error, const char *info) +virErrorMsg(virErrorNumber error, const char *info) { const char *errmsg = NULL; @@ -724,7 +723,7 @@ } /** - * __virReportErrorHelper + * virReportErrorHelper * * @conn: the connection to the hypervisor if available * @dom: the domain if available @@ -740,11 +739,11 @@ * Helper function to do most of the grunt work for individual driver * ReportError */ -void __virReportErrorHelper(virConnectPtr conn, int domcode, int errcode, - const char *filename ATTRIBUTE_UNUSED, - const char *funcname ATTRIBUTE_UNUSED, - long long linenr ATTRIBUTE_UNUSED, - const char *fmt, ...) +void virReportErrorHelper(virConnectPtr conn, int domcode, int errcode, + const char *filename ATTRIBUTE_UNUSED, + const char *funcname ATTRIBUTE_UNUSED, + long long linenr ATTRIBUTE_UNUSED, + const char *fmt, ...) { va_list args; char errorMessage[1024]; @@ -758,8 +757,8 @@ errorMessage[0] = '\0'; } - virerr = __virErrorMsg(errcode, (errorMessage[0] ? errorMessage : NULL)); - __virRaiseError(conn, NULL, NULL, domcode, errcode, VIR_ERR_ERROR, - virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); + virerr = virErrorMsg(errcode, (errorMessage[0] ? errorMessage : NULL)); + virRaiseError(conn, NULL, NULL, domcode, errcode, VIR_ERR_ERROR, + virerr, errorMessage, NULL, -1, -1, virerr, errorMessage); } diff -r 786626684900 src/virterror_internal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/virterror_internal.h Wed Oct 29 20:09:48 2008 +0000 @@ -0,0 +1,56 @@ +/* + * virterror.h: internal error handling + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __VIRT_ERROR_H_ +#define __VIRT_ERROR_H_ + +#include "internal.h" + +extern virError virLastErr; +extern virErrorFunc virErrorHandler; +extern void *virUserData; + +/************************************************************************ + * * + * API for error handling * + * * + ************************************************************************/ +void virRaiseError(virConnectPtr conn, + virDomainPtr dom, + virNetworkPtr net, + int domain, + int code, + virErrorLevel level, + const char *str1, + const char *str2, + const char *str3, + int int1, int int2, const char *msg, ...) + ATTRIBUTE_FORMAT(printf, 12, 13); +const char *virErrorMsg(virErrorNumber error, const char *info); +void virReportErrorHelper(virConnectPtr conn, int domcode, int errcode, + const char *filename ATTRIBUTE_UNUSED, + const char *funcname ATTRIBUTE_UNUSED, + long long linenr ATTRIBUTE_UNUSED, + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 7, 8); + + +#endif diff -r 786626684900 src/xen_internal.c --- a/src/xen_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xen_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -26,11 +26,6 @@ #include <errno.h> #include <sys/utsname.h> -#include "xs_internal.h" -#include "stats_linux.h" -#include "xend_internal.h" -#include "util.h" - /* required for dom0_getdomaininfo_t */ #include <xen/dom0_ops.h> #include <xen/version.h> @@ -45,6 +40,14 @@ /* required for shutdown flags */ #include <xen/sched.h> +#include "virterror_internal.h" +#include "driver.h" +#include "util.h" +#include "xen_unified.h" +#include "xen_internal.h" +#include "xs_internal.h" +#include "stats_linux.h" +#include "xend_internal.h" #include "buf.h" #include "capabilities.h" #include "memory.h" @@ -653,10 +656,6 @@ }; typedef struct xen_op_v2_dom xen_op_v2_dom; -#include "internal.h" -#include "driver.h" -#include "xen_unified.h" -#include "xen_internal.h" #ifdef __linux__ #define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd" @@ -720,7 +719,7 @@ #define virXenError(conn, code, fmt...) \ if (in_init == 0) \ - __virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) #ifndef PROXY @@ -747,15 +746,15 @@ return; - errmsg = __virErrorMsg(error, info); + errmsg =virErrorMsg(error, info); if (func != NULL) { snprintf(fullinfo, 999, "%s: %s", func, info); fullinfo[999] = 0; - __virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, errmsg, fullinfo, NULL, value, 0, errmsg, fullinfo, value); } else { - __virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, + virRaiseError(conn, NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR, errmsg, info, NULL, value, 0, errmsg, info, value); } diff -r 786626684900 src/xen_unified.c --- a/src/xen_unified.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xen_unified.c Wed Oct 29 20:09:48 2008 +0000 @@ -27,7 +27,7 @@ #include <xen/dom0_ops.h> #include <libxml/uri.h> -#include "internal.h" +#include "virterror_internal.h" #include "xen_unified.h" @@ -59,7 +59,7 @@ }; #define xenUnifiedError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_XEN, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) /* diff -r 786626684900 src/xend_internal.c --- a/src/xend_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xend_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -32,6 +32,7 @@ #include <libxml/uri.h> #include <errno.h> +#include "virterror_internal.h" #include "xend_internal.h" #include "driver.h" #include "util.h" @@ -105,7 +106,7 @@ #endif #define virXendError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_XEND, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_XEND, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) #define virXendErrorInt(conn, code, ival) \ diff -r 786626684900 src/xm_internal.c --- a/src/xm_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xm_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -35,6 +35,7 @@ #include <stdint.h> #include <xen/dom0_ops.h> +#include "virterror_internal.h" #include "xm_internal.h" #include "xen_unified.h" #include "xend_internal.h" @@ -123,7 +124,7 @@ }; #define xenXMError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_XENXM, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_XENXM, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) int diff -r 786626684900 src/xml.c --- a/src/xml.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xml.c Wed Oct 29 20:09:48 2008 +0000 @@ -16,14 +16,15 @@ #include <stdarg.h> #include <limits.h> #include <math.h> /* for isnan() */ -#include "internal.h" + +#include "virterror_internal.h" #include "xml.h" #include "buf.h" #include "util.h" #include "memory.h" #define virXMLError(conn, code, fmt...) \ - __virReportErrorHelper(conn, VIR_FROM_XML, code, __FILE__, \ + virReportErrorHelper(conn, VIR_FROM_XML, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) diff -r 786626684900 src/xmlrpc.c --- a/src/xmlrpc.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xmlrpc.c Wed Oct 29 20:09:48 2008 +0000 @@ -11,7 +11,7 @@ #include <config.h> #include "xmlrpc.h" -#include "internal.h" +#include "virterror_internal.h" #include "memory.h" #include <libxml/nanohttp.h> @@ -41,8 +41,8 @@ if (error == VIR_ERR_OK) return; - errmsg = __virErrorMsg(error, info); - __virRaiseError(NULL, NULL, NULL, VIR_FROM_RPC, error, VIR_ERR_ERROR, + errmsg = virErrorMsg(error, info); + virRaiseError(NULL, NULL, NULL, VIR_FROM_RPC, error, VIR_ERR_ERROR, errmsg, info, NULL, value, 0, errmsg, info, value); } diff -r 786626684900 src/xs_internal.c --- a/src/xs_internal.c Wed Oct 29 15:23:00 2008 +0000 +++ b/src/xs_internal.c Wed Oct 29 20:09:48 2008 +0000 @@ -26,7 +26,7 @@ #include <xs.h> -#include "internal.h" +#include "virterror_internal.h" #include "driver.h" #include "xen_unified.h" #include "xs_internal.h" @@ -88,7 +88,7 @@ #endif /* ! PROXY */ #define virXenStoreError(conn, code, fmt...) \ - __virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__, \ + virReportErrorHelper(NULL, VIR_FROM_XENSTORE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) /************************************************************************ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:36:10PM +0000, Daniel P. Berrange wrote:
After Daniel's feedback that adding src/virterror.h is confusing, I've re-done the patch to instead add virterror_internal.h, making it clear that these function prototypes are related to virterror.c, but internal use only. That patch is basically moving them out of src/internal.h In addition it removes the leading __ prefix from virRaiseError since this symbol was never exported fromthe library.
The diff is mis-leading - most of this is just the s/__// change.
Okay, I'm surprized that there is no more usage of internal.h, i would have though it was still used widely for things like ATTRIBUTE_UNUSED, but apparently not, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Thu, Oct 30, 2008 at 03:19:11PM +0100, Daniel Veillard wrote:
On Thu, Oct 30, 2008 at 01:36:10PM +0000, Daniel P. Berrange wrote:
After Daniel's feedback that adding src/virterror.h is confusing, I've re-done the patch to instead add virterror_internal.h, making it clear that these function prototypes are related to virterror.c, but internal use only. That patch is basically moving them out of src/internal.h In addition it removes the leading __ prefix from virRaiseError since this symbol was never exported fromthe library.
The diff is mis-leading - most of this is just the s/__// change.
Okay, I'm surprized that there is no more usage of internal.h, i would have though it was still used widely for things like ATTRIBUTE_UNUSED, but apparently not,
Actually, that's just a minor simplification on my part - virterror_internal.h will include internal.h, so there was no need to keep the explicit internal.h, though we could if you wanted. Ultimately every single file uses the internal.h, via one or more of its includs. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 02:21:35PM +0000, Daniel P. Berrange wrote:
On Thu, Oct 30, 2008 at 03:19:11PM +0100, Daniel Veillard wrote:
On Thu, Oct 30, 2008 at 01:36:10PM +0000, Daniel P. Berrange wrote:
After Daniel's feedback that adding src/virterror.h is confusing, I've re-done the patch to instead add virterror_internal.h, making it clear that these function prototypes are related to virterror.c, but internal use only. That patch is basically moving them out of src/internal.h In addition it removes the leading __ prefix from virRaiseError since this symbol was never exported fromthe library.
The diff is mis-leading - most of this is just the s/__// change.
Okay, I'm surprized that there is no more usage of internal.h, i would have though it was still used widely for things like ATTRIBUTE_UNUSED, but apparently not,
Actually, that's just a minor simplification on my part - virterror_internal.h will include internal.h, so there was no need to keep the explicit internal.h, though we could if you wanted. Ultimately every single file uses the internal.h, via one or more of its includs.
Ah, right, i missed that, now it's clear ! thanks, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

When we added the LXC driver, it originally needed to respond to signals. We removed that need a while ago, but left the infrastructure around. This patch removes the driver calls relating to signal progation, since they're unneccessary and we shouldn't follow this approach again in the future, because all drivers need to survive libvirtd restarts, which means they cannot rely in having signals from child processes. qemud/qemud.c | 3 +-- src/driver.h | 6 +----- src/internal.h | 2 -- src/libvirt.c | 10 ---------- src/network_driver.c | 1 - 5 files changed, 2 insertions(+), 20 deletions(-) Daniel diff -r dbe9394acdf8 qemud/qemud.c --- a/qemud/qemud.c Wed Oct 29 15:23:01 2008 +0000 +++ b/qemud/qemud.c Wed Oct 29 15:24:01 2008 +0000 @@ -262,9 +262,8 @@ break; default: - qemudLog(QEMUD_INFO, _("Received signal %d, dispatching to drivers"), + qemudLog(QEMUD_INFO, _("Received unexpected signal %d"), siginfo.si_signo); - virStateSigDispatcher(&siginfo); break; } diff -r dbe9394acdf8 src/driver.h --- a/src/driver.h Wed Oct 29 15:23:01 2008 +0000 +++ b/src/driver.h Wed Oct 29 15:24:01 2008 +0000 @@ -10,8 +10,6 @@ #include "libvirt/virterror.h" #include <libxml/uri.h> - -#include <signal.h> /* * List of registered drivers numbers @@ -595,12 +593,11 @@ virDrvStorageVolGetPath volGetPath; }; +#ifdef WITH_LIBVIRTD typedef int (*virDrvStateInitialize) (void); typedef int (*virDrvStateCleanup) (void); typedef int (*virDrvStateReload) (void); typedef int (*virDrvStateActive) (void); -#ifdef WITH_LIBVIRTD -typedef int (*virDrvSigHandler) (siginfo_t *siginfo); typedef struct _virStateDriver virStateDriver; typedef virStateDriver *virStateDriverPtr; @@ -610,7 +607,6 @@ virDrvStateCleanup cleanup; virDrvStateReload reload; virDrvStateActive active; - virDrvSigHandler sigHandler; }; #endif diff -r dbe9394acdf8 src/internal.h --- a/src/internal.h Wed Oct 29 15:23:01 2008 +0000 +++ b/src/internal.h Wed Oct 29 15:24:01 2008 +0000 @@ -333,12 +333,10 @@ int __virStateCleanup(void); int __virStateReload(void); int __virStateActive(void); -int __virStateSigDispatcher(siginfo_t *siginfo); #define virStateInitialize() __virStateInitialize() #define virStateCleanup() __virStateCleanup() #define virStateReload() __virStateReload() #define virStateActive() __virStateActive() -#define virStateSigDispatcher(s) __virStateSigDispatcher(s) #endif int __virDrvSupportsFeature (virConnectPtr conn, int feature); diff -r dbe9394acdf8 src/libvirt.c --- a/src/libvirt.c Wed Oct 29 15:23:01 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 15:24:01 2008 +0000 @@ -625,16 +625,6 @@ return ret; } -int __virStateSigDispatcher(siginfo_t *siginfo) { - int i, ret = 0; - - for (i = 0 ; i < virStateDriverTabCount ; i++) { - if (virStateDriverTab[i]->sigHandler && - virStateDriverTab[i]->sigHandler(siginfo)) - ret = 1; - } - return ret; -} #endif diff -r dbe9394acdf8 src/network_driver.c --- a/src/network_driver.c Wed Oct 29 15:23:01 2008 +0000 +++ b/src/network_driver.c Wed Oct 29 15:24:01 2008 +0000 @@ -1144,7 +1144,6 @@ networkShutdown, networkReload, networkActive, - NULL }; int networkRegister(void) { -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:36:45PM +0000, Daniel P. Berrange wrote:
When we added the LXC driver, it originally needed to respond to signals. We removed that need a while ago, but left the infrastructure around. This patch removes the driver calls relating to signal progation, since they're unneccessary and
uncontroversial +1
we shouldn't follow this approach again in the future, because all drivers need to survive libvirtd restarts, which means they cannot rely in having signals from child processes.
So ultimately we could remove the signal part of the drivers and maybe simplify the handling from qemudDispatchSignalEvent Maybe we can extract the persistency mechanism and share it between the wrapper processes then. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Following Daniel's feedback yesterday, instead of moving the virGetDomain & related functions from hash.c into libvirt.c, I create a new file to deal with all our public datatypes. I call it datatypes.h, datatypes.c A bunch of stuff moves out of hash.c and internal.h into these two files. Quite a few internal driver files need updates to add an extra #include line. There should be no functional changes here b/src/datatypes.c | 772 +++++++++++++++++++++++++++++++++++++++++++++++ b/src/datatypes.h | 212 ++++++++++++ b/src/libvirt_internal.h | 64 +++ po/POTFILES.in | 2 proxy/libvirt_proxy.c | 2 qemud/qemud.c | 2 qemud/remote.c | 3 src/Makefile.am | 3 src/domain_conf.c | 1 src/domain_conf.h | 4 src/driver.h | 3 src/hash.c | 725 -------------------------------------------- src/internal.h | 206 ------------ src/libvirt.c | 6 src/lxc_driver.c | 1 src/network_conf.c | 1 src/network_conf.h | 4 src/network_driver.c | 1 src/openvz_driver.c | 1 src/proxy_internal.c | 1 src/proxy_internal.h | 2 src/qemu_driver.c | 1 src/qparams.c | 2 src/remote_internal.c | 1 src/stats_linux.c | 1 src/storage_conf.c | 6 src/storage_conf.h | 5 src/storage_driver.c | 1 src/test.c | 1 src/uuid.c | 1 src/veth.c | 1 src/virterror.c | 1 src/xen_internal.c | 1 src/xen_internal.h | 2 src/xen_unified.c | 2 src/xen_unified.h | 3 src/xend_internal.c | 1 src/xend_internal.h | 1 src/xm_internal.c | 1 src/xs_internal.c | 1 tests/xmconfigtest.c | 1 41 files changed, 1102 insertions(+), 948 deletions(-) Daniel diff -r 10d728ae8445 po/POTFILES.in --- a/po/POTFILES.in Wed Oct 29 20:09:50 2008 +0000 +++ b/po/POTFILES.in Wed Oct 29 20:10:40 2008 +0000 @@ -3,8 +3,8 @@ qemud/remote.c src/conf.c src/console.c +src/datatypes.c src/domain_conf.c -src/hash.c src/iptables.c src/libvirt.c src/lxc_container.c diff -r 10d728ae8445 proxy/libvirt_proxy.c --- a/proxy/libvirt_proxy.c Wed Oct 29 20:09:50 2008 +0000 +++ b/proxy/libvirt_proxy.c Wed Oct 29 20:10:40 2008 +0000 @@ -24,7 +24,7 @@ #include <locale.h> #include "internal.h" - +#include "datatypes.h" #include "proxy_internal.h" #include "util.h" #include "xen_internal.h" diff -r 10d728ae8445 qemud/qemud.c --- a/qemud/qemud.c Wed Oct 29 20:09:50 2008 +0000 +++ b/qemud/qemud.c Wed Oct 29 20:10:40 2008 +0000 @@ -49,7 +49,7 @@ #include <signal.h> #include <netdb.h> -#include "internal.h" +#include "libvirt_internal.h" #include "qemud.h" #include "util.h" diff -r 10d728ae8445 qemud/remote.c --- a/qemud/remote.c Wed Oct 29 20:09:50 2008 +0000 +++ b/qemud/remote.c Wed Oct 29 20:10:40 2008 +0000 @@ -48,7 +48,8 @@ #include <polkit-dbus/polkit-dbus.h> #endif -#include "internal.h" +#include "libvirt_internal.h" +#include "datatypes.h" #include "qemud.h" #include "memory.h" diff -r 10d728ae8445 src/Makefile.am --- a/src/Makefile.am Wed Oct 29 20:09:50 2008 +0000 +++ b/src/Makefile.am Wed Oct 29 20:10:40 2008 +0000 @@ -44,6 +44,7 @@ buf.c buf.h \ conf.c conf.h \ event.c event.h \ + hash.c hash.h \ iptables.c iptables.h \ memory.c memory.h \ qparams.c qparams.h \ @@ -147,8 +148,8 @@ libvirt_la_SOURCES = \ driver.h \ - hash.c hash.h \ internal.h \ + datatypes.c datatypes.h \ libvirt.c libvirt_internal.h \ $(GENERIC_LIB_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ diff -r 10d728ae8445 src/datatypes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/datatypes.c Wed Oct 29 20:10:40 2008 +0000 @@ -0,0 +1,772 @@ +/* + * datatypes.h: management of structs for public data types + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <config.h> + +#include "datatypes.h" +#include "virterror_internal.h" +#include "memory.h" + +/************************************************************************ + * * + * Domain and Connections allocations * + * * + ************************************************************************/ +/** + * virLibConnError: + * @conn: the connection if available + * @error: the error number + * @info: extra information string + * + * Handle an error at the connection level + */ +static void +virLibConnError(virConnectPtr conn, virErrorNumber error, const char *info) +{ + const char *errmsg; + + if (error == VIR_ERR_OK) + return; + + errmsg = virErrorMsg(error, info); + virRaiseError(conn, NULL, NULL, VIR_FROM_NONE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); +} + +/** + * virDomainFreeName: + * @domain: a domain object + * + * Destroy the domain object, this is just used by the domain hash callback. + * + * Returns 0 in case of success and -1 in case of failure. + */ +static int +virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED) +{ + return (virDomainFree(domain)); +} + +/** + * virNetworkFreeName: + * @network: a network object + * + * Destroy the network object, this is just used by the network hash callback. + * + * Returns 0 in case of success and -1 in case of failure. + */ +static int +virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED) +{ + return (virNetworkFree(network)); +} + +/** + * virStoragePoolFreeName: + * @pool: a pool object + * + * Destroy the pool object, this is just used by the pool hash callback. + * + * Returns 0 in case of success and -1 in case of failure. + */ +static int +virStoragePoolFreeName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED) +{ + return (virStoragePoolFree(pool)); +} + +/** + * virStorageVolFreeName: + * @vol: a vol object + * + * Destroy the vol object, this is just used by the vol hash callback. + * + * Returns 0 in case of success and -1 in case of failure. + */ +static int +virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED) +{ + return (virStorageVolFree(vol)); +} + +/** + * virGetConnect: + * + * Allocates a new hypervisor connection structure + * + * Returns a new pointer or NULL in case of error. + */ +virConnectPtr +virGetConnect(void) { + virConnectPtr ret; + + if (VIR_ALLOC(ret) < 0) { + virLibConnError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection")); + goto failed; + } + ret->magic = VIR_CONNECT_MAGIC; + ret->driver = NULL; + ret->networkDriver = NULL; + ret->privateData = NULL; + ret->networkPrivateData = NULL; + ret->domains = virHashCreate(20); + if (ret->domains == NULL) + goto failed; + ret->networks = virHashCreate(20); + if (ret->networks == NULL) + goto failed; + ret->storagePools = virHashCreate(20); + if (ret->storagePools == NULL) + goto failed; + ret->storageVols = virHashCreate(20); + if (ret->storageVols == NULL) + goto failed; + + pthread_mutex_init(&ret->lock, NULL); + + ret->refs = 1; + return(ret); + +failed: + if (ret != NULL) { + if (ret->domains != NULL) + virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName); + if (ret->networks != NULL) + virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName); + if (ret->storagePools != NULL) + virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName); + if (ret->storageVols != NULL) + virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName); + + pthread_mutex_destroy(&ret->lock); + VIR_FREE(ret); + } + return(NULL); +} + +/** + * virReleaseConnect: + * @conn: the hypervisor connection to release + * + * Unconditionally release all memory associated with a connection. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The connection obj must not + * be used once this method returns. + */ +static void +virReleaseConnect(virConnectPtr conn) { + DEBUG("release connection %p %s", conn, conn->name); + if (conn->domains != NULL) + virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName); + if (conn->networks != NULL) + virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName); + if (conn->storagePools != NULL) + virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName); + if (conn->storageVols != NULL) + virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName); + + virResetError(&conn->err); + if (virLastErr.conn == conn) + virLastErr.conn = NULL; + + VIR_FREE(conn->name); + + pthread_mutex_unlock(&conn->lock); + pthread_mutex_destroy(&conn->lock); + VIR_FREE(conn); +} + +/** + * virUnrefConnect: + * @conn: the hypervisor connection to unreference + * + * Unreference the connection. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefConnect(virConnectPtr conn) { + int refs; + + if ((!VIR_IS_CONNECT(conn))) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + pthread_mutex_lock(&conn->lock); + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + refs = conn->refs; + if (refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return (0); + } + pthread_mutex_unlock(&conn->lock); + return (refs); +} + +/** + * virGetDomain: + * @conn: the hypervisor connection + * @name: pointer to the domain name + * @uuid: pointer to the uuid + * + * Lookup if the domain is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virUnrefDomain() is needed to not leak data. + * + * Returns a pointer to the domain, or NULL in case of failure + */ +virDomainPtr +__virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) { + virDomainPtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + /* TODO search by UUID first as they are better differenciators */ + + ret = (virDomainPtr) virHashLookup(conn->domains, name); + /* TODO check the UUID */ + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating domain")); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating domain")); + goto error; + } + ret->magic = VIR_DOMAIN_MAGIC; + ret->conn = conn; + ret->id = -1; + if (uuid != NULL) + memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); + + if (virHashAddEntry(conn->domains, name, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add domain to connection hash table")); + goto error; + } + conn->refs++; + DEBUG("New hash entry %p", ret); + } else { + DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1); + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + + error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + +/** + * virReleaseDomain: + * @domain: the domain to release + * + * Unconditionally release all memory associated with a domain. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The domain obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseDomain(virDomainPtr domain) { + virConnectPtr conn = domain->conn; + DEBUG("release domain %p %s", domain, domain->name); + + /* TODO search by UUID first as they are better differenciators */ + if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("domain missing from connection hash table")); + + if (conn->err.dom == domain) + conn->err.dom = NULL; + if (virLastErr.dom == domain) + virLastErr.dom = NULL; + domain->magic = -1; + domain->id = -1; + VIR_FREE(domain->name); + VIR_FREE(domain); + + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefDomain: + * @domain: the domain to unreference + * + * Unreference the domain. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefDomain(virDomainPtr domain) { + int refs; + + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { + virLibConnError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + pthread_mutex_lock(&domain->conn->lock); + DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs); + domain->refs--; + refs = domain->refs; + if (refs == 0) { + virReleaseDomain(domain); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&domain->conn->lock); + return (refs); +} + +/** + * virGetNetwork: + * @conn: the hypervisor connection + * @name: pointer to the network name + * @uuid: pointer to the uuid + * + * Lookup if the network is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virUnrefNetwork() is needed to not leak data. + * + * Returns a pointer to the network, or NULL in case of failure + */ +virNetworkPtr +__virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) { + virNetworkPtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + /* TODO search by UUID first as they are better differenciators */ + + ret = (virNetworkPtr) virHashLookup(conn->networks, name); + /* TODO check the UUID */ + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating network")); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating network")); + goto error; + } + ret->magic = VIR_NETWORK_MAGIC; + ret->conn = conn; + if (uuid != NULL) + memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); + + if (virHashAddEntry(conn->networks, name, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add network to connection hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + + error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + +/** + * virReleaseNetwork: + * @network: the network to release + * + * Unconditionally release all memory associated with a network. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The network obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseNetwork(virNetworkPtr network) { + virConnectPtr conn = network->conn; + DEBUG("release network %p %s", network, network->name); + + /* TODO search by UUID first as they are better differenciators */ + if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("network missing from connection hash table")); + + if (conn->err.net == network) + conn->err.net = NULL; + if (virLastErr.net == network) + virLastErr.net = NULL; + + network->magic = -1; + VIR_FREE(network->name); + VIR_FREE(network); + + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefNetwork: + * @network: the network to unreference + * + * Unreference the network. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefNetwork(virNetworkPtr network) { + int refs; + + if (!VIR_IS_CONNECTED_NETWORK(network)) { + virLibConnError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + pthread_mutex_lock(&network->conn->lock); + DEBUG("unref network %p %s %d", network, network->name, network->refs); + network->refs--; + refs = network->refs; + if (refs == 0) { + virReleaseNetwork(network); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&network->conn->lock); + return (refs); +} + + +/** + * virGetStoragePool: + * @conn: the hypervisor connection + * @name: pointer to the storage pool name + * @uuid: pointer to the uuid + * + * Lookup if the storage pool is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virFreeStoragePool() is needed to not leak data. + * + * Returns a pointer to the network, or NULL in case of failure + */ +virStoragePoolPtr +__virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) { + virStoragePoolPtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + /* TODO search by UUID first as they are better differenciators */ + + ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name); + /* TODO check the UUID */ + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool")); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating storage pool")); + goto error; + } + ret->magic = VIR_STORAGE_POOL_MAGIC; + ret->conn = conn; + if (uuid != NULL) + memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); + + if (virHashAddEntry(conn->storagePools, name, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add storage pool to connection hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + +error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + + +/** + * virReleaseStoragePool: + * @pool: the pool to release + * + * Unconditionally release all memory associated with a pool. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The pool obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseStoragePool(virStoragePoolPtr pool) { + virConnectPtr conn = pool->conn; + DEBUG("release pool %p %s", pool, pool->name); + + /* TODO search by UUID first as they are better differenciators */ + if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("pool missing from connection hash table")); + + pool->magic = -1; + VIR_FREE(pool->name); + VIR_FREE(pool); + + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefStoragePool: + * @pool: the pool to unreference + * + * Unreference the pool. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefStoragePool(virStoragePoolPtr pool) { + int refs; + + if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { + virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + pthread_mutex_lock(&pool->conn->lock); + DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs); + pool->refs--; + refs = pool->refs; + if (refs == 0) { + virReleaseStoragePool(pool); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&pool->conn->lock); + return (refs); +} + + +/** + * virGetStorageVol: + * @conn: the hypervisor connection + * @pool: pool owning the volume + * @name: pointer to the storage vol name + * @uuid: pointer to the uuid + * + * Lookup if the storage vol is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virFreeStorageVol() is needed to not leak data. + * + * Returns a pointer to the storage vol, or NULL in case of failure + */ +virStorageVolPtr +__virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) { + virStorageVolPtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key); + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol")); + goto error; + } + ret->pool = strdup(pool); + if (ret->pool == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol")); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating storage vol")); + goto error; + } + strncpy(ret->key, key, sizeof(ret->key)-1); + ret->key[sizeof(ret->key)-1] = '\0'; + ret->magic = VIR_STORAGE_VOL_MAGIC; + ret->conn = conn; + + if (virHashAddEntry(conn->storageVols, key, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add storage vol to connection hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + +error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret->pool); + VIR_FREE(ret); + } + return(NULL); +} + + +/** + * virReleaseStorageVol: + * @vol: the vol to release + * + * Unconditionally release all memory associated with a vol. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The vol obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseStorageVol(virStorageVolPtr vol) { + virConnectPtr conn = vol->conn; + DEBUG("release vol %p %s", vol, vol->name); + + /* TODO search by UUID first as they are better differenciators */ + if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("vol missing from connection hash table")); + + vol->magic = -1; + VIR_FREE(vol->name); + VIR_FREE(vol->pool); + VIR_FREE(vol); + + DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefStorageVol: + * @vol: the vol to unreference + * + * Unreference the vol. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefStorageVol(virStorageVolPtr vol) { + int refs; + + if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { + virLibConnError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + pthread_mutex_lock(&vol->conn->lock); + DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs); + vol->refs--; + refs = vol->refs; + if (refs == 0) { + virReleaseStorageVol(vol); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&vol->conn->lock); + return (refs); +} diff -r 10d728ae8445 src/datatypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/datatypes.h Wed Oct 29 20:10:40 2008 +0000 @@ -0,0 +1,212 @@ +/* + * datatypes.h: management of structs for public data types + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __VIRT_DATATYPES_H_ +#define __VIRT_DATATYPES_H_ + +#include "internal.h" + +#include "hash.h" +#include "driver.h" + + +/** + * VIR_CONNECT_MAGIC: + * + * magic value used to protect the API when pointers to connection structures + * are passed down by the uers. + */ +#define VIR_CONNECT_MAGIC 0x4F23DEAD +#define VIR_IS_CONNECT(obj) ((obj) && (obj)->magic==VIR_CONNECT_MAGIC) + + +/** + * VIR_DOMAIN_MAGIC: + * + * magic value used to protect the API when pointers to domain structures + * are passed down by the users. + */ +#define VIR_DOMAIN_MAGIC 0xDEAD4321 +#define VIR_IS_DOMAIN(obj) ((obj) && (obj)->magic==VIR_DOMAIN_MAGIC) +#define VIR_IS_CONNECTED_DOMAIN(obj) (VIR_IS_DOMAIN(obj) && VIR_IS_CONNECT((obj)->conn)) + +/** + * VIR_NETWORK_MAGIC: + * + * magic value used to protect the API when pointers to network structures + * are passed down by the users. + */ +#define VIR_NETWORK_MAGIC 0xDEAD1234 +#define VIR_IS_NETWORK(obj) ((obj) && (obj)->magic==VIR_NETWORK_MAGIC) +#define VIR_IS_CONNECTED_NETWORK(obj) (VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn)) + +/** + * VIR_STORAGE_POOL_MAGIC: + * + * magic value used to protect the API when pointers to storage pool structures + * are passed down by the users. + */ +#define VIR_STORAGE_POOL_MAGIC 0xDEAD5678 +#define VIR_IS_STORAGE_POOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_POOL_MAGIC) +#define VIR_IS_CONNECTED_STORAGE_POOL(obj) (VIR_IS_STORAGE_POOL(obj) && VIR_IS_CONNECT((obj)->conn)) + +/** + * VIR_STORAGE_VOL_MAGIC: + * + * magic value used to protect the API when pointers to storage vol structures + * are passed down by the users. + */ +#define VIR_STORAGE_VOL_MAGIC 0xDEAD8765 +#define VIR_IS_STORAGE_VOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC) +#define VIR_IS_CONNECTED_STORAGE_VOL(obj) (VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn)) + + +/** + * _virConnect: + * + * Internal structure associated to a connection + */ +struct _virConnect { + unsigned int magic; /* specific value to check */ + int flags; /* a set of connection flags */ + char *name; /* connection URI */ + + /* The underlying hypervisor driver and network driver. */ + virDriverPtr driver; + virNetworkDriverPtr networkDriver; + virStorageDriverPtr storageDriver; + + /* Private data pointer which can be used by driver and + * network driver as they wish. + * NB: 'private' is a reserved word in C++. + */ + void * privateData; + void * networkPrivateData; + void * storagePrivateData; + + /* Per-connection error. */ + virError err; /* the last error */ + virErrorFunc handler; /* associated handlet */ + void *userData; /* the user data */ + + /* + * The lock mutex must be acquired before accessing/changing + * any of members following this point, or changing the ref + * count of any virDomain/virNetwork object associated with + * this connection + */ + PTHREAD_MUTEX_T (lock); + virHashTablePtr domains; /* hash table for known domains */ + virHashTablePtr networks; /* hash table for known domains */ + virHashTablePtr storagePools;/* hash table for known storage pools */ + virHashTablePtr storageVols;/* hash table for known storage vols */ + int refs; /* reference count */ +}; + +/** +* _virDomain: +* +* Internal structure associated to a domain +*/ +struct _virDomain { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* the domain external name */ + int id; /* the domain ID */ + unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */ +}; + +/** +* _virNetwork: +* +* Internal structure associated to a domain +*/ +struct _virNetwork { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* the network external name */ + unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */ +}; + +/** +* _virStoragePool: +* +* Internal structure associated to a storage pool +*/ +struct _virStoragePool { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* the storage pool external name */ + unsigned char uuid[VIR_UUID_BUFLEN]; /* the storage pool unique identifier */ +}; + +/** +* _virStorageVol: +* +* Internal structure associated to a storage volume +*/ +struct _virStorageVol { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *pool; /* Pool name of owner */ + char *name; /* the storage vol external name */ + /* XXX currently abusing path for this. Ought not to be so evil */ + char key[PATH_MAX]; /* unique key for storage vol */ +}; + +/************************************************************************ + * * + * API for domain/connections (de)allocations and lookups * + * * + ************************************************************************/ + +virConnectPtr virGetConnect(void); +int virUnrefConnect(virConnectPtr conn); +virDomainPtr __virGetDomain(virConnectPtr conn, + const char *name, + const unsigned char *uuid); +int virUnrefDomain(virDomainPtr domain); +virNetworkPtr __virGetNetwork(virConnectPtr conn, + const char *name, + const unsigned char *uuid); +int virUnrefNetwork(virNetworkPtr network); + +virStoragePoolPtr __virGetStoragePool(virConnectPtr conn, + const char *name, + const unsigned char *uuid); +int virUnrefStoragePool(virStoragePoolPtr pool); +virStorageVolPtr __virGetStorageVol(virConnectPtr conn, + const char *pool, + const char *name, + const char *key); +int virUnrefStorageVol(virStorageVolPtr vol); + +#define virGetDomain(c,n,u) __virGetDomain((c),(n),(u)) +#define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u)) +#define virGetStoragePool(c,n,u) __virGetStoragePool((c),(n),(u)) +#define virGetStorageVol(c,p,n,u) __virGetStorageVol((c),(p),(n),(u)) + + +#endif diff -r 10d728ae8445 src/domain_conf.c --- a/src/domain_conf.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/domain_conf.c Wed Oct 29 20:10:40 2008 +0000 @@ -30,6 +30,7 @@ #include <dirent.h> #include "virterror_internal.h" +#include "datatypes.h" #include "domain_conf.h" #include "memory.h" #include "verify.h" diff -r 10d728ae8445 src/domain_conf.h --- a/src/domain_conf.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/domain_conf.h Wed Oct 29 20:10:40 2008 +0000 @@ -24,7 +24,9 @@ #ifndef __DOMAIN_CONF_H #define __DOMAIN_CONF_H -#include <config.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> #include "internal.h" #include "capabilities.h" diff -r 10d728ae8445 src/driver.h --- a/src/driver.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/driver.h Wed Oct 29 20:10:40 2008 +0000 @@ -5,9 +5,6 @@ #ifndef __VIR_DRIVER_H__ #define __VIR_DRIVER_H__ - -#include "libvirt/libvirt.h" -#include "libvirt/virterror.h" #include <libxml/uri.h> diff -r 10d728ae8445 src/hash.c --- a/src/hash.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/hash.c Wed Oct 29 20:10:40 2008 +0000 @@ -594,728 +594,3 @@ return (NULL); } -/************************************************************************ - * * - * Domain and Connections allocations * - * * - ************************************************************************/ - -/** - * virDomainFreeName: - * @domain: a domain object - * - * Destroy the domain object, this is just used by the domain hash callback. - * - * Returns 0 in case of success and -1 in case of failure. - */ -static int -virDomainFreeName(virDomainPtr domain, const char *name ATTRIBUTE_UNUSED) -{ - return (virDomainFree(domain)); -} - -/** - * virNetworkFreeName: - * @network: a network object - * - * Destroy the network object, this is just used by the network hash callback. - * - * Returns 0 in case of success and -1 in case of failure. - */ -static int -virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED) -{ - return (virNetworkFree(network)); -} - -/** - * virStoragePoolFreeName: - * @pool: a pool object - * - * Destroy the pool object, this is just used by the pool hash callback. - * - * Returns 0 in case of success and -1 in case of failure. - */ -static int -virStoragePoolFreeName(virStoragePoolPtr pool, const char *name ATTRIBUTE_UNUSED) -{ - return (virStoragePoolFree(pool)); -} - -/** - * virStorageVolFreeName: - * @vol: a vol object - * - * Destroy the vol object, this is just used by the vol hash callback. - * - * Returns 0 in case of success and -1 in case of failure. - */ -static int -virStorageVolFreeName(virStorageVolPtr vol, const char *name ATTRIBUTE_UNUSED) -{ - return (virStorageVolFree(vol)); -} - -/** - * virGetConnect: - * - * Allocates a new hypervisor connection structure - * - * Returns a new pointer or NULL in case of error. - */ -virConnectPtr -virGetConnect(void) { - virConnectPtr ret; - - if (VIR_ALLOC(ret) < 0) { - virHashError(NULL, VIR_ERR_NO_MEMORY, "%s", _("allocating connection")); - goto failed; - } - ret->magic = VIR_CONNECT_MAGIC; - ret->driver = NULL; - ret->networkDriver = NULL; - ret->privateData = NULL; - ret->networkPrivateData = NULL; - ret->domains = virHashCreate(20); - if (ret->domains == NULL) - goto failed; - ret->networks = virHashCreate(20); - if (ret->networks == NULL) - goto failed; - ret->storagePools = virHashCreate(20); - if (ret->storagePools == NULL) - goto failed; - ret->storageVols = virHashCreate(20); - if (ret->storageVols == NULL) - goto failed; - - pthread_mutex_init(&ret->lock, NULL); - - ret->refs = 1; - return(ret); - -failed: - if (ret != NULL) { - if (ret->domains != NULL) - virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName); - if (ret->networks != NULL) - virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName); - if (ret->storagePools != NULL) - virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName); - if (ret->storageVols != NULL) - virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName); - - pthread_mutex_destroy(&ret->lock); - VIR_FREE(ret); - } - return(NULL); -} - -/** - * virReleaseConnect: - * @conn: the hypervisor connection to release - * - * Unconditionally release all memory associated with a connection. - * The conn.lock mutex must be held prior to calling this, and will - * be released prior to this returning. The connection obj must not - * be used once this method returns. - */ -static void -virReleaseConnect(virConnectPtr conn) { - DEBUG("release connection %p %s", conn, conn->name); - if (conn->domains != NULL) - virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName); - if (conn->networks != NULL) - virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName); - if (conn->storagePools != NULL) - virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName); - if (conn->storageVols != NULL) - virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName); - - virResetError(&conn->err); - if (virLastErr.conn == conn) - virLastErr.conn = NULL; - - VIR_FREE(conn->name); - - pthread_mutex_unlock(&conn->lock); - pthread_mutex_destroy(&conn->lock); - VIR_FREE(conn); -} - -/** - * virUnrefConnect: - * @conn: the hypervisor connection to unreference - * - * Unreference the connection. If the use count drops to zero, the structure is - * actually freed. - * - * Returns the reference count or -1 in case of failure. - */ -int -virUnrefConnect(virConnectPtr conn) { - int refs; - - if ((!VIR_IS_CONNECT(conn))) { - virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(-1); - } - pthread_mutex_lock(&conn->lock); - DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); - conn->refs--; - refs = conn->refs; - if (refs == 0) { - virReleaseConnect(conn); - /* Already unlocked mutex */ - return (0); - } - pthread_mutex_unlock(&conn->lock); - return (refs); -} - -/** - * virGetDomain: - * @conn: the hypervisor connection - * @name: pointer to the domain name - * @uuid: pointer to the uuid - * - * Lookup if the domain is already registered for that connection, - * if yes return a new pointer to it, if no allocate a new structure, - * and register it in the table. In any case a corresponding call to - * virUnrefDomain() is needed to not leak data. - * - * Returns a pointer to the domain, or NULL in case of failure - */ -virDomainPtr -__virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) { - virDomainPtr ret = NULL; - - if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(NULL); - } - pthread_mutex_lock(&conn->lock); - - /* TODO search by UUID first as they are better differenciators */ - - ret = (virDomainPtr) virHashLookup(conn->domains, name); - /* TODO check the UUID */ - if (ret == NULL) { - if (VIR_ALLOC(ret) < 0) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating domain")); - goto error; - } - ret->name = strdup(name); - if (ret->name == NULL) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating domain")); - goto error; - } - ret->magic = VIR_DOMAIN_MAGIC; - ret->conn = conn; - ret->id = -1; - if (uuid != NULL) - memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); - - if (virHashAddEntry(conn->domains, name, ret) < 0) { - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to add domain to connection hash table")); - goto error; - } - conn->refs++; - DEBUG("New hash entry %p", ret); - } else { - DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1); - } - ret->refs++; - pthread_mutex_unlock(&conn->lock); - return(ret); - - error: - pthread_mutex_unlock(&conn->lock); - if (ret != NULL) { - VIR_FREE(ret->name); - VIR_FREE(ret); - } - return(NULL); -} - -/** - * virReleaseDomain: - * @domain: the domain to release - * - * Unconditionally release all memory associated with a domain. - * The conn.lock mutex must be held prior to calling this, and will - * be released prior to this returning. The domain obj must not - * be used once this method returns. - * - * It will also unreference the associated connection object, - * which may also be released if its ref count hits zero. - */ -static void -virReleaseDomain(virDomainPtr domain) { - virConnectPtr conn = domain->conn; - DEBUG("release domain %p %s", domain, domain->name); - - /* TODO search by UUID first as they are better differenciators */ - if (virHashRemoveEntry(conn->domains, domain->name, NULL) < 0) - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("domain missing from connection hash table")); - - if (conn->err.dom == domain) - conn->err.dom = NULL; - if (virLastErr.dom == domain) - virLastErr.dom = NULL; - domain->magic = -1; - domain->id = -1; - VIR_FREE(domain->name); - VIR_FREE(domain); - - DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); - conn->refs--; - if (conn->refs == 0) { - virReleaseConnect(conn); - /* Already unlocked mutex */ - return; - } - - pthread_mutex_unlock(&conn->lock); -} - - -/** - * virUnrefDomain: - * @domain: the domain to unreference - * - * Unreference the domain. If the use count drops to zero, the structure is - * actually freed. - * - * Returns the reference count or -1 in case of failure. - */ -int -virUnrefDomain(virDomainPtr domain) { - int refs; - - if (!VIR_IS_CONNECTED_DOMAIN(domain)) { - virHashError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(-1); - } - pthread_mutex_lock(&domain->conn->lock); - DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs); - domain->refs--; - refs = domain->refs; - if (refs == 0) { - virReleaseDomain(domain); - /* Already unlocked mutex */ - return (0); - } - - pthread_mutex_unlock(&domain->conn->lock); - return (refs); -} - -/** - * virGetNetwork: - * @conn: the hypervisor connection - * @name: pointer to the network name - * @uuid: pointer to the uuid - * - * Lookup if the network is already registered for that connection, - * if yes return a new pointer to it, if no allocate a new structure, - * and register it in the table. In any case a corresponding call to - * virUnrefNetwork() is needed to not leak data. - * - * Returns a pointer to the network, or NULL in case of failure - */ -virNetworkPtr -__virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) { - virNetworkPtr ret = NULL; - - if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(NULL); - } - pthread_mutex_lock(&conn->lock); - - /* TODO search by UUID first as they are better differenciators */ - - ret = (virNetworkPtr) virHashLookup(conn->networks, name); - /* TODO check the UUID */ - if (ret == NULL) { - if (VIR_ALLOC(ret) < 0) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating network")); - goto error; - } - ret->name = strdup(name); - if (ret->name == NULL) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating network")); - goto error; - } - ret->magic = VIR_NETWORK_MAGIC; - ret->conn = conn; - if (uuid != NULL) - memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); - - if (virHashAddEntry(conn->networks, name, ret) < 0) { - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to add network to connection hash table")); - goto error; - } - conn->refs++; - } - ret->refs++; - pthread_mutex_unlock(&conn->lock); - return(ret); - - error: - pthread_mutex_unlock(&conn->lock); - if (ret != NULL) { - VIR_FREE(ret->name); - VIR_FREE(ret); - } - return(NULL); -} - -/** - * virReleaseNetwork: - * @network: the network to release - * - * Unconditionally release all memory associated with a network. - * The conn.lock mutex must be held prior to calling this, and will - * be released prior to this returning. The network obj must not - * be used once this method returns. - * - * It will also unreference the associated connection object, - * which may also be released if its ref count hits zero. - */ -static void -virReleaseNetwork(virNetworkPtr network) { - virConnectPtr conn = network->conn; - DEBUG("release network %p %s", network, network->name); - - /* TODO search by UUID first as they are better differenciators */ - if (virHashRemoveEntry(conn->networks, network->name, NULL) < 0) - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("network missing from connection hash table")); - - if (conn->err.net == network) - conn->err.net = NULL; - if (virLastErr.net == network) - virLastErr.net = NULL; - - network->magic = -1; - VIR_FREE(network->name); - VIR_FREE(network); - - DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); - conn->refs--; - if (conn->refs == 0) { - virReleaseConnect(conn); - /* Already unlocked mutex */ - return; - } - - pthread_mutex_unlock(&conn->lock); -} - - -/** - * virUnrefNetwork: - * @network: the network to unreference - * - * Unreference the network. If the use count drops to zero, the structure is - * actually freed. - * - * Returns the reference count or -1 in case of failure. - */ -int -virUnrefNetwork(virNetworkPtr network) { - int refs; - - if (!VIR_IS_CONNECTED_NETWORK(network)) { - virHashError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(-1); - } - pthread_mutex_lock(&network->conn->lock); - DEBUG("unref network %p %s %d", network, network->name, network->refs); - network->refs--; - refs = network->refs; - if (refs == 0) { - virReleaseNetwork(network); - /* Already unlocked mutex */ - return (0); - } - - pthread_mutex_unlock(&network->conn->lock); - return (refs); -} - - -/** - * virGetStoragePool: - * @conn: the hypervisor connection - * @name: pointer to the storage pool name - * @uuid: pointer to the uuid - * - * Lookup if the storage pool is already registered for that connection, - * if yes return a new pointer to it, if no allocate a new structure, - * and register it in the table. In any case a corresponding call to - * virFreeStoragePool() is needed to not leak data. - * - * Returns a pointer to the network, or NULL in case of failure - */ -virStoragePoolPtr -__virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) { - virStoragePoolPtr ret = NULL; - - if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { - virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(NULL); - } - pthread_mutex_lock(&conn->lock); - - /* TODO search by UUID first as they are better differenciators */ - - ret = (virStoragePoolPtr) virHashLookup(conn->storagePools, name); - /* TODO check the UUID */ - if (ret == NULL) { - if (VIR_ALLOC(ret) < 0) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating storage pool")); - goto error; - } - ret->name = strdup(name); - if (ret->name == NULL) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating storage pool")); - goto error; - } - ret->magic = VIR_STORAGE_POOL_MAGIC; - ret->conn = conn; - if (uuid != NULL) - memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); - - if (virHashAddEntry(conn->storagePools, name, ret) < 0) { - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to add storage pool to connection hash table")); - goto error; - } - conn->refs++; - } - ret->refs++; - pthread_mutex_unlock(&conn->lock); - return(ret); - -error: - pthread_mutex_unlock(&conn->lock); - if (ret != NULL) { - VIR_FREE(ret->name); - VIR_FREE(ret); - } - return(NULL); -} - - -/** - * virReleaseStoragePool: - * @pool: the pool to release - * - * Unconditionally release all memory associated with a pool. - * The conn.lock mutex must be held prior to calling this, and will - * be released prior to this returning. The pool obj must not - * be used once this method returns. - * - * It will also unreference the associated connection object, - * which may also be released if its ref count hits zero. - */ -static void -virReleaseStoragePool(virStoragePoolPtr pool) { - virConnectPtr conn = pool->conn; - DEBUG("release pool %p %s", pool, pool->name); - - /* TODO search by UUID first as they are better differenciators */ - if (virHashRemoveEntry(conn->storagePools, pool->name, NULL) < 0) - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("pool missing from connection hash table")); - - pool->magic = -1; - VIR_FREE(pool->name); - VIR_FREE(pool); - - DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); - conn->refs--; - if (conn->refs == 0) { - virReleaseConnect(conn); - /* Already unlocked mutex */ - return; - } - - pthread_mutex_unlock(&conn->lock); -} - - -/** - * virUnrefStoragePool: - * @pool: the pool to unreference - * - * Unreference the pool. If the use count drops to zero, the structure is - * actually freed. - * - * Returns the reference count or -1 in case of failure. - */ -int -virUnrefStoragePool(virStoragePoolPtr pool) { - int refs; - - if (!VIR_IS_CONNECTED_STORAGE_POOL(pool)) { - virHashError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(-1); - } - pthread_mutex_lock(&pool->conn->lock); - DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs); - pool->refs--; - refs = pool->refs; - if (refs == 0) { - virReleaseStoragePool(pool); - /* Already unlocked mutex */ - return (0); - } - - pthread_mutex_unlock(&pool->conn->lock); - return (refs); -} - - -/** - * virGetStorageVol: - * @conn: the hypervisor connection - * @pool: pool owning the volume - * @name: pointer to the storage vol name - * @uuid: pointer to the uuid - * - * Lookup if the storage vol is already registered for that connection, - * if yes return a new pointer to it, if no allocate a new structure, - * and register it in the table. In any case a corresponding call to - * virFreeStorageVol() is needed to not leak data. - * - * Returns a pointer to the storage vol, or NULL in case of failure - */ -virStorageVolPtr -__virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) { - virStorageVolPtr ret = NULL; - - if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) { - virHashError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(NULL); - } - pthread_mutex_lock(&conn->lock); - - ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key); - if (ret == NULL) { - if (VIR_ALLOC(ret) < 0) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating storage vol")); - goto error; - } - ret->pool = strdup(pool); - if (ret->pool == NULL) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating storage vol")); - goto error; - } - ret->name = strdup(name); - if (ret->name == NULL) { - virHashError(conn, VIR_ERR_NO_MEMORY, "%s", _("allocating storage vol")); - goto error; - } - strncpy(ret->key, key, sizeof(ret->key)-1); - ret->key[sizeof(ret->key)-1] = '\0'; - ret->magic = VIR_STORAGE_VOL_MAGIC; - ret->conn = conn; - - if (virHashAddEntry(conn->storageVols, key, ret) < 0) { - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("failed to add storage vol to connection hash table")); - goto error; - } - conn->refs++; - } - ret->refs++; - pthread_mutex_unlock(&conn->lock); - return(ret); - -error: - pthread_mutex_unlock(&conn->lock); - if (ret != NULL) { - VIR_FREE(ret->name); - VIR_FREE(ret->pool); - VIR_FREE(ret); - } - return(NULL); -} - - -/** - * virReleaseStorageVol: - * @vol: the vol to release - * - * Unconditionally release all memory associated with a vol. - * The conn.lock mutex must be held prior to calling this, and will - * be released prior to this returning. The vol obj must not - * be used once this method returns. - * - * It will also unreference the associated connection object, - * which may also be released if its ref count hits zero. - */ -static void -virReleaseStorageVol(virStorageVolPtr vol) { - virConnectPtr conn = vol->conn; - DEBUG("release vol %p %s", vol, vol->name); - - /* TODO search by UUID first as they are better differenciators */ - if (virHashRemoveEntry(conn->storageVols, vol->key, NULL) < 0) - virHashError(conn, VIR_ERR_INTERNAL_ERROR, - "%s", _("vol missing from connection hash table")); - - vol->magic = -1; - VIR_FREE(vol->name); - VIR_FREE(vol->pool); - VIR_FREE(vol); - - DEBUG("unref connection %p %s %d", conn, conn->name, conn->refs); - conn->refs--; - if (conn->refs == 0) { - virReleaseConnect(conn); - /* Already unlocked mutex */ - return; - } - - pthread_mutex_unlock(&conn->lock); -} - - -/** - * virUnrefStorageVol: - * @vol: the vol to unreference - * - * Unreference the vol. If the use count drops to zero, the structure is - * actually freed. - * - * Returns the reference count or -1 in case of failure. - */ -int -virUnrefStorageVol(virStorageVolPtr vol) { - int refs; - - if (!VIR_IS_CONNECTED_STORAGE_VOL(vol)) { - virHashError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); - return(-1); - } - pthread_mutex_lock(&vol->conn->lock); - DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs); - vol->refs--; - refs = vol->refs; - if (refs == 0) { - virReleaseStorageVol(vol); - /* Already unlocked mutex */ - return (0); - } - - pthread_mutex_unlock(&vol->conn->lock); - return (refs); -} diff -r 10d728ae8445 src/internal.h --- a/src/internal.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/internal.h Wed Oct 29 20:10:40 2008 +0000 @@ -33,10 +33,8 @@ #include "gettext.h" -#include "hash.h" #include "libvirt/libvirt.h" #include "libvirt/virterror.h" -#include "driver.h" /* On architectures which lack these limits, define them (ie. Cygwin). * Note that the libvirt code should be robust enough to handle the @@ -142,210 +140,6 @@ __FILE__, __LINE__); /** - * VIR_CONNECT_MAGIC: - * - * magic value used to protect the API when pointers to connection structures - * are passed down by the uers. - */ -#define VIR_CONNECT_MAGIC 0x4F23DEAD -#define VIR_IS_CONNECT(obj) ((obj) && (obj)->magic==VIR_CONNECT_MAGIC) - - -/** - * VIR_DOMAIN_MAGIC: - * - * magic value used to protect the API when pointers to domain structures - * are passed down by the users. - */ -#define VIR_DOMAIN_MAGIC 0xDEAD4321 -#define VIR_IS_DOMAIN(obj) ((obj) && (obj)->magic==VIR_DOMAIN_MAGIC) -#define VIR_IS_CONNECTED_DOMAIN(obj) (VIR_IS_DOMAIN(obj) && VIR_IS_CONNECT((obj)->conn)) - -/** - * VIR_NETWORK_MAGIC: - * - * magic value used to protect the API when pointers to network structures - * are passed down by the users. - */ -#define VIR_NETWORK_MAGIC 0xDEAD1234 -#define VIR_IS_NETWORK(obj) ((obj) && (obj)->magic==VIR_NETWORK_MAGIC) -#define VIR_IS_CONNECTED_NETWORK(obj) (VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn)) - -/** - * VIR_STORAGE_POOL_MAGIC: - * - * magic value used to protect the API when pointers to storage pool structures - * are passed down by the users. - */ -#define VIR_STORAGE_POOL_MAGIC 0xDEAD5678 -#define VIR_IS_STORAGE_POOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_POOL_MAGIC) -#define VIR_IS_CONNECTED_STORAGE_POOL(obj) (VIR_IS_STORAGE_POOL(obj) && VIR_IS_CONNECT((obj)->conn)) - -/** - * VIR_STORAGE_VOL_MAGIC: - * - * magic value used to protect the API when pointers to storage vol structures - * are passed down by the users. - */ -#define VIR_STORAGE_VOL_MAGIC 0xDEAD8765 -#define VIR_IS_STORAGE_VOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC) -#define VIR_IS_CONNECTED_STORAGE_VOL(obj) (VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn)) - -/* - * arbitrary limitations - */ -#define MAX_DRIVERS 10 -#define MIN_XEN_GUEST_SIZE 64 /* 64 megabytes */ - -/** - * _virConnect: - * - * Internal structure associated to a connection - */ -struct _virConnect { - unsigned int magic; /* specific value to check */ - int flags; /* a set of connection flags */ - char *name; /* connection URI */ - - /* The underlying hypervisor driver and network driver. */ - virDriverPtr driver; - virNetworkDriverPtr networkDriver; - virStorageDriverPtr storageDriver; - - /* Private data pointer which can be used by driver and - * network driver as they wish. - * NB: 'private' is a reserved word in C++. - */ - void * privateData; - void * networkPrivateData; - void * storagePrivateData; - - /* Per-connection error. */ - virError err; /* the last error */ - virErrorFunc handler; /* associated handlet */ - void *userData; /* the user data */ - - /* - * The lock mutex must be acquired before accessing/changing - * any of members following this point, or changing the ref - * count of any virDomain/virNetwork object associated with - * this connection - */ - PTHREAD_MUTEX_T (lock); - virHashTablePtr domains; /* hash table for known domains */ - virHashTablePtr networks; /* hash table for known domains */ - virHashTablePtr storagePools;/* hash table for known storage pools */ - virHashTablePtr storageVols;/* hash table for known storage vols */ - int refs; /* reference count */ -}; - -/** -* _virDomain: -* -* Internal structure associated to a domain -*/ -struct _virDomain { - unsigned int magic; /* specific value to check */ - int refs; /* reference count */ - virConnectPtr conn; /* pointer back to the connection */ - char *name; /* the domain external name */ - int id; /* the domain ID */ - unsigned char uuid[VIR_UUID_BUFLEN]; /* the domain unique identifier */ -}; - -/** -* _virNetwork: -* -* Internal structure associated to a domain -*/ -struct _virNetwork { - unsigned int magic; /* specific value to check */ - int refs; /* reference count */ - virConnectPtr conn; /* pointer back to the connection */ - char *name; /* the network external name */ - unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */ -}; - -/** -* _virStoragePool: -* -* Internal structure associated to a storage pool -*/ -struct _virStoragePool { - unsigned int magic; /* specific value to check */ - int refs; /* reference count */ - virConnectPtr conn; /* pointer back to the connection */ - char *name; /* the storage pool external name */ - unsigned char uuid[VIR_UUID_BUFLEN]; /* the storage pool unique identifier */ -}; - -/** -* _virStorageVol: -* -* Internal structure associated to a storage volume -*/ -struct _virStorageVol { - unsigned int magic; /* specific value to check */ - int refs; /* reference count */ - virConnectPtr conn; /* pointer back to the connection */ - char *pool; /* Pool name of owner */ - char *name; /* the storage vol external name */ - /* XXX currently abusing path for this. Ought not to be so evil */ - char key[PATH_MAX]; /* unique key for storage vol */ -}; - - - -/************************************************************************ - * * - * API for domain/connections (de)allocations and lookups * - * * - ************************************************************************/ - -virConnectPtr virGetConnect (void); -int virUnrefConnect (virConnectPtr conn); -virDomainPtr __virGetDomain (virConnectPtr conn, - const char *name, - const unsigned char *uuid); -int virUnrefDomain (virDomainPtr domain); -virNetworkPtr __virGetNetwork (virConnectPtr conn, - const char *name, - const unsigned char *uuid); -int virUnrefNetwork (virNetworkPtr network); - -virStoragePoolPtr __virGetStoragePool (virConnectPtr conn, - const char *name, - const unsigned char *uuid); -int virUnrefStoragePool (virStoragePoolPtr pool); -virStorageVolPtr __virGetStorageVol (virConnectPtr conn, - const char *pool, - const char *name, - const char *key); -int virUnrefStorageVol (virStorageVolPtr vol); - -#define virGetDomain(c,n,u) __virGetDomain((c),(n),(u)) -#define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u)) -#define virGetStoragePool(c,n,u) __virGetStoragePool((c),(n),(u)) -#define virGetStorageVol(c,p,n,u) __virGetStorageVol((c),(p),(n),(u)) - -#ifdef WITH_LIBVIRTD -int __virStateInitialize(void); -int __virStateCleanup(void); -int __virStateReload(void); -int __virStateActive(void); -#define virStateInitialize() __virStateInitialize() -#define virStateCleanup() __virStateCleanup() -#define virStateReload() __virStateReload() -#define virStateActive() __virStateActive() -#endif - -int __virDrvSupportsFeature (virConnectPtr conn, int feature); - -int __virDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, char **uri_out, unsigned long flags, const char *dname, unsigned long bandwidth); -int __virDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long bandwidth); -virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags); - -/** * Domain Event Notification */ diff -r 10d728ae8445 src/libvirt.c --- a/src/libvirt.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 20:10:40 2008 +0000 @@ -32,6 +32,8 @@ #endif #include "virterror_internal.h" +#include "datatypes.h" +#include "libvirt_internal.h" #include "driver.h" #include "uuid.h" @@ -66,6 +68,8 @@ * - use lock to protect against concurrent accesses ? * - use reference counting to guarantee coherent pointer state ? */ + +#define MAX_DRIVERS 10 static virDriverPtr virDriverTab[MAX_DRIVERS]; static int virDriverTabCount = 0; @@ -5560,3 +5564,5 @@ return 0; } + + diff -r 10d728ae8445 src/libvirt_internal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libvirt_internal.h Wed Oct 29 20:10:40 2008 +0000 @@ -0,0 +1,64 @@ +/* + * libvirt.h: publically exported APIs, not for public use + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __LIBVIRT_H_ +#define __LIBVIRT_H_ + +#include "internal.h" + + +#ifdef WITH_LIBVIRTD +int __virStateInitialize(void); +int __virStateCleanup(void); +int __virStateReload(void); +int __virStateActive(void); +#define virStateInitialize() __virStateInitialize() +#define virStateCleanup() __virStateCleanup() +#define virStateReload() __virStateReload() +#define virStateActive() __virStateActive() +#endif + +int __virDrvSupportsFeature (virConnectPtr conn, int feature); + +int __virDomainMigratePrepare (virConnectPtr dconn, + char **cookie, + int *cookielen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long bandwidth); +int __virDomainMigratePerform (virDomainPtr domain, + const char *cookie, + int cookielen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long bandwidth); +virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, + const char *dname, + const char *cookie, + int cookielen, + const char *uri, + unsigned long flags); + + +#endif diff -r 10d728ae8445 src/lxc_driver.c --- a/src/lxc_driver.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/lxc_driver.c Wed Oct 29 20:10:40 2008 +0000 @@ -36,6 +36,7 @@ #include <wait.h> #include "virterror_internal.h" +#include "datatypes.h" #include "lxc_conf.h" #include "lxc_container.h" #include "lxc_driver.h" diff -r 10d728ae8445 src/network_conf.c --- a/src/network_conf.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/network_conf.c Wed Oct 29 20:10:40 2008 +0000 @@ -34,6 +34,7 @@ #include <dirent.h> #include "virterror_internal.h" +#include "datatypes.h" #include "network_conf.h" #include "memory.h" #include "xml.h" diff -r 10d728ae8445 src/network_conf.h --- a/src/network_conf.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/network_conf.h Wed Oct 29 20:10:40 2008 +0000 @@ -23,6 +23,10 @@ #ifndef __NETWORK_CONF_H__ #define __NETWORK_CONF_H__ + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> #include "internal.h" diff -r 10d728ae8445 src/network_driver.c --- a/src/network_driver.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/network_driver.c Wed Oct 29 20:10:40 2008 +0000 @@ -45,6 +45,7 @@ #include <sys/ioctl.h> #include "virterror_internal.h" +#include "datatypes.h" #include "network_driver.h" #include "network_conf.h" #include "driver.h" diff -r 10d728ae8445 src/openvz_driver.c --- a/src/openvz_driver.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/openvz_driver.c Wed Oct 29 20:10:40 2008 +0000 @@ -48,6 +48,7 @@ #include <sys/wait.h> #include "virterror_internal.h" +#include "datatypes.h" #include "openvz_driver.h" #include "event.h" #include "buf.h" diff -r 10d728ae8445 src/proxy_internal.c --- a/src/proxy_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/proxy_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -23,6 +23,7 @@ #include <string.h> #include "virterror_internal.h" +#include "datatypes.h" #include "driver.h" #include "proxy_internal.h" #include "util.h" diff -r 10d728ae8445 src/proxy_internal.h --- a/src/proxy_internal.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/proxy_internal.h Wed Oct 29 20:10:40 2008 +0000 @@ -12,7 +12,7 @@ #ifndef __LIBVIR_PROXY_H__ #define __LIBVIR_PROXY_H__ -#include "libvirt/libvirt.h" +#include "internal.h" #define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn" #define PROXY_PROTO_VERSION 1 diff -r 10d728ae8445 src/qemu_driver.c --- a/src/qemu_driver.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/qemu_driver.c Wed Oct 29 20:10:40 2008 +0000 @@ -53,6 +53,7 @@ #endif #include "virterror_internal.h" +#include "datatypes.h" #include "qemu_driver.h" #include "qemu_conf.h" #include "c-ctype.h" diff -r 10d728ae8445 src/qparams.c --- a/src/qparams.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/qparams.c Wed Oct 29 20:10:40 2008 +0000 @@ -25,6 +25,8 @@ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> + +#include <libxml/uri.h> #include "virterror_internal.h" #include "buf.h" diff -r 10d728ae8445 src/remote_internal.c --- a/src/remote_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/remote_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -74,6 +74,7 @@ #endif #include "virterror_internal.h" +#include "datatypes.h" #include "driver.h" #include "buf.h" #include "qparams.h" diff -r 10d728ae8445 src/stats_linux.c --- a/src/stats_linux.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/stats_linux.c Wed Oct 29 20:10:40 2008 +0000 @@ -25,6 +25,7 @@ #endif #include "virterror_internal.h" +#include "datatypes.h" #include "util.h" #include "xen_unified.h" #include "stats_linux.h" diff -r 10d728ae8445 src/storage_conf.c --- a/src/storage_conf.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/storage_conf.c Wed Oct 29 20:10:40 2008 +0000 @@ -23,11 +23,6 @@ #include <config.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <libxml/uri.h> - #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> @@ -39,6 +34,7 @@ #include <string.h> #include "virterror_internal.h" +#include "datatypes.h" #include "storage_conf.h" #include "storage_backend.h" #include "xml.h" diff -r 10d728ae8445 src/storage_conf.h --- a/src/storage_conf.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/storage_conf.h Wed Oct 29 20:10:40 2008 +0000 @@ -24,7 +24,10 @@ #ifndef __VIR_STORAGE_CONF_H__ #define __VIR_STORAGE_CONF_H__ -#include <libvirt/libvirt.h> +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xpath.h> + #include "internal.h" /* Shared structs */ diff -r 10d728ae8445 src/storage_driver.c --- a/src/storage_driver.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/storage_driver.c Wed Oct 29 20:10:40 2008 +0000 @@ -33,6 +33,7 @@ #include <string.h> #include "virterror_internal.h" +#include "datatypes.h" #include "driver.h" #include "util.h" #include "storage_driver.h" diff -r 10d728ae8445 src/test.c --- a/src/test.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/test.c Wed Oct 29 20:10:40 2008 +0000 @@ -32,6 +32,7 @@ #include "virterror_internal.h" +#include "datatypes.h" #include "test.h" #include "buf.h" #include "util.h" diff -r 10d728ae8445 src/uuid.c --- a/src/uuid.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/uuid.c Wed Oct 29 20:10:40 2008 +0000 @@ -26,6 +26,7 @@ #include <errno.h> #include <fcntl.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> diff -r 10d728ae8445 src/veth.c --- a/src/veth.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/veth.c Wed Oct 29 20:10:40 2008 +0000 @@ -12,6 +12,7 @@ #include <config.h> #include <string.h> +#include <stdio.h> #include "veth.h" #include "internal.h" diff -r 10d728ae8445 src/virterror.c --- a/src/virterror.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/virterror.c Wed Oct 29 20:10:40 2008 +0000 @@ -16,6 +16,7 @@ #include <stdarg.h> #include "virterror_internal.h" +#include "datatypes.h" virError virLastErr = /* the last error */ { .code = 0, .domain = 0, .message = NULL, .level = VIR_ERR_NONE, diff -r 10d728ae8445 src/xen_internal.c --- a/src/xen_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xen_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -41,6 +41,7 @@ #include <xen/sched.h> #include "virterror_internal.h" +#include "datatypes.h" #include "driver.h" #include "util.h" #include "xen_unified.h" diff -r 10d728ae8445 src/xen_internal.h --- a/src/xen_internal.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xen_internal.h Wed Oct 29 20:10:40 2008 +0000 @@ -10,6 +10,8 @@ #ifndef __VIR_XEN_INTERNAL_H__ #define __VIR_XEN_INTERNAL_H__ + +#include <libxml/uri.h> #include "internal.h" #include "capabilities.h" diff -r 10d728ae8445 src/xen_unified.c --- a/src/xen_unified.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xen_unified.c Wed Oct 29 20:10:40 2008 +0000 @@ -28,7 +28,7 @@ #include <libxml/uri.h> #include "virterror_internal.h" - +#include "datatypes.h" #include "xen_unified.h" #include "xen_internal.h" diff -r 10d728ae8445 src/xen_unified.h --- a/src/xen_unified.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xen_unified.h Wed Oct 29 20:10:40 2008 +0000 @@ -13,6 +13,7 @@ #include "internal.h" #include "capabilities.h" +#include "driver.h" #ifndef HAVE_WINSOCK2_H #include <sys/un.h> @@ -29,6 +30,8 @@ #define XEN_UNIFIED_XS_OFFSET 3 #define XEN_UNIFIED_XM_OFFSET 4 #define XEN_UNIFIED_NR_DRIVERS 5 + +#define MIN_XEN_GUEST_SIZE 64 /* 64 megabytes */ /* _xenUnifiedDriver: * diff -r 10d728ae8445 src/xend_internal.c --- a/src/xend_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xend_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -33,6 +33,7 @@ #include <errno.h> #include "virterror_internal.h" +#include "datatypes.h" #include "xend_internal.h" #include "driver.h" #include "util.h" diff -r 10d728ae8445 src/xend_internal.h --- a/src/xend_internal.h Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xend_internal.h Wed Oct 29 20:10:40 2008 +0000 @@ -19,6 +19,7 @@ #include <sys/types.h> #include <stdint.h> #include <stdbool.h> +#include <libxml/uri.h> #include "internal.h" #include "capabilities.h" diff -r 10d728ae8445 src/xm_internal.c --- a/src/xm_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xm_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -36,6 +36,7 @@ #include <xen/dom0_ops.h> #include "virterror_internal.h" +#include "datatypes.h" #include "xm_internal.h" #include "xen_unified.h" #include "xend_internal.h" diff -r 10d728ae8445 src/xs_internal.c --- a/src/xs_internal.c Wed Oct 29 20:09:50 2008 +0000 +++ b/src/xs_internal.c Wed Oct 29 20:10:40 2008 +0000 @@ -27,6 +27,7 @@ #include <xs.h> #include "virterror_internal.h" +#include "datatypes.h" #include "driver.h" #include "xen_unified.h" #include "xs_internal.h" diff -r 10d728ae8445 tests/xmconfigtest.c --- a/tests/xmconfigtest.c Wed Oct 29 20:09:50 2008 +0000 +++ b/tests/xmconfigtest.c Wed Oct 29 20:10:40 2008 +0000 @@ -30,6 +30,7 @@ #ifdef WITH_XEN #include "internal.h" +#include "datatypes.h" #include "xen_unified.h" #include "xm_internal.h" #include "testutils.h" -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:37:34PM +0000, Daniel P. Berrange wrote:
Following Daniel's feedback yesterday, instead of moving the virGetDomain & related functions from hash.c into libvirt.c, I create a new file to deal with all our public datatypes. I call it datatypes.h, datatypes.c
I don't care too much about the name, datatypes.[ch] sounds good :-)
A bunch of stuff moves out of hash.c and internal.h into these two files. Quite a few internal driver files need updates to add an extra #include line. There should be no functional changes here [...] --- a/po/POTFILES.in Wed Oct 29 20:09:50 2008 +0000 +++ b/po/POTFILES.in Wed Oct 29 20:10:40 2008 +0000 @@ -3,8 +3,8 @@ qemud/remote.c src/conf.c src/console.c +src/datatypes.c src/domain_conf.c -src/hash.c src/iptables.c src/libvirt.c
Hum, this means I should push the .pot file soonish after the patches are applied Patch looks fine, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This is a re-diff of the patch I sent yesterday to just move the domain events code into its own separate file. b/src/domain_event.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++ b/src/domain_event.h | 83 ++++++++++++++++++ qemud/event.c | 8 - qemud/event.h | 7 + src/Makefile.am | 1 src/internal.h | 72 --------------- src/libvirt.c | 203 -------------------------------------------- src/qemu_conf.h | 1 src/remote_internal.c | 1 9 files changed, 327 insertions(+), 278 deletions(-) Daniel diff -r f9233a3621e6 qemud/event.c --- a/qemud/event.c Wed Oct 29 15:51:13 2008 +0000 +++ b/qemud/event.c Wed Oct 29 15:58:26 2008 +0000 @@ -489,7 +489,7 @@ } int -__virEventHandleTypeToPollEvent(virEventHandleType events) +virEventHandleTypeToPollEvent(int events) { int ret = 0; if(events & VIR_EVENT_HANDLE_READABLE) @@ -503,10 +503,10 @@ return ret; } -virEventHandleType -__virPollEventToEventHandleType(int events) +int +virPollEventToEventHandleType(int events) { - virEventHandleType ret = 0; + int ret = 0; if(events & POLLIN) ret |= VIR_EVENT_HANDLE_READABLE; if(events & POLLOUT) diff -r f9233a3621e6 qemud/event.h --- a/qemud/event.h Wed Oct 29 15:51:13 2008 +0000 +++ b/qemud/event.h Wed Oct 29 15:58:26 2008 +0000 @@ -105,4 +105,11 @@ */ int virEventRunOnce(void); +int +virEventHandleTypeToPollEvent(int events); +int +virPollEventToEventHandleType(int events); + + + #endif /* __VIRTD_EVENT_H__ */ diff -r f9233a3621e6 src/Makefile.am --- a/src/Makefile.am Wed Oct 29 15:51:13 2008 +0000 +++ b/src/Makefile.am Wed Oct 29 15:58:26 2008 +0000 @@ -150,6 +150,7 @@ driver.h \ internal.h \ datatypes.c datatypes.h \ + domain_event.c domain_event.h \ libvirt.c libvirt_internal.h \ $(GENERIC_LIB_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ diff -r f9233a3621e6 src/domain_event.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/domain_event.c Wed Oct 29 15:58:26 2008 +0000 @@ -0,0 +1,229 @@ +/* + * domain_event.c: domain event queue processing helpers + * + * Copyright (C) 2008 VirtualIron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Ben Guthro + */ + +#include <config.h> + +#include "domain_event.h" +#include "datatypes.h" +#include "memory.h" + + +/** + * virDomainEventCallbackListFree: + * @list: event callback list head + * + * Free the memory in the domain event callback list + */ +void +virDomainEventCallbackListFree(virDomainEventCallbackListPtr list) +{ + int i; + for (i=0; i<list->count; i++) { + VIR_FREE(list->callbacks[i]); + } + VIR_FREE(list); +} +/** + * virDomainEventCallbackListRemove: + * @conn: pointer to the connection + * @cbList: the list + * @callback: the callback to remove + * + * Internal function to remove a callback from a virDomainEventCallbackListPtr + */ +int +virDomainEventCallbackListRemove(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback) +{ + int i; + for (i = 0 ; i < cbList->count ; i++) { + if(cbList->callbacks[i]->cb == callback && + cbList->callbacks[i]->conn == conn) { + virUnrefConnect(cbList->callbacks[i]->conn); + VIR_FREE(cbList->callbacks[i]); + + if (i < (cbList->count - 1)) + memmove(cbList->callbacks + i, + cbList->callbacks + i + 1, + sizeof(*(cbList->callbacks)) * + (cbList->count - (i + 1))); + + if (VIR_REALLOC_N(cbList->callbacks, + cbList->count - 1) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + cbList->count--; + + return 0; + } + } + return -1; +} + +/** + * virDomainEventCallbackListAdd: + * @conn: pointer to the connection + * @cbList: the list + * @callback: the callback to add + * @opaque: opaque data tio pass to callback + * + * Internal function to add a callback from a virDomainEventCallbackListPtr + */ +int +virDomainEventCallbackListAdd(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback, + void *opaque) +{ + virDomainEventCallbackPtr event; + int n; + + /* Check incoming */ + if ( !cbList ) { + return -1; + } + + /* check if we already have this callback on our list */ + for (n=0; n < cbList->count; n++) { + if(cbList->callbacks[n]->cb == callback && + conn == cbList->callbacks[n]->conn) { + DEBUG0("WARNING: Callback already tracked"); + return -1; + } + } + /* Allocate new event */ + if (VIR_ALLOC(event) < 0) { + DEBUG0("Error allocating event"); + return -1; + } + event->conn = conn; + event->cb = callback; + event->opaque = opaque; + + /* Make space on list */ + n = cbList->count; + if (VIR_REALLOC_N(cbList->callbacks, n + 1) < 0) { + DEBUG0("Error reallocating list"); + VIR_FREE(event); + return -1; + } + + event->conn->refs++; + + cbList->callbacks[n] = event; + cbList->count++; + return 0; +} + +/** + * virDomainEventQueueFree: + * @queue: pointer to the queue + * + * Free the memory in the queue. We process this like a list here + */ +void +virDomainEventQueueFree(virDomainEventQueuePtr queue) +{ + int i; + for ( i=0 ; i<queue->count ; i++ ) { + VIR_FREE(queue->events[i]); + } + VIR_FREE(queue); +} + +/** + * virDomainEventCallbackQueuePop: + * @evtQueue: the queue of events + * + * Internal function to pop off, and return the front of the queue + * NOTE: The caller is responsible for freeing the returned object + * + * Returns: virDomainEventPtr on success NULL on failure. + */ +virDomainEventPtr +virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue) +{ + virDomainEventPtr ret; + + if(!evtQueue || evtQueue->count == 0 ) + return NULL; + + ret = evtQueue->events[0]; + + memmove(evtQueue->events, + evtQueue->events + 1, + sizeof(*(evtQueue->events)) * + (evtQueue->count - 1)); + + if (VIR_REALLOC_N(evtQueue->events, + evtQueue->count - 1) < 0) { + ; /* Failure to reduce memory allocation isn't fatal */ + } + evtQueue->count--; + + return ret; +} + +/** + * virDomainEventCallbackQueuePush: + * @evtQueue: the dom event queue + * @dom: the domain to add + * @event: the event to add + * + * Internal function to push onto the back of an virDomainEventQueue + * + * Returns: 0 on success, -1 on failure + */ +int +virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, + virDomainPtr dom, + virDomainEventType event) +{ + virDomainEventPtr domEvent; + + /* Check incoming */ + if ( !evtQueue ) { + return -1; + } + + /* Allocate new event */ + if (VIR_ALLOC(domEvent) < 0) { + DEBUG0("Error allocating event"); + return -1; + } + domEvent->dom = dom; + domEvent->event = event; + + /* Make space on queue */ + if (VIR_REALLOC_N(evtQueue->events, + evtQueue->count + 1) < 0) { + DEBUG0("Error reallocating queue"); + VIR_FREE(domEvent); + return -1; + } + + evtQueue->events[evtQueue->count] = domEvent; + evtQueue->count++; + return 0; +} + diff -r f9233a3621e6 src/domain_event.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/domain_event.h Wed Oct 29 15:58:26 2008 +0000 @@ -0,0 +1,83 @@ +/* + * domain_event.h: domain event queue processing helpers + * + * Copyright (C) 2008 VirtualIron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Ben Guthro + */ + +#include "internal.h" + + +#ifndef __DOMAIN_EVENT_H__ +#define __DOMAIN_EVENT_H__ + +struct _virDomainEventCallback { + virConnectPtr conn; + virConnectDomainEventCallback cb; + void *opaque; +}; +typedef struct _virDomainEventCallback virDomainEventCallback; +typedef virDomainEventCallback *virDomainEventCallbackPtr; + +struct _virDomainEventCallbackList { + unsigned int count; + virDomainEventCallbackPtr *callbacks; +}; +typedef struct _virDomainEventCallbackList virDomainEventCallbackList; +typedef virDomainEventCallbackList *virDomainEventCallbackListPtr; + +void virDomainEventCallbackListFree(virDomainEventCallbackListPtr list); + +int virDomainEventCallbackListAdd(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback, + void *opaque); + +int virDomainEventCallbackListRemove(virConnectPtr conn, + virDomainEventCallbackListPtr cbList, + virConnectDomainEventCallback callback); + +/** + * Dispatching domain events that come in while + * in a call / response rpc + */ +struct _virDomainEvent { + virDomainPtr dom; + virDomainEventType event; +}; +typedef struct _virDomainEvent virDomainEvent; +typedef virDomainEvent *virDomainEventPtr; + +struct _virDomainEventQueue { + unsigned int count; + virDomainEventPtr *events; +}; +typedef struct _virDomainEventQueue virDomainEventQueue; +typedef virDomainEventQueue *virDomainEventQueuePtr; + +int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, + virDomainPtr dom, + virDomainEventType event); + +virDomainEventPtr +virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue); + +void virDomainEventQueueFree(virDomainEventQueuePtr queue); + + +#endif diff -r f9233a3621e6 src/internal.h --- a/src/internal.h Wed Oct 29 15:51:13 2008 +0000 +++ b/src/internal.h Wed Oct 29 15:58:26 2008 +0000 @@ -139,76 +139,4 @@ fprintf(stderr, "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__); -/** - * Domain Event Notification - */ - -struct _virDomainEventCallback { - virConnectPtr conn; - virConnectDomainEventCallback cb; - void *opaque; -}; -typedef struct _virDomainEventCallback virDomainEventCallback; -typedef virDomainEventCallback *virDomainEventCallbackPtr; - -struct _virDomainEventCallbackList { - unsigned int count; - virDomainEventCallbackPtr *callbacks; -}; -typedef struct _virDomainEventCallbackList virDomainEventCallbackList; -typedef virDomainEventCallbackList *virDomainEventCallbackListPtr; - -void __virDomainEventCallbackListFree(virDomainEventCallbackListPtr list); -#define virDomainEventCallbackListFree(x) __virDomainEventCallbackListFree(x) - -int __virDomainEventCallbackListAdd(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback, - void *opaque); -#define virDomainEventCallbackListAdd(a,b,c,d) \ - __virDomainEventCallbackListAdd((a),(b),(c),(d)) - -int __virDomainEventCallbackListRemove(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback); -#define virDomainEventCallbackListRemove(a,b,c) \ - __virDomainEventCallbackListRemove((a),(b),(c)) - -int __virEventHandleTypeToPollEvent(virEventHandleType events); -#define virEventHandleTypeToPollEvent(x) __virEventHandleTypeToPollEvent(x) - -virEventHandleType __virPollEventToEventHandleType(int events); -#define virPollEventToEventHandleType(x) __virPollEventToEventHandleType(x) - -/** - * Dispatching domain events that come in while - * in a call / response rpc - */ -struct _virDomainEvent { - virDomainPtr dom; - virDomainEventType event; -}; -typedef struct _virDomainEvent virDomainEvent; -typedef virDomainEvent *virDomainEventPtr; - -struct _virDomainEventQueue { - unsigned int count; - virDomainEventPtr *events; -}; -typedef struct _virDomainEventQueue virDomainEventQueue; -typedef virDomainEventQueue *virDomainEventQueuePtr; - -int __virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, - virDomainPtr dom, - virDomainEventType event); -#define virDomainEventCallbackQueuePush(a,b,c) \ - __virDomainEventCallbackQueuePush((a),(b),(c)) - -virDomainEventPtr -__virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue); -#define virDomainEventCallbackQueuePop(x) __virDomainEventCallbackQueuePop(x) - -void __virDomainEventQueueFree(virDomainEventQueuePtr queue); -#define virDomainEventQueueFree(x) __virDomainEventQueueFree(x) - #endif /* __VIR_INTERNAL_H__ */ diff -r f9233a3621e6 src/libvirt.c --- a/src/libvirt.c Wed Oct 29 15:51:13 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 15:58:26 2008 +0000 @@ -5364,205 +5364,4 @@ return -1; } -/** - * __virDomainEventCallbackListFree: - * @list: event callback list head - * - * Free the memory in the domain event callback list - */ -void -__virDomainEventCallbackListFree(virDomainEventCallbackListPtr list) -{ - int i; - for (i=0; i<list->count; i++) { - VIR_FREE(list->callbacks[i]); - } - VIR_FREE(list); -} -/** - * __virDomainEventCallbackListRemove: - * @conn: pointer to the connection - * @cbList: the list - * @callback: the callback to remove - * - * Internal function to remove a callback from a virDomainEventCallbackListPtr - */ -int -__virDomainEventCallbackListRemove(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback) -{ - int i; - for (i = 0 ; i < cbList->count ; i++) { - if(cbList->callbacks[i]->cb == callback && - cbList->callbacks[i]->conn == conn) { - virUnrefConnect(cbList->callbacks[i]->conn); - VIR_FREE(cbList->callbacks[i]); - - if (i < (cbList->count - 1)) - memmove(cbList->callbacks + i, - cbList->callbacks + i + 1, - sizeof(*(cbList->callbacks)) * - (cbList->count - (i + 1))); - - if (VIR_REALLOC_N(cbList->callbacks, - cbList->count - 1) < 0) { - ; /* Failure to reduce memory allocation isn't fatal */ - } - cbList->count--; - - return 0; - } - } - return -1; -} - -/** - * __virDomainEventCallbackListAdd: - * @conn: pointer to the connection - * @cbList: the list - * @callback: the callback to add - * @opaque: opaque data tio pass to callback - * - * Internal function to add a callback from a virDomainEventCallbackListPtr - */ -int -__virDomainEventCallbackListAdd(virConnectPtr conn, - virDomainEventCallbackListPtr cbList, - virConnectDomainEventCallback callback, - void *opaque) -{ - virDomainEventCallbackPtr event; - int n; - - /* Check incoming */ - if ( !cbList ) { - return -1; - } - - /* check if we already have this callback on our list */ - for (n=0; n < cbList->count; n++) { - if(cbList->callbacks[n]->cb == callback && - conn == cbList->callbacks[n]->conn) { - DEBUG0("WARNING: Callback already tracked"); - return -1; - } - } - /* Allocate new event */ - if (VIR_ALLOC(event) < 0) { - DEBUG0("Error allocating event"); - return -1; - } - event->conn = conn; - event->cb = callback; - event->opaque = opaque; - - /* Make space on list */ - n = cbList->count; - if (VIR_REALLOC_N(cbList->callbacks, n + 1) < 0) { - DEBUG0("Error reallocating list"); - VIR_FREE(event); - return -1; - } - - event->conn->refs++; - - cbList->callbacks[n] = event; - cbList->count++; - return 0; -} - -/** - * __virDomainEventQueueFree: - * @queue: pointer to the queue - * - * Free the memory in the queue. We process this like a list here - */ -void -__virDomainEventQueueFree(virDomainEventQueuePtr queue) -{ - int i; - for ( i=0 ; i<queue->count ; i++ ) { - VIR_FREE(queue->events[i]); - } - VIR_FREE(queue); -} - -/** - * __virDomainEventCallbackQueuePop: - * @evtQueue: the queue of events - * - * Internal function to pop off, and return the front of the queue - * NOTE: The caller is responsible for freeing the returned object - * - * Returns: virDomainEventPtr on success NULL on failure. - */ -virDomainEventPtr -__virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue) -{ - virDomainEventPtr ret; - - if(!evtQueue || evtQueue->count == 0 ) - return NULL; - - ret = evtQueue->events[0]; - - memmove(evtQueue->events, - evtQueue->events + 1, - sizeof(*(evtQueue->events)) * - (evtQueue->count - 1)); - - if (VIR_REALLOC_N(evtQueue->events, - evtQueue->count - 1) < 0) { - ; /* Failure to reduce memory allocation isn't fatal */ - } - evtQueue->count--; - - return ret; -} - -/** - * __virDomainEventCallbackQueuePush: - * @evtQueue: the dom event queue - * @dom: the domain to add - * @event: the event to add - * - * Internal function to push onto the back of an virDomainEventQueue - * - * Returns: 0 on success, -1 on failure - */ -int -__virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue, - virDomainPtr dom, - virDomainEventType event) -{ - virDomainEventPtr domEvent; - - /* Check incoming */ - if ( !evtQueue ) { - return -1; - } - - /* Allocate new event */ - if (VIR_ALLOC(domEvent) < 0) { - DEBUG0("Error allocating event"); - return -1; - } - domEvent->dom = dom; - domEvent->event = event; - - /* Make space on queue */ - if (VIR_REALLOC_N(evtQueue->events, - evtQueue->count + 1) < 0) { - DEBUG0("Error reallocating queue"); - VIR_FREE(domEvent); - return -1; - } - - evtQueue->events[evtQueue->count] = domEvent; - evtQueue->count++; - return 0; -} - - - + diff -r f9233a3621e6 src/qemu_conf.h --- a/src/qemu_conf.h Wed Oct 29 15:51:13 2008 +0000 +++ b/src/qemu_conf.h Wed Oct 29 15:58:26 2008 +0000 @@ -31,6 +31,7 @@ #include "capabilities.h" #include "network_conf.h" #include "domain_conf.h" +#include "domain_event.h" #define qemudDebug(fmt, ...) do {} while(0) diff -r f9233a3621e6 src/remote_internal.c --- a/src/remote_internal.c Wed Oct 29 15:51:13 2008 +0000 +++ b/src/remote_internal.c Wed Oct 29 15:58:26 2008 +0000 @@ -75,6 +75,7 @@ #include "virterror_internal.h" #include "datatypes.h" +#include "domain_event.h" #include "driver.h" #include "buf.h" #include "qparams.h" -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:38:08PM +0000, Daniel P. Berrange wrote:
This is a re-diff of the patch I sent yesterday to just move the domain events code into its own separate file.
Yup, fine +1, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The configure script lets users turn on/of individual drivers. Their choices get fed into a LIBVIRT_FEATURES macro, which has one or more -DWITH_XEN -DWITH_OPENVZ, etc, etc. The compiler args become rather long when we have all the drivers enabled. So this patch tweaks the configure file to instead put all these WITH_XEN, WITH_QEMU macros into the config.h file. Secondly, the Makefile.am has a few places where we do nested conditionals to determine whether to build QEMU, eg if WITH_LIBVIRTD if WITH_QEMU This patch also tweaks the configure script so that WITH_QEMU is never defined, unless WITH_LIBVIRTD is also defined. Now the makefile.am can just do if WITH_QEMU which makes things a little more readable, and helps avoid errors where we miss the WITH_LIBVIRTD wrapper. There is no functional code change here, its all just playing with the way makefile/macro conditionals are done. configure.in | 83 +++++++++++++++++++++++++++++++++--------------------- proxy/Makefile.am | 4 +- qemud/Makefile.am | 2 - src/Makefile.am | 29 +++++++++--------- src/libvirt.c | 2 - tests/Makefile.am | 4 -- 6 files changed, 70 insertions(+), 54 deletions(-) Daniel diff -r 0960752d24df configure.in --- a/configure.in Wed Oct 29 20:10:43 2008 +0000 +++ b/configure.in Wed Oct 29 20:10:49 2008 +0000 @@ -232,59 +232,69 @@ AC_PATH_PROG([IPTABLES_PATH], [iptables], /sbin/iptables, [/usr/sbin:$PATH]) AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IPTABLES_PATH", [path to iptables binary]) -dnl -dnl Specify the xen-distribution directory to be able to compile on a -dnl non-xenified host -dnl -AC_ARG_WITH([xen-distdir], [AC_HELP_STRING([--with-xen-distdir=path], - [distribution directory of Xen, default /usr])]) -if test "x$with_xen_distdir" != "x" -then -CPPFLAGS="$CPPFLAGS -I$withval/install/usr/include" -LDFLAGS="$LDFLAGS -L$withval/install/usr/lib -L$withval/install/usr/lib64" -fi - -LIBVIRT_FEATURES= -WITH_XEN=0 - if test "$with_openvz" = "yes"; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_OPENVZ" + AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled]) fi AM_CONDITIONAL([WITH_OPENVZ], [test "$with_openvz" = "yes"]) +if test "$with_libvirtd" = "no" ; then + with_lxc=no +fi if test "$with_lxc" = "yes" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_LXC" + AC_DEFINE_UNQUOTED([WITH_LXC], 1, [whether LXC driver is enabled]) fi AM_CONDITIONAL([WITH_LXC], [test "$with_lxc" = "yes"]) +if test "$with_libvirtd" = "no" ; then + with_qemu=no +fi if test "$with_qemu" = "yes" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_QEMU" + AC_DEFINE_UNQUOTED([WITH_QEMU], 1, [whether QEMU driver is enabled]) fi AM_CONDITIONAL([WITH_QEMU], [test "$with_qemu" = "yes"]) if test "$with_test" = "yes" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_TEST" + AC_DEFINE_UNQUOTED([WITH_TEST], 1, [whether Test driver is enabled]) fi AM_CONDITIONAL([WITH_TEST], [test "$with_test" = "yes"]) if test "$with_remote" = "yes" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_REMOTE" + AC_DEFINE_UNQUOTED([WITH_REMOTE], 1, [whether Remote driver is enabled]) fi AM_CONDITIONAL([WITH_REMOTE], [test "$with_remote" = "yes"]) if test "$with_libvirtd" = "yes" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_LIBVIRTD" + AC_DEFINE_UNQUOTED([WITH_LIBVIRTD], 1, [whether libvirtd daemon is enabled]) fi AM_CONDITIONAL([WITH_LIBVIRTD], [test "$with_libvirtd" = "yes"]) -if test "$with_xen" = "yes" ; then - dnl search for the Xen store library - AC_SEARCH_LIBS(xs_read, [xenstore], - [WITH_XEN=1], - [AC_MSG_RESULT([Xen store library not found])]) - if test "$WITH_XEN" != "0" ; then - LIBVIRT_FEATURES="$LIBVIRT_FEATURES -DWITH_XEN" +XEN_LIBS="" +XEN_CFLAGS="" +dnl search for the Xen store library +if test "$with_xen" != "no" ; then + if test "$with_xen" != "yes" -a "$with_xen" != "check" ; then + XEN_CFLAGS="-I$with_xen/include" + XEN_LIBS="-L$with_xen/lib64 -L$with_xen/lib" fi + fail=0 + old_LIBS="$LIBS" + old_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $XEN_CFLAGS" + LIBS="$LIBS $XEN_LIBS" + AC_CHECK_LIB([xenstore], [xs_read], [ + with_xen=yes + XEN_LIBS="$XEN_LIBS -lxenstore" + ],[ + if test "$with_xen" = "check" ; then + with_xen=no + else + with_xen=no + fail=1 + fi + ]) + + test $fail = 1 && + AC_MSG_ERROR([You must install the Xen development package to compile Xen driver with -lxenstore]) AC_CHECK_HEADERS([xen/xen.h xen/version.h xen/dom0_ops.h],,[ AC_MSG_ERROR([Cannot find standard Xen headers. Is xen-devel installed?]) @@ -307,8 +317,15 @@ #include <stdint.h> #include <xen/xen.h> ]) + LIBS="$old_LIBS" + CFLAGS="$old_CFLAGS" fi -AM_CONDITIONAL([WITH_XEN], [test "$WITH_XEN" = "1"]) +if test "$with_xen" = "yes"; then + AC_DEFINE_UNQUOTED([WITH_XEN], 1, [whether Xen driver is enabled]) +fi +AM_CONDITIONAL([WITH_XEN], [test "$with_xen" = "yes"]) +AC_SUBST([XEN_CFLAGS]) +AC_SUBST([XEN_LIBS]) dnl dnl check for kernel headers required by src/bridge.c @@ -640,9 +657,6 @@ fi AC_SUBST([READLINE_CFLAGS]) AC_SUBST([VIRSH_LIBS]) - -AC_SUBST([WITH_XEN]) -AC_SUBST([LIBVIRT_FEATURES]) AC_ARG_WITH([network], @@ -1124,6 +1138,11 @@ else AC_MSG_NOTICE([ numactl: no]) fi +if test "$with_xen" = "yes" ; then +AC_MSG_NOTICE([ xen: $XEN_CFLAGS $XEN_LIBS]) +else +AC_MSG_NOTICE([ xen: no]) +fi AC_MSG_NOTICE([]) AC_MSG_NOTICE([Test suite]) AC_MSG_NOTICE([]) diff -r 0960752d24df proxy/Makefile.am --- a/proxy/Makefile.am Wed Oct 29 20:10:43 2008 +0000 +++ b/proxy/Makefile.am Wed Oct 29 20:10:49 2008 +0000 @@ -5,7 +5,7 @@ -I$(top_builddir)/include -I@top_srcdir@/include \ -I@top_srcdir@/proxy -I@top_srcdir@/src @LIBXML_CFLAGS@ \ -DPROXY -DLOCALEBASEDIR=\""$(datadir)/locale"\" \ - -DGETTEXT_PACKAGE=\"$(PACKAGE)\" $(WARN_CFLAGS) $(LIBVIRT_FEATURES) + -DGETTEXT_PACKAGE=\"$(PACKAGE)\" $(WARN_CFLAGS) $(XEN_CFLAGS) libexec_PROGRAMS = libvirt_proxy @@ -19,7 +19,7 @@ @top_srcdir@/src/util.c \ @top_srcdir@/src/event.c \ @top_srcdir@/src/uuid.c -libvirt_proxy_LDFLAGS = $(WARN_CFLAGS) +libvirt_proxy_LDFLAGS = $(WARN_CFLAGS) $(XEN_LIBS) libvirt_proxy_DEPENDENCIES = libvirt_proxy_LDADD = ../gnulib/lib/libgnu.la diff -r 0960752d24df qemud/Makefile.am --- a/qemud/Makefile.am Wed Oct 29 20:10:43 2008 +0000 +++ b/qemud/Makefile.am Wed Oct 29 20:10:49 2008 +0000 @@ -1,6 +1,4 @@ ## Process this file with automake to produce Makefile.in - -INCLUDES = $(LIBVIRT_FEATURES) DAEMON_SOURCES = \ event.c event.h \ diff -r 0960752d24df src/Makefile.am --- a/src/Makefile.am Wed Oct 29 20:10:43 2008 +0000 +++ b/src/Makefile.am Wed Oct 29 20:10:49 2008 +0000 @@ -10,14 +10,15 @@ $(SASL_CFLAGS) \ $(SELINUX_CFLAGS) \ $(NUMACTL_CFLAGS) \ + $(XEN_CFLAGS) \ -DBINDIR=\""$(libexecdir)"\" \ -DSBINDIR=\""$(sbindir)"\" \ -DSYSCONF_DIR="\"$(sysconfdir)\"" \ -DLOCALEBASEDIR=\""$(datadir)/locale"\" \ -DLOCAL_STATE_DIR=\""$(localstatedir)"\" \ -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ - $(WARN_CFLAGS) \ - $(LIBVIRT_FEATURES) + $(WARN_CFLAGS) + DEPS = libvirt.la LDADDS = @STATIC_BINARIES@ $(WARN_CFLAGS) libvirt.la ../gnulib/lib/libgnu.la VIRSH_LIBS = @VIRSH_LIBS@ @@ -48,7 +49,6 @@ iptables.c iptables.h \ memory.c memory.h \ qparams.c qparams.h \ - stats_linux.c stats_linux.h \ uuid.c uuid.h \ util.c util.h \ virterror.c virterror_internal.h \ @@ -151,13 +151,13 @@ internal.h \ datatypes.c datatypes.h \ domain_event.c domain_event.h \ + stats_linux.c stats_linux.h \ libvirt.c libvirt_internal.h \ $(GENERIC_LIB_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ $(NETWORK_CONF_SOURCES) \ $(STORAGE_CONF_SOURCES) -# Drivers usable outside daemon context if WITH_TEST libvirt_la_SOURCES += $(TEST_DRIVER_SOURCES) endif @@ -174,20 +174,22 @@ libvirt_la_SOURCES += $(OPENVZ_DRIVER_SOURCES) endif -# Drivers usable inside daemon context -if WITH_LIBVIRTD -if WITH_NETWORK -libvirt_la_SOURCES += $(NETWORK_DRIVER_SOURCES) -endif -libvirt_la_SOURCES += $(STORAGE_DRIVER_SOURCES) -libvirt_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) - if WITH_QEMU libvirt_la_SOURCES += $(QEMU_DRIVER_SOURCES) endif if WITH_LXC libvirt_la_SOURCES += $(LXC_DRIVER_SOURCES) +endif + + +if WITH_NETWORK +libvirt_la_SOURCES += $(NETWORK_DRIVER_SOURCES) +endif + +if WITH_STORAGE_DIR +libvirt_la_SOURCES += $(STORAGE_DRIVER_SOURCES) +libvirt_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif if WITH_STORAGE_LVM @@ -200,7 +202,6 @@ if WITH_STORAGE_DISK libvirt_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES) -endif endif # Add all conditional sources just in case... @@ -220,7 +221,7 @@ libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(SELINUX_LIBS) \ - $(NUMACTL_LIBS) \ + $(NUMACTL_LIBS) $(XEN_LIBS) \ @CYGWIN_EXTRA_LIBADD@ ../gnulib/lib/libgnu.la libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \ -version-info @LIBVIRT_VERSION_INFO@ \ diff -r 0960752d24df src/libvirt.c --- a/src/libvirt.c Wed Oct 29 20:10:43 2008 +0000 +++ b/src/libvirt.c Wed Oct 29 20:10:49 2008 +0000 @@ -289,7 +289,6 @@ #ifdef WITH_XEN if (xenUnifiedRegister () == -1) return -1; #endif -#ifdef WITH_LIBVIRTD #ifdef WITH_QEMU if (qemudRegister() == -1) return -1; #endif @@ -302,6 +301,7 @@ #ifdef WITH_NETWORK if (networkRegister() == -1) return -1; #endif +#ifdef WITH_STORAGE_DIR if (storageRegister() == -1) return -1; #endif #ifdef WITH_REMOTE diff -r 0960752d24df tests/Makefile.am --- a/tests/Makefile.am Wed Oct 29 20:10:43 2008 +0000 +++ b/tests/Makefile.am Wed Oct 29 20:10:49 2008 +0000 @@ -15,11 +15,9 @@ $(GNUTLS_CFLAGS) \ $(SASL_CFLAGS) \ $(SELINUX_CFLAGS) \ - -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199506L \ -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ $(COVERAGE_CFLAGS) \ - $(WARN_CFLAGS) \ - $(LIBVIRT_FEATURES) + $(WARN_CFLAGS) LDADDS = \ @STATIC_BINARIES@ \ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:38:56PM +0000, Daniel P. Berrange wrote:
The configure script lets users turn on/of individual drivers. Their choices get fed into a LIBVIRT_FEATURES macro, which has one or more -DWITH_XEN -DWITH_OPENVZ, etc, etc. The compiler args become rather long when we have all the drivers enabled. So this patch tweaks the configure file to instead put all these WITH_XEN, WITH_QEMU macros into the config.h file.
Secondly, the Makefile.am has a few places where we do nested conditionals to determine whether to build QEMU, eg
if WITH_LIBVIRTD if WITH_QEMU
This patch also tweaks the configure script so that WITH_QEMU is never defined, unless WITH_LIBVIRTD is also defined. Now the makefile.am can just do
if WITH_QEMU
which makes things a little more readable, and helps avoid errors where we miss the WITH_LIBVIRTD wrapper.
There is no functional code change here, its all just playing with the way makefile/macro conditionals are done.
Hum, this can get a bit crazy, I hope we will never get to the 2 pages of --with/without options of libxml2 (but we are getting closer every month) and while it easilly get impossible to test all combination, since we are doing background builds of HEAD every night, would it be possible to at least test compilation with some of the main options enabled or disabled. The mingw compile tests the bare minimum. Maybe a compile with only each of the hypervisor activated, and maybe one without avahi/SELinux/polkit/numactl to test compilation in a restricted environment, would be useful to catch this kind of troubles. Patch looks fine, the Xen configure.in changes are a bit hard to follow, I hope we will be able to give it some testing ... +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Thu, Oct 30, 2008 at 03:44:20PM +0100, Daniel Veillard wrote:
On Thu, Oct 30, 2008 at 01:38:56PM +0000, Daniel P. Berrange wrote:
The configure script lets users turn on/of individual drivers. Their choices get fed into a LIBVIRT_FEATURES macro, which has one or more -DWITH_XEN -DWITH_OPENVZ, etc, etc. The compiler args become rather long when we have all the drivers enabled. So this patch tweaks the configure file to instead put all these WITH_XEN, WITH_QEMU macros into the config.h file.
Secondly, the Makefile.am has a few places where we do nested conditionals to determine whether to build QEMU, eg
if WITH_LIBVIRTD if WITH_QEMU
This patch also tweaks the configure script so that WITH_QEMU is never defined, unless WITH_LIBVIRTD is also defined. Now the makefile.am can just do
if WITH_QEMU
which makes things a little more readable, and helps avoid errors where we miss the WITH_LIBVIRTD wrapper.
There is no functional code change here, its all just playing with the way makefile/macro conditionals are done.
Hum, this can get a bit crazy, I hope we will never get to the 2 pages of --with/without options of libxml2 (but we are getting closer every month) and while it easilly get impossible to test all combination, since we are doing background builds of HEAD every night, would it be possible to at least test compilation with some of the main options enabled or disabled. The mingw compile tests the bare minimum. Maybe a compile with only each of the hypervisor activated, and maybe one without avahi/SELinux/polkit/numactl to test compilation in a restricted environment, would be useful to catch this kind of troubles.
The later patches in this series which move every driver into a libtool convenience library, and then the subsquent dlopen support could help us here by making cross-file dependancies much more obvious. So we will catch many more problem at compile time even with all drivers enabled. I can probably tweak the compile find even more problems in this way, as well as documenting where the boundaries are in our internal APIs. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

A while ago we introduced a libvirt_test.so which is identical to libvirt.so, but without the linker whitelist of symbols. This did impose a little overhead in the build process - it meant we compiled all source files twice. A future patch will want to compile drivers into individual libraries to allow dlopening, and it occurred to me that if we built some more libtool convenience libraries we could avoid the double compilation. The trick is that libvirt.la must not have any source files listed against it. It must only be used to link together other convenience libraries. So, I define a while set of libraries - libvirt_util.la - generic code not related to drivers or libvirt API - libvirt_driver.la - the libvirt public API and driver support code - libvirt_driver_XXXX.la - one for each of qemu, xen, test, remote, openvz, lxc, storage, network These are all convenience libraries, so libtool will just build a local non-installed, static .a archive. Now, the actual things we care about - libvirt.la - links to all of these convenience .la libraries together and adds the libvirt_sym.version script to filter symbols - libvirt_test.la - the same, but with the version script - libvirt_lxc - links to libvirt_util.la and libvirt_driver_lxc.la - virsh - links to libvirt.la So the end result is that each source file is only ever compiled once, and each library/program just links to the .a files is actually needs. Makefile.am | 107 +++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 36 deletions(-) Daniel diff -r a5221822f20b src/Makefile.am --- a/src/Makefile.am Wed Oct 29 20:10:49 2008 +0000 +++ b/src/Makefile.am Wed Oct 29 20:10:52 2008 +0000 @@ -6,11 +6,7 @@ -I@top_srcdir@/include \ -I@top_srcdir@/qemud \ $(LIBXML_CFLAGS) \ - $(GNUTLS_CFLAGS) \ - $(SASL_CFLAGS) \ $(SELINUX_CFLAGS) \ - $(NUMACTL_CFLAGS) \ - $(XEN_CFLAGS) \ -DBINDIR=\""$(libexecdir)"\" \ -DSBINDIR=\""$(sbindir)"\" \ -DSYSCONF_DIR="\"$(sysconfdir)\"" \ @@ -18,10 +14,6 @@ -DLOCAL_STATE_DIR=\""$(localstatedir)"\" \ -DGETTEXT_PACKAGE=\"$(PACKAGE)\" \ $(WARN_CFLAGS) - -DEPS = libvirt.la -LDADDS = @STATIC_BINARIES@ $(WARN_CFLAGS) libvirt.la ../gnulib/lib/libgnu.la -VIRSH_LIBS = @VIRSH_LIBS@ confdir = $(sysconfdir)/libvirt/ conf_DATA = qemu.conf @@ -40,7 +32,7 @@ # These files are not related to driver APIs. Simply generic # helper APIs for various purposes -GENERIC_LIB_SOURCES = \ +UTIL_SOURCES = \ bridge.c bridge.h \ buf.c buf.h \ conf.c conf.h \ @@ -53,6 +45,16 @@ util.c util.h \ virterror.c virterror_internal.h \ xml.c xml.h + +# Internal generic driver infrastructure +DRIVER_SOURCES = \ + driver.h \ + internal.h \ + datatypes.c datatypes.h \ + domain_event.c domain_event.h \ + stats_linux.c stats_linux.h \ + libvirt.c libvirt_internal.h + # Domain driver generic impl APIs DOMAIN_CONF_SOURCES = \ @@ -146,62 +148,91 @@ # # First deal with sources usable in non-daemon context -libvirt_la_SOURCES = \ - driver.h \ - internal.h \ - datatypes.c datatypes.h \ - domain_event.c domain_event.h \ - stats_linux.c stats_linux.h \ - libvirt.c libvirt_internal.h \ - $(GENERIC_LIB_SOURCES) \ +noinst_LTLIBRARIES = libvirt_util.la +libvirt_la_LIBADD = libvirt_util.la +libvirt_util_la_SOURCES = \ + $(UTIL_SOURCES) + +noinst_LTLIBRARIES += libvirt_driver.la +libvirt_la_LIBADD += libvirt_driver.la +libvirt_driver_la_SOURCES = \ + $(DRIVER_SOURCES) \ $(DOMAIN_CONF_SOURCES) \ $(NETWORK_CONF_SOURCES) \ $(STORAGE_CONF_SOURCES) if WITH_TEST -libvirt_la_SOURCES += $(TEST_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_test.la +libvirt_la_LIBADD += libvirt_driver_test.la +libvirt_driver_test_la_SOURCES = $(TEST_DRIVER_SOURCES) endif if WITH_REMOTE -libvirt_la_SOURCES += $(REMOTE_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_remote.la +libvirt_la_LIBADD += libvirt_driver_remote.la +libvirt_driver_remote_la_CFLAGS = \ + $(GNUTLS_CFLAGS) \ + $(SASL_CFLAGS) +libvirt_driver_remote_la_LDFLAGS = \ + $(GNUTLS_LIBS) \ + $(SASL_LIBS) +libvirt_driver_remote_la_SOURCES = $(REMOTE_DRIVER_SOURCES) endif if WITH_XEN -libvirt_la_SOURCES += $(XEN_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_xen.la +libvirt_la_LIBADD += libvirt_driver_xen.la +libvirt_driver_xen_la_CFLAGS = $(XEN_CFLAGS) +libvirt_driver_xen_la_LDFLAGS = $(XEN_LIBS) +libvirt_driver_xen_la_SOURCES = $(XEN_DRIVER_SOURCES) endif if WITH_OPENVZ -libvirt_la_SOURCES += $(OPENVZ_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_openvz.la +libvirt_la_LIBADD += libvirt_driver_openvz.la +libvirt_driver_openvz_la_SOURCES = $(OPENVZ_DRIVER_SOURCES) endif if WITH_QEMU -libvirt_la_SOURCES += $(QEMU_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_qemu.la +libvirt_la_LIBADD += libvirt_driver_qemu.la +libvirt_driver_qemu_la_CFLAGS = $(NUMACTL_CFLAGS) +libvirt_driver_qemu_la_LDFLAGS = $(NUMACTL_LIBS) +libvirt_driver_qemu_la_SOURCES = $(QEMU_DRIVER_SOURCES) endif if WITH_LXC -libvirt_la_SOURCES += $(LXC_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_lxc.la +libvirt_la_LIBADD += libvirt_driver_lxc.la +libvirt_driver_lxc_la_SOURCES = $(LXC_DRIVER_SOURCES) endif if WITH_NETWORK -libvirt_la_SOURCES += $(NETWORK_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_network.la +libvirt_la_LIBADD += libvirt_driver_network.la +libvirt_driver_network_la_SOURCES = $(NETWORK_DRIVER_SOURCES) endif +# Needed to keep automake quiet about conditionals +libvirt_driver_storage_la_SOURCES = if WITH_STORAGE_DIR -libvirt_la_SOURCES += $(STORAGE_DRIVER_SOURCES) -libvirt_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_storage.la +libvirt_la_LIBADD += libvirt_driver_storage.la +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SOURCES) +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif if WITH_STORAGE_LVM -libvirt_la_SOURCES += $(STORAGE_DRIVER_LVM_SOURCES) +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_LVM_SOURCES) endif if WITH_STORAGE_ISCSI -libvirt_la_SOURCES += $(STORAGE_DRIVER_ISCSI_SOURCES) +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_ISCSI_SOURCES) endif if WITH_STORAGE_DISK -libvirt_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES) +libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_DISK_SOURCES) endif # Add all conditional sources just in case... @@ -220,8 +251,9 @@ $(STORAGE_DRIVER_DISK_SOURCES) -libvirt_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(SASL_LIBS) $(SELINUX_LIBS) \ - $(NUMACTL_LIBS) $(XEN_LIBS) \ +# Empty source list - it merely links a bunch of convenience libs together +libvirt_la_SOURCES = +libvirt_la_LIBADD += $(LIBXML_LIBS) $(SELINUX_LIBS) \ @CYGWIN_EXTRA_LIBADD@ ../gnulib/lib/libgnu.la libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \ -version-info @LIBVIRT_VERSION_INFO@ \ @@ -232,7 +264,7 @@ # Create an automake "convenience library" version of libvirt_la, # just for testing, since the test harness requires access to internal # bits and pieces that we don't want to make publicly accessible. -noinst_LTLIBRARIES = libvirt_test.la +noinst_LTLIBRARIES += libvirt_test.la # Convert libvirt_sym.version # to libvirt_test_sym.version, and @@ -256,8 +288,12 @@ virsh.c virsh_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDFLAGS) -virsh_DEPENDENCIES = $(DEPS) -virsh_LDADD = $(LDADDS) $(VIRSH_LIBS) +virsh_LDADD = \ + $(STATIC_BINARIES) \ + $(WARN_CFLAGS) \ + libvirt.la \ + ../gnulib/lib/libgnu.la \ + $(VIRSH_LIBS) virsh_CFLAGS = $(COVERAGE_CFLAGS) $(READLINE_CFLAGS) BUILT_SOURCES = virsh-net-edit.c virsh-pool-edit.c @@ -294,7 +330,6 @@ if WITH_WIN_ICON virsh_LDADD += virsh_win_icon.$(OBJEXT) -virsh_DEPENDENCIES += virsh_win_icon.$(OBJEXT) # Before you edit virsh_win_icon.rc, please note the following # limitations of the resource file format: @@ -340,7 +375,7 @@ libvirt_lxc_SOURCES = \ $(LXC_CONTROLLER_SOURCES) \ - $(GENERIC_LIB_SOURCES) \ + $(UTIL_SOURCES) \ $(DOMAIN_CONF_SOURCES) libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) libvirt_lxc_LDADD = $(LIBXML_LIBS) ../gnulib/lib/libgnu.la -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:39:33PM +0000, Daniel P. Berrange wrote:
A while ago we introduced a libvirt_test.so which is identical to libvirt.so, but without the linker whitelist of symbols. This did impose a little overhead in the build process - it meant we compiled all source files twice.
A future patch will want to compile drivers into individual libraries to allow dlopening, and it occurred to me that if we built some more libtool convenience libraries we could avoid the double compilation.
The trick is that libvirt.la must not have any source files listed against it. It must only be used to link together other convenience libraries. So, I define a while set of libraries
- libvirt_util.la - generic code not related to drivers or libvirt API - libvirt_driver.la - the libvirt public API and driver support code - libvirt_driver_XXXX.la - one for each of qemu, xen, test, remote, openvz, lxc, storage, network
These are all convenience libraries, so libtool will just build a local non-installed, static .a archive.
Now, the actual things we care about
- libvirt.la - links to all of these convenience .la libraries together and adds the libvirt_sym.version script to filter symbols - libvirt_test.la - the same, but with the version script - libvirt_lxc - links to libvirt_util.la and libvirt_driver_lxc.la - virsh - links to libvirt.la
So the end result is that each source file is only ever compiled once, and each library/program just links to the .a files is actually needs.
In principle it's fine, it's equivalent, but it's a bit complex. Maybe this description should go somewhere in the HACKING file too i assume we can still compile with --disable-shared and everything will just build and link fine, just that the .la will be replaced with good old .a and the binaries will have them statically linked in. I we can just double check this, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

The libvirt.so file currently whitelists all the symbols in our public API. libvirtd and virsh, however, also want to use a bunch of our so called 'private' symbols which aren't in the public API. For saferead and safewrite() we dealt with this by compiling the code twice with some nasty macro tricks to give the function a different name to avoid dup symbols when statically linking. For the other APIs, we prefixed them with __ and then just added them to the exports. Neither option is very good because they both impose a burden on the source code - needing to append __ everywhere and write crazy macros. Each time we want to export another symbol, we have to make lots of manual changes to add __. This was OK if it was just a handful of symbols, but we're now upto 30 odd, and its not scaling. When we make drivers modular we'll be adding 100's more symbols. As an aside, we use ELF library versioning when linking, via the libtool -version-info flag. Since we maintain ABI compat going forwards though, the version in the eventual .so is always going to be 'libvirt.so.0'. This is sub-optimal because you may build a binary that requires 'virDomainBlockPeek' which appeared in libvirt 0.4.2, but the ELF version cannot validate this. There is nothing stopping your application launching against libvirt 0.3.0 and then aborting with a linker failure sometime while it is running when it eventually referneces the non-existant symbol. Likewise RPM automatic versioning hooks off the ELF version too, so that's not preventing you installing too old a libvirt for your app's needs. A far better solution to all these problems has been sitting in front of us the whole time. Namely we need to make full use of the linkers symbol version scripts. Our current libvirt_sym.version script is defining an unversioned set of symbols. This only enforces what's exported, and can do nothing about version compatability. So instead we need to switch to a fully versioned script, where every symbol we export is tagged with the libvirt version number at which it was introduced. Taking the virDomainBlockPeek example again, this appeared in the libvirt 0.4.2 release, so we'd add a section to the linker script LIBVIRT_0.4.2 { global: virDomainBlockPeek; virDomainMemoryPeek; } LIBVIRT_0.4.1; Then 0.4.5 added in storage pool discovery so you get another section LIBVIRT_0.4.5 { global: virConnectFindStoragePoolSources; } LIBVIRT_0.4.2; And so on for every release. The resulting libvirt.so file will thus gain metadata listing all the ABI versions for all symbols it includes. That deals with public APIs. Now we also want to export some internal APIs whose semantics/syntax may arbitrarily change between releases. Thus they should not be included in any of the formal public version sections. Instead they should be in a seperate versioned section, whose version changes on every release. This will ensure that if libvirtd or virsh link to some internal symbols, they are guareteened to only run against the exactly same libvirt.so they were linked to. This will avoid some nasty bugs our users have hit where they installed a custom libvirt version on their OS which already had another version installed, and then libvirtd crashed/behave wierdly/etc To do this we rename libvirt_sym.version to libvirt_sym.version.in and add a section called LIBVIRT_PRIVATE_@VERSION@ { global: /* libvirt_internal.h */ debugFlag; virStateInitialize; virStateCleanup; virStateReload; virStateActive; .... more private symbols... } The @VERSION@ gets subsituted by the version number of the libvirt release by configure. Do a build with this all active and look at the resulting libvirt.so using objdump (or eu-readelf). # objdump -p src/.libs/libvirt.so Version definitions: 1 0x01 0x0e5a1d10 libvirt.so.0 2 0x00 0x0af6bd33 LIBVIRT_0.0.3 3 0x00 0x0af6bd35 LIBVIRT_0.0.5 LIBVIRT_0.0.3 4 0x00 0x0af6be30 LIBVIRT_0.1.0 LIBVIRT_0.0.5 5 0x00 0x0af6be31 LIBVIRT_0.1.1 LIBVIRT_0.1.0 6 0x00 0x0af6be34 LIBVIRT_0.1.4 LIBVIRT_0.1.1 7 0x00 0x0af6be35 LIBVIRT_0.1.5 LIBVIRT_0.1.4 8 0x00 0x0af6be39 LIBVIRT_0.1.9 LIBVIRT_0.1.5 9 0x00 0x0af6bb30 LIBVIRT_0.2.0 LIBVIRT_0.1.9 10 0x00 0x0af6bb31 LIBVIRT_0.2.1 LIBVIRT_0.2.0 11 0x00 0x0af6bb33 LIBVIRT_0.2.3 LIBVIRT_0.2.1 12 0x00 0x0af6bc30 LIBVIRT_0.3.0 LIBVIRT_0.2.3 13 0x00 0x0af6bc32 LIBVIRT_0.3.2 LIBVIRT_0.3.0 14 0x00 0x0af6bc33 LIBVIRT_0.3.3 LIBVIRT_0.3.2 15 0x00 0x0af6b930 LIBVIRT_0.4.0 LIBVIRT_0.3.3 16 0x00 0x0af6b931 LIBVIRT_0.4.1 LIBVIRT_0.4.0 17 0x00 0x0af6b932 LIBVIRT_0.4.2 LIBVIRT_0.4.1 18 0x00 0x0af6b935 LIBVIRT_0.4.5 LIBVIRT_0.4.2 19 0x00 0x0af6ba30 LIBVIRT_0.5.0 LIBVIRT_0.4.5 20 0x00 0x09e39b06 LIBVIRT_PRIVATE_0.4.6 You can see that as well as the main SONAME libvirt.so.0, we've got version info for each release which introduced new public API symbols, as well as our versioned private symbols. If you look at glibc's libc.so, you'll see a similar set of versioned interfaces. Then take a look at the virsh binary, and see that it has references to all of the versions corresponding to symbols it uses. You can also see that it used some libvirt internal symbols, by presence of the LIBVIRT_PRIVATE_0.4.6 reference. This ensures that this virsh binary can't accidentally be used against libvirt 0.4.5 or 0.4.7 where it'd likely crash at runtime # objdump -p src/.libs/virsh Version References: required from libpthread.so.0: 0x09691a75 0x00 10 GLIBC_2.2.5 required from libc.so.6: 0x0d696918 0x00 19 GLIBC_2.8 0x09691974 0x00 13 GLIBC_2.3.4 0x09691a75 0x00 04 GLIBC_2.2.5 required from libvirt.so.0: 0x0af6ba30 0x00 22 LIBVIRT_0.5.0 0x0af6bc30 0x00 21 LIBVIRT_0.3.0 0x0af6bc33 0x00 20 LIBVIRT_0.3.3 0x0af6be34 0x00 18 LIBVIRT_0.1.4 0x0af6be35 0x00 17 LIBVIRT_0.1.5 0x0af6b935 0x00 16 LIBVIRT_0.4.5 0x0af6be31 0x00 15 LIBVIRT_0.1.1 0x0af6bc32 0x00 14 LIBVIRT_0.3.2 0x0af6be39 0x00 12 LIBVIRT_0.1.9 0x0af6bd33 0x00 11 LIBVIRT_0.0.3 0x0af6bb31 0x00 09 LIBVIRT_0.2.1 0x09e39b06 0x00 08 LIBVIRT_PRIVATE_0.4.6 0x0af6b930 0x00 07 LIBVIRT_0.4.0 0x0af6bb30 0x00 06 LIBVIRT_0.2.0 0x0af6be30 0x00 05 LIBVIRT_0.1.0 0x0af6bb33 0x00 03 LIBVIRT_0.2.3 0x0af6b931 0x00 02 LIBVIRT_0.4.1 The next nice thing is that RPM knows how to make use of these symbols for strong dependancies. $ rpm -qp --provides libvirt-0.4.6-1.fc9.berrange1225311229.x86_64.rpm config(libvirt) = 0.4.6-1.fc9.berrange1225311229 libvirt.so.0()(64bit) libvirt.so.0(LIBVIRT_0.0.3)(64bit) libvirt.so.0(LIBVIRT_0.0.5)(64bit) libvirt.so.0(LIBVIRT_0.1.0)(64bit) libvirt.so.0(LIBVIRT_0.1.1)(64bit) libvirt.so.0(LIBVIRT_0.1.4)(64bit) libvirt.so.0(LIBVIRT_0.1.5)(64bit) libvirt.so.0(LIBVIRT_0.1.9)(64bit) libvirt.so.0(LIBVIRT_0.2.0)(64bit) libvirt.so.0(LIBVIRT_0.2.1)(64bit) libvirt.so.0(LIBVIRT_0.2.3)(64bit) libvirt.so.0(LIBVIRT_0.3.0)(64bit) libvirt.so.0(LIBVIRT_0.3.2)(64bit) libvirt.so.0(LIBVIRT_0.3.3)(64bit) libvirt.so.0(LIBVIRT_0.4.0)(64bit) libvirt.so.0(LIBVIRT_0.4.1)(64bit) libvirt.so.0(LIBVIRT_0.4.2)(64bit) libvirt.so.0(LIBVIRT_0.4.5)(64bit) libvirt.so.0(LIBVIRT_0.5.0)(64bit) libvirt.so.0(LIBVIRT_PRIVATE_0.4.6)(64bit) Again notice the LIBVIRT_PRIVATE_0.4.6 version here. If some $EVIL user links to libvirt private symbols, RPM wil ensure they can only ever be installed with the exactly matching libvirt build. The libvirt-python bindings demonstrate a well behaved app that doesn't access internal sybols: $ rpm -qp --requires libvirt-python-0.4.6-1.fc9.berrange1225311229.x86_64.rpm /usr/bin/python libc.so.6()(64bit) libc.so.6(GLIBC_2.2.5)(64bit) libc.so.6(GLIBC_2.4)(64bit) libpthread.so.0()(64bit) libvirt = 0.4.6 libvirt.so.0()(64bit) libvirt.so.0(LIBVIRT_0.0.3)(64bit) libvirt.so.0(LIBVIRT_0.0.5)(64bit) libvirt.so.0(LIBVIRT_0.1.0)(64bit) libvirt.so.0(LIBVIRT_0.1.1)(64bit) libvirt.so.0(LIBVIRT_0.1.4)(64bit) libvirt.so.0(LIBVIRT_0.1.5)(64bit) libvirt.so.0(LIBVIRT_0.1.9)(64bit) libvirt.so.0(LIBVIRT_0.2.0)(64bit) libvirt.so.0(LIBVIRT_0.2.1)(64bit) libvirt.so.0(LIBVIRT_0.2.3)(64bit) libvirt.so.0(LIBVIRT_0.3.0)(64bit) libvirt.so.0(LIBVIRT_0.3.2)(64bit) libvirt.so.0(LIBVIRT_0.3.3)(64bit) libvirt.so.0(LIBVIRT_0.4.0)(64bit) libvirt.so.0(LIBVIRT_0.4.1)(64bit) libvirt.so.0(LIBVIRT_0.4.5)(64bit) libvirt.so.0(LIBVIRT_0.5.0)(64bit) python(abi) = 2.5 rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(PartialHardlinkSets) <= 4.0.4-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rtld(GNU_HASH) There is one important thing to note. Going from an unversioned ELF library to a versioned library is a one-way operation. If you have a existing binary built against an unversioned .so, it'll link just fine to the versioned .so. If you have a binary built against a versioned .so, then it'll never run with an unversioned .so. Of course this is the entire point of having formal versioning info, but it bears mentioning anyway. This is all quite a complex subject, but there are actually some very good docs on this exact topic. See 'info ld', and follow 'Scripts', 'VERSION' for the GNU docs. Or see it online: http://sources.redhat.com/binutils/docs-2.16/ld/VERSION.html#VERSION Solaris uses exact same format for its linker, but calls this concept a mapfile rather than a linker script, so this all applies to Solaris libvirt builds too. Their docs are excellant reading http://docs.sun.com/app/docs/doc/817-1974/6mhlu8fds?l=en&q=linkers&a=view http://developers.sun.com/solaris/articles/linker_mapfiles.html http://www.usenix.org/publications/library/proceedings/als00/2000papers/pape... For non Linux, non Solaris platforms we're no worse than before - everything is publically visible and we rely on trust. Now onto the patch itself - Remove libvirt_sym.version, and add libvirt_sym.version.in - Change the unversion public API into a fully versioned API. I did this getting a checkout of every single libvirt release, and comparing the APIs listed in the public libvirt.h file to find out what version we introduced them in - Remove the leading __ prefix for all private symbols that we export for virsh/libvirtd & fix up code using them - Add a LIBVIRT_PRIVATE section mentioning all the private symbols needed by virsh/libivrtd - Merge util-lib.c back into util.c, and add saferead/write to the private exports There should be no functional change in this patch. We're merely renaming symbols, and playing games with the linker. a/src/libvirt_sym.version | 203 --------------------------- a/src/util-lib.c | 52 ------- a/src/util-lib.h | 25 --- b/src/libvirt_sym.version.in | 318 +++++++++++++++++++++++++++++++++++++++++++ configure.in | 1 qemud/Makefile.am | 3 qemud/remote.c | 28 +-- src/Makefile.am | 1 src/buf.c | 10 - src/buf.h | 19 -- src/conf.c | 36 ++-- src/conf.h | 28 +-- src/console.c | 2 src/datatypes.c | 8 - src/datatypes.h | 14 - src/driver.h | 4 src/libvirt.c | 16 +- src/libvirt_internal.h | 56 +++---- src/memory.c | 8 - src/memory.h | 16 +- src/util.c | 53 ++++++- src/util.h | 25 +-- src/virsh.c | 1 23 files changed, 486 insertions(+), 441 deletions(-) Daniel diff -r 2a018ec3c877 configure.in --- a/configure.in Thu Oct 30 10:11:40 2008 +0000 +++ b/configure.in Thu Oct 30 10:46:19 2008 +0000 @@ -1072,6 +1072,7 @@ gnulib/lib/Makefile \ gnulib/tests/Makefile \ libvirt.pc libvirt.spec mingw32-libvirt.spec \ + src/libvirt_sym.version \ po/Makefile.in \ include/libvirt/Makefile include/libvirt/libvirt.h \ python/Makefile python/tests/Makefile \ diff -r 2a018ec3c877 qemud/Makefile.am --- a/qemud/Makefile.am Thu Oct 30 10:11:40 2008 +0000 +++ b/qemud/Makefile.am Thu Oct 30 10:46:19 2008 +0000 @@ -7,8 +7,7 @@ remote_dispatch_prototypes.h \ remote_dispatch_localvars.h \ remote_dispatch_proc_switch.h \ - remote_protocol.h remote_protocol.c \ - $(srcdir)/../src/util-lib.c + remote_protocol.h remote_protocol.c AVAHI_SOURCES = \ mdns.c mdns.h diff -r 2a018ec3c877 qemud/remote.c --- a/qemud/remote.c Thu Oct 30 10:11:40 2008 +0000 +++ b/qemud/remote.c Thu Oct 30 10:46:19 2008 +0000 @@ -487,7 +487,7 @@ { CHECK_CONN(client); - ret->supported = __virDrvSupportsFeature (client->conn, args->feature); + ret->supported = virDrvSupportsFeature (client->conn, args->feature); if (ret->supported == -1) return -1; return 0; @@ -1396,9 +1396,9 @@ return -2; } - r = __virDomainMigratePrepare (client->conn, &cookie, &cookielen, - uri_in, uri_out, - args->flags, dname, args->resource); + r = virDomainMigratePrepare (client->conn, &cookie, &cookielen, + uri_in, uri_out, + args->flags, dname, args->resource); if (r == -1) { VIR_FREE(uri_out); return -1; @@ -1439,11 +1439,11 @@ dname = args->dname == NULL ? NULL : *args->dname; - r = __virDomainMigratePerform (dom, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags, dname, args->resource); + r = virDomainMigratePerform (dom, + args->cookie.cookie_val, + args->cookie.cookie_len, + args->uri, + args->flags, dname, args->resource); virDomainFree (dom); if (r == -1) return -1; @@ -1460,11 +1460,11 @@ virDomainPtr ddom; CHECK_CONN (client); - ddom = __virDomainMigrateFinish (client->conn, args->dname, - args->cookie.cookie_val, - args->cookie.cookie_len, - args->uri, - args->flags); + ddom = virDomainMigrateFinish (client->conn, args->dname, + args->cookie.cookie_val, + args->cookie.cookie_len, + args->uri, + args->flags); if (ddom == NULL) return -1; make_nonnull_domain (&ret->ddom, ddom); diff -r 2a018ec3c877 src/Makefile.am --- a/src/Makefile.am Thu Oct 30 10:11:40 2008 +0000 +++ b/src/Makefile.am Thu Oct 30 10:46:19 2008 +0000 @@ -284,7 +284,6 @@ virsh_SOURCES = \ console.c console.h \ - util-lib.c util-lib.h \ virsh.c virsh_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDFLAGS) diff -r 2a018ec3c877 src/buf.c --- a/src/buf.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/buf.c Thu Oct 30 10:46:19 2008 +0000 @@ -88,7 +88,7 @@ * */ void -__virBufferAdd(const virBufferPtr buf, const char *str, int len) +virBufferAdd(const virBufferPtr buf, const char *str, int len) { unsigned int needSize; @@ -120,7 +120,7 @@ * */ void -__virBufferAddChar (virBufferPtr buf, char c) +virBufferAddChar (virBufferPtr buf, char c) { unsigned int needSize; @@ -150,7 +150,7 @@ * Returns the buffer content or NULL in case of error. */ char * -__virBufferContentAndReset(const virBufferPtr buf) +virBufferContentAndReset(const virBufferPtr buf) { char *str; if (buf == NULL) @@ -176,7 +176,7 @@ * Return true if in error, 0 if normal */ int -__virBufferError(const virBufferPtr buf) +virBufferError(const virBufferPtr buf) { if (buf == NULL) return 1; @@ -208,7 +208,7 @@ * Do a formatted print to an XML buffer. */ void -__virBufferVSprintf(const virBufferPtr buf, const char *format, ...) +virBufferVSprintf(const virBufferPtr buf, const char *format, ...) { int size, count, grow_size; va_list locarg, argptr; diff -r 2a018ec3c877 src/buf.h --- a/src/buf.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/buf.h Thu Oct 30 10:46:19 2008 +0000 @@ -34,25 +34,18 @@ }; #endif -char *__virBufferContentAndReset(const virBufferPtr buf); -int __virBufferError(const virBufferPtr buf); +char *virBufferContentAndReset(const virBufferPtr buf); +int virBufferError(const virBufferPtr buf); unsigned int virBufferUse(const virBufferPtr buf); -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, ...) +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_FORMAT(printf, 2, 3); void virBufferStrcat(const virBufferPtr buf, ...); void virBufferEscapeString(const virBufferPtr buf, const char *format, const char *str); void virBufferURIEncodeString (const virBufferPtr buf, const char *str); #define virBufferAddLit(buf_, literal_string_) \ - __virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1) - -#define virBufferAdd(b,s,l) __virBufferAdd((b),(s),(l)) -#define virBufferAddChar(b,c) __virBufferAddChar((b),(c)) -#define virBufferVSprintf(b,f,...) __virBufferVSprintf((b),(f), __VA_ARGS__) - -#define virBufferContentAndReset(b) __virBufferContentAndReset((b)) -#define virBufferError(b) __virBufferError((b)) + virBufferAdd (buf_, "" literal_string_ "", sizeof literal_string_ - 1) #endif /* __VIR_BUFFER_H__ */ diff -r 2a018ec3c877 src/conf.c --- a/src/conf.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/conf.c Thu Oct 30 10:46:19 2008 +0000 @@ -142,7 +142,7 @@ * Free a value */ void -__virConfFreeValue(virConfValuePtr val) +virConfFreeValue(virConfValuePtr val) { if (val == NULL) return; @@ -156,7 +156,7 @@ } virConfPtr -__virConfNew(void) +virConfNew(void) { virConfPtr ret; @@ -691,7 +691,7 @@ #define MAX_CONFIG_FILE_SIZE (1024*1024*10) /** - * __virConfReadFile: + * virConfReadFile: * @filename: the path to the configuration file. * * Reads a configuration file. @@ -700,7 +700,7 @@ * read or parse the file, use virConfFree() to free the data. */ virConfPtr -__virConfReadFile(const char *filename) +virConfReadFile(const char *filename) { char *content; int len; @@ -724,7 +724,7 @@ } /** - * __virConfReadMem: + * virConfReadMem: * @memory: pointer to the content of the configuration file * @len: length in byte * @@ -735,7 +735,7 @@ * parse the content, use virConfFree() to free the data. */ virConfPtr -__virConfReadMem(const char *memory, int len) +virConfReadMem(const char *memory, int len) { if ((memory == NULL) || (len < 0)) { virConfError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); @@ -748,7 +748,7 @@ } /** - * __virConfFree: + * virConfFree: * @conf: a configuration file handle * * Frees all data associated to the handle @@ -756,7 +756,7 @@ * Returns 0 in case of success, -1 in case of error. */ int -__virConfFree(virConfPtr conf) +virConfFree(virConfPtr conf) { virConfEntryPtr tmp; if (conf == NULL) { @@ -779,7 +779,7 @@ } /** - * __virConfGetValue: + * virConfGetValue: * @conf: a configuration file handle * @entry: the name of the entry * @@ -789,7 +789,7 @@ * associated will be freed when virConfFree() is called */ virConfValuePtr -__virConfGetValue(virConfPtr conf, const char *setting) +virConfGetValue(virConfPtr conf, const char *setting) { virConfEntryPtr cur; @@ -803,7 +803,7 @@ } /** - * __virConfSetValue: + * virConfSetValue: * @conf: a configuration file handle * @entry: the name of the entry * @value: the new configuration value @@ -816,9 +816,9 @@ * Returns 0 on success, or -1 on failure. */ int -__virConfSetValue (virConfPtr conf, - const char *setting, - virConfValuePtr value) +virConfSetValue (virConfPtr conf, + const char *setting, + virConfValuePtr value) { virConfEntryPtr cur, prev = NULL; @@ -861,7 +861,7 @@ /** - * __virConfWriteFile: + * virConfWriteFile: * @filename: the path to the configuration file. * @conf: the conf * @@ -870,7 +870,7 @@ * Returns the number of bytes written or -1 in case of error. */ int -__virConfWriteFile(const char *filename, virConfPtr conf) +virConfWriteFile(const char *filename, virConfPtr conf) { virBuffer buf = VIR_BUFFER_INITIALIZER; virConfEntryPtr cur; @@ -915,7 +915,7 @@ } /** - * __virConfWriteMem: + * virConfWriteMem: * @memory: pointer to the memory to store the config file * @len: pointer to the length in bytes of the store, on output the size * @conf: the conf @@ -928,7 +928,7 @@ * Returns the number of bytes written or -1 in case of error. */ int -__virConfWriteMem(char *memory, int *len, virConfPtr conf) +virConfWriteMem(char *memory, int *len, virConfPtr conf) { virBuffer buf = VIR_BUFFER_INITIALIZER; virConfEntryPtr cur; diff -r 2a018ec3c877 src/conf.h --- a/src/conf.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/conf.h Thu Oct 30 10:46:19 2008 +0000 @@ -61,32 +61,22 @@ typedef struct _virConf virConf; typedef virConf *virConfPtr; -virConfPtr __virConfNew (void); -virConfPtr __virConfReadFile (const char *filename); -virConfPtr __virConfReadMem (const char *memory, +virConfPtr virConfNew (void); +virConfPtr virConfReadFile (const char *filename); +virConfPtr virConfReadMem (const char *memory, int len); -int __virConfFree (virConfPtr conf); -void __virConfFreeValue (virConfValuePtr val); +int virConfFree (virConfPtr conf); +void virConfFreeValue (virConfValuePtr val); -virConfValuePtr __virConfGetValue (virConfPtr conf, +virConfValuePtr virConfGetValue (virConfPtr conf, const char *setting); -int __virConfSetValue (virConfPtr conf, +int virConfSetValue (virConfPtr conf, const char *setting, virConfValuePtr value); -int __virConfWriteFile (const char *filename, +int virConfWriteFile (const char *filename, virConfPtr conf); -int __virConfWriteMem (char *memory, +int virConfWriteMem (char *memory, int *len, virConfPtr conf); -#define virConfNew() __virConfNew() -#define virConfReadFile(f) __virConfReadFile((f)) -#define virConfReadMem(m,l) __virConfReadMem((m),(l)) -#define virConfFree(c) __virConfFree((c)) -#define virConfFreeValue(v) __virConfFreeValue((v)) -#define virConfGetValue(c,s) __virConfGetValue((c),(s)) -#define virConfSetValue(c,s,v) __virConfSetValue((c),(s),(v)) -#define virConfWriteFile(f,c) __virConfWriteFile((f),(c)) -#define virConfWriteMem(m,l,c) __virConfWriteMem((m),(l),(c)) - #endif /* __VIR_CONF_H__ */ diff -r 2a018ec3c877 src/console.c --- a/src/console.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/console.c Thu Oct 30 10:46:19 2008 +0000 @@ -37,7 +37,7 @@ #include "console.h" #include "internal.h" -#include "util-lib.h" +#include "util.h" /* ie Ctrl-] as per telnet */ #define CTRL_CLOSE_BRACKET '\35' diff -r 2a018ec3c877 src/datatypes.c --- a/src/datatypes.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/datatypes.c Thu Oct 30 10:46:19 2008 +0000 @@ -238,7 +238,7 @@ * Returns a pointer to the domain, or NULL in case of failure */ virDomainPtr -__virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) { +virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid) { virDomainPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { @@ -378,7 +378,7 @@ * Returns a pointer to the network, or NULL in case of failure */ virNetworkPtr -__virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) { +virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid) { virNetworkPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { @@ -515,7 +515,7 @@ * Returns a pointer to the network, or NULL in case of failure */ virStoragePoolPtr -__virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) { +virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid) { virStoragePoolPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { @@ -649,7 +649,7 @@ * Returns a pointer to the storage vol, or NULL in case of failure */ virStorageVolPtr -__virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) { +virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key) { virStorageVolPtr ret = NULL; if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (key == NULL)) { diff -r 2a018ec3c877 src/datatypes.h --- a/src/datatypes.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/datatypes.h Thu Oct 30 10:46:19 2008 +0000 @@ -184,29 +184,23 @@ virConnectPtr virGetConnect(void); int virUnrefConnect(virConnectPtr conn); -virDomainPtr __virGetDomain(virConnectPtr conn, +virDomainPtr virGetDomain(virConnectPtr conn, const char *name, const unsigned char *uuid); int virUnrefDomain(virDomainPtr domain); -virNetworkPtr __virGetNetwork(virConnectPtr conn, +virNetworkPtr virGetNetwork(virConnectPtr conn, const char *name, const unsigned char *uuid); int virUnrefNetwork(virNetworkPtr network); -virStoragePoolPtr __virGetStoragePool(virConnectPtr conn, +virStoragePoolPtr virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid); int virUnrefStoragePool(virStoragePoolPtr pool); -virStorageVolPtr __virGetStorageVol(virConnectPtr conn, +virStorageVolPtr virGetStorageVol(virConnectPtr conn, const char *pool, const char *name, const char *key); int virUnrefStorageVol(virStorageVolPtr vol); -#define virGetDomain(c,n,u) __virGetDomain((c),(n),(u)) -#define virGetNetwork(c,n,u) __virGetNetwork((c),(n),(u)) -#define virGetStoragePool(c,n,u) __virGetStoragePool((c),(n),(u)) -#define virGetStorageVol(c,p,n,u) __virGetStorageVol((c),(p),(n),(u)) - - #endif diff -r 2a018ec3c877 src/driver.h --- a/src/driver.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/driver.h Thu Oct 30 10:46:19 2008 +0000 @@ -73,7 +73,7 @@ typedef int (*virDrvClose) (virConnectPtr conn); typedef int - (*virDrvSupportsFeature) (virConnectPtr conn, int feature); + (*virDrvDrvSupportsFeature) (virConnectPtr conn, int feature); typedef const char * (*virDrvGetType) (virConnectPtr conn); typedef int @@ -305,7 +305,7 @@ virDrvProbe probe; virDrvOpen open; virDrvClose close; - virDrvSupportsFeature supports_feature; + virDrvDrvSupportsFeature supports_feature; virDrvGetType type; virDrvGetVersion version; virDrvGetHostname getHostname; diff -r 2a018ec3c877 src/libvirt.c --- a/src/libvirt.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/libvirt.c Thu Oct 30 10:46:19 2008 +0000 @@ -582,7 +582,7 @@ return virStateDriverTabCount++; } -int __virStateInitialize(void) { +int virStateInitialize(void) { int i, ret = 0; if (virInitialize() < 0) @@ -596,7 +596,7 @@ return ret; } -int __virStateCleanup(void) { +int virStateCleanup(void) { int i, ret = 0; for (i = 0 ; i < virStateDriverTabCount ; i++) { @@ -607,7 +607,7 @@ return ret; } -int __virStateReload(void) { +int virStateReload(void) { int i, ret = 0; for (i = 0 ; i < virStateDriverTabCount ; i++) { @@ -618,7 +618,7 @@ return ret; } -int __virStateActive(void) { +int virStateActive(void) { int i, ret = 0; for (i = 0 ; i < virStateDriverTabCount ; i++) { @@ -970,7 +970,7 @@ * implementation of driver features in the remote case. */ int -__virDrvSupportsFeature (virConnectPtr conn, int feature) +virDrvSupportsFeature (virConnectPtr conn, int feature) { DEBUG("conn=%p, feature=%d", conn, feature); @@ -2258,7 +2258,7 @@ * implementation of migration in the remote case. */ int -__virDomainMigratePrepare (virConnectPtr dconn, +virDomainMigratePrepare (virConnectPtr dconn, char **cookie, int *cookielen, const char *uri_in, @@ -2287,7 +2287,7 @@ * implementation of migration in the remote case. */ int -__virDomainMigratePerform (virDomainPtr domain, +virDomainMigratePerform (virDomainPtr domain, const char *cookie, int cookielen, const char *uri, @@ -2317,7 +2317,7 @@ * implementation of migration in the remote case. */ virDomainPtr -__virDomainMigrateFinish (virConnectPtr dconn, +virDomainMigrateFinish (virConnectPtr dconn, const char *dname, const char *cookie, int cookielen, diff -r 2a018ec3c877 src/libvirt_internal.h --- a/src/libvirt_internal.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/libvirt_internal.h Thu Oct 30 10:46:19 2008 +0000 @@ -26,39 +26,35 @@ #ifdef WITH_LIBVIRTD -int __virStateInitialize(void); -int __virStateCleanup(void); -int __virStateReload(void); -int __virStateActive(void); -#define virStateInitialize() __virStateInitialize() -#define virStateCleanup() __virStateCleanup() -#define virStateReload() __virStateReload() -#define virStateActive() __virStateActive() +int virStateInitialize(void); +int virStateCleanup(void); +int virStateReload(void); +int virStateActive(void); #endif -int __virDrvSupportsFeature (virConnectPtr conn, int feature); +int virDrvSupportsFeature (virConnectPtr conn, int feature); -int __virDomainMigratePrepare (virConnectPtr dconn, - char **cookie, - int *cookielen, - const char *uri_in, - char **uri_out, - unsigned long flags, - const char *dname, - unsigned long bandwidth); -int __virDomainMigratePerform (virDomainPtr domain, - const char *cookie, - int cookielen, - const char *uri, - unsigned long flags, - const char *dname, - unsigned long bandwidth); -virDomainPtr __virDomainMigrateFinish (virConnectPtr dconn, - const char *dname, - const char *cookie, - int cookielen, - const char *uri, - unsigned long flags); +int virDomainMigratePrepare (virConnectPtr dconn, + char **cookie, + int *cookielen, + const char *uri_in, + char **uri_out, + unsigned long flags, + const char *dname, + unsigned long bandwidth); +int virDomainMigratePerform (virDomainPtr domain, + const char *cookie, + int cookielen, + const char *uri, + unsigned long flags, + const char *dname, + unsigned long bandwidth); +virDomainPtr virDomainMigrateFinish (virConnectPtr dconn, + const char *dname, + const char *cookie, + int cookielen, + const char *uri, + unsigned long flags); #endif diff -r 2a018ec3c877 src/libvirt_sym.version --- a/src/libvirt_sym.version Thu Oct 30 10:11:40 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -{ - global: - virInitialize; - virConnectOpen; - virConnectOpenReadOnly; - virConnectOpenAuth; - virConnectAuthPtrDefault; - - virConnectClose; - virConnectGetType; - virConnectGetVersion; - virConnectGetHostname; - virConnectGetURI; - virDomainGetConnect; - virConnectListDomains; - virConnectNumOfDomains; - virDomainCreate; - virDomainCreateLinux; - virDomainCreateXML; - virDomainDefineXML; - virDomainDestroy; - virDomainFree; - virDomainGetID; - virDomainGetUUID; - virDomainGetUUIDString; - virDomainGetInfo; - virNodeGetCellsFreeMemory; - virDomainGetMaxMemory; - virDomainGetName; - virDomainGetOSType; - virDomainGetXMLDesc; - virDomainLookupByID; - virDomainLookupByName; - virDomainLookupByUUID; - virDomainLookupByUUIDString; - virDomainRestore; - virDomainResume; - virDomainSave; - virDomainCoreDump; - virDomainSetMemory; - virDomainSetMaxMemory; - virDomainShutdown; - virDomainReboot; - virDomainSuspend; - virConnectListDefinedDomains; - virConnectNumOfDefinedDomains; - virConnectGetMaxVcpus; - virDomainUndefine; - virDomainGetAutostart; - virDomainSetAutostart; - virGetVersion; - virCopyLastError; - virConnSetErrorFunc; - virResetLastError; - virErrorFunc; - virResetError; - virConnGetLastError; - virGetLastError; - virSetErrorFunc; - virConnCopyLastError; - virConnResetLastError; - virDefaultErrorFunc; - virNodeGetInfo; - virConnectGetCapabilities; - virNodeGetCellsFreeMemory; - virNodeGetFreeMemory; - - virDomainSetVcpus; - virDomainPinVcpu; - virDomainGetVcpus; - virDomainGetMaxVcpus; - virDomainGetSchedulerType; - virDomainGetSchedulerParameters; - virDomainSetSchedulerParameters; - virDomainBlockStats; - virDomainInterfaceStats; - virDomainBlockPeek; - virDomainMemoryPeek; - virDomainAttachDevice; - virDomainDetachDevice; - - virDomainMigrate; - - virNetworkGetConnect; - virConnectNumOfNetworks; - virConnectListNetworks; - virConnectNumOfDefinedNetworks; - virConnectListDefinedNetworks; - virNetworkLookupByName; - virNetworkLookupByUUID; - virNetworkLookupByUUIDString; - virNetworkCreateXML; - virNetworkDefineXML; - virNetworkUndefine; - virNetworkCreate; - virNetworkDestroy; - virNetworkFree; - virNetworkGetName; - virNetworkGetUUID; - virNetworkGetUUIDString; - virNetworkGetXMLDesc; - virNetworkGetBridgeName; - virNetworkGetAutostart; - virNetworkSetAutostart; - - virStoragePoolGetConnect; - virConnectNumOfStoragePools; - virConnectNumOfDefinedStoragePools; - virConnectListStoragePools; - virConnectListDefinedStoragePools; - virConnectFindStoragePoolSources; - virStoragePoolLookupByName; - virStoragePoolLookupByUUID; - virStoragePoolLookupByUUIDString; - virStoragePoolLookupByVolume; - virStoragePoolCreateXML; - virStoragePoolDefineXML; - virStoragePoolUndefine; - virStoragePoolCreate; - virStoragePoolBuild; - virStoragePoolDestroy; - virStoragePoolDelete; - virStoragePoolRefresh; - virStoragePoolFree; - virStoragePoolGetName; - virStoragePoolGetUUID; - virStoragePoolGetUUIDString; - virStoragePoolGetInfo; - virStoragePoolGetXMLDesc; - virStoragePoolSetAutostart; - virStoragePoolGetAutostart; - virStoragePoolNumOfVolumes; - virStoragePoolListVolumes; - - virConnectNumOfStorageVolumes; - virConnectListStorageVolumes; - virStorageVolGetConnect; - virStorageVolLookupByName; - virStorageVolLookupByKey; - virStorageVolLookupByPath; - virStorageVolCreateXML; - virStorageVolDelete; - virStorageVolFree; - virStorageVolGetName; - virStorageVolGetKey; - virStorageVolGetInfo; - virStorageVolGetXMLDesc; - virStorageVolGetPath; - - virEventRegisterImpl; - virConnectDomainEventRegister; - virConnectDomainEventDeregister; - - /* Symbols with __ are private only - for use by the libvirtd daemon. - They are not part of stable ABI - guarentee provided for the public - symbols above */ - - __virConfNew; - __virConfReadFile; - __virConfReadMem; - __virConfFree; - __virConfGetValue; - __virConfSetValue; - __virConfWriteFile; - __virConfWriteMem; - - __virGetDomain; - __virGetNetwork; - __virGetStoragePool; - __virGetStorageVol; - - __virStateInitialize; - __virStateCleanup; - __virStateReload; - __virStateActive; - __virStateSigDispatcher; - - __virDrvSupportsFeature; - - __virDomainMigratePrepare; - __virDomainMigratePerform; - __virDomainMigrateFinish; - - __virFileReadAll; - __virStrToLong_i; - __virStrToLong_ull; - - __virBufferVSprintf; - __virBufferAdd; - __virBufferAddChar; - __virBufferContentAndReset; - __virBufferError; - - __virMacAddrCompare; - - __virAlloc; - __virAllocN; - __virReallocN; - __virFree; - local: *; -}; diff -r 2a018ec3c877 src/libvirt_sym.version.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libvirt_sym.version.in Thu Oct 30 10:46:19 2008 +0000 @@ -0,0 +1,318 @@ +/* + * WARNING: libvirt_sym.version.in is the master file + * + * WARNING: libvirt_sym.version is auto-generated by configure + */ + +/* + * First officially exported symbols, for which header + * file definitions are installed in /usr/include/libvirt + * either from libvirt.h and virterror.h + * + * Versions here are *fixed* to match the libvirt version + * at which the symbol was introduced. This ensures that + * a new client app requiring symbol foo() can't accidentally + * run with old libvirt.so not providing foo() - the global + * soname version info can't enforce this since we never + * change the soname + */ +LIBVIRT_0.0.3 { + global: + virConnectClose; + virConnectGetType; + virConnectGetVersion; + virConnectListDomains; + virConnectNumOfDomains; + virConnectOpen; + virConnectOpenReadOnly; + + virDomainCreateLinux; + virDomainDestroy; + virDomainFree; + virDomainGetID; + virDomainGetInfo; + virDomainGetMaxMemory; + virDomainGetName; + virDomainGetOSType; + virDomainGetXMLDesc; + virDomainLookupByID; + virDomainLookupByName; + virDomainRestore; + virDomainResume; + virDomainSave; + virDomainSetMaxMemory; + virDomainShutdown; + virDomainSuspend; + + virGetVersion; +}; + +LIBVIRT_0.0.5 { + global: + virDomainLookupByUUID; + virDomainGetUUID; +} LIBVIRT_0.0.3; + +LIBVIRT_0.1.0 { + global: + virInitialize; + virNodeGetInfo; + virDomainReboot; + + virCopyLastError; + virConnSetErrorFunc; + virResetLastError; + virErrorFunc; + virResetError; + virConnGetLastError; + virGetLastError; + virSetErrorFunc; + virConnCopyLastError; + virConnResetLastError; + virDefaultErrorFunc; +} LIBVIRT_0.0.5; + +LIBVIRT_0.1.1 { + global: + virDomainLookupByUUIDString; + virDomainGetUUIDString; + virDomainSetMemory; + virDomainDefineXML; + virDomainCreate; + virDomainUndefine; + virConnectListDefinedDomains; +} LIBVIRT_0.1.0; + +LIBVIRT_0.1.4 { + global: + virDomainSetVcpus; + virDomainPinVcpu; + virDomainGetVcpus; +} LIBVIRT_0.1.1; + +LIBVIRT_0.1.5 { + global: + virConnectNumOfDefinedDomains; +} LIBVIRT_0.1.4; + +LIBVIRT_0.1.9 { + global: + virDomainCoreDump; + virDomainAttachDevice; + virDomainDetachDevice; +} LIBVIRT_0.1.5; + +LIBVIRT_0.2.0 { + global: + virConnectNumOfNetworks; + virConnectListNetworks; + virConnectNumOfDefinedNetworks; + virConnectListDefinedNetworks; + virNetworkLookupByName; + virNetworkLookupByUUID; + virNetworkLookupByUUIDString; + virNetworkCreateXML; + virNetworkDefineXML; + virNetworkUndefine; + virNetworkCreate; + virNetworkDestroy; + virNetworkFree; + virNetworkGetName; + virNetworkGetUUID; + virNetworkGetUUIDString; + virNetworkGetXMLDesc; + virNetworkGetBridgeName; +} LIBVIRT_0.1.9; + +LIBVIRT_0.2.1 { + global: + virConnectGetCapabilities; + virConnectGetMaxVcpus; + virDomainGetMaxVcpus; + virDomainGetAutostart; + virDomainSetAutostart; + virNetworkGetAutostart; + virNetworkSetAutostart; +} LIBVIRT_0.2.0; + +LIBVIRT_0.2.3 { + global: + virDomainGetSchedulerType; + virDomainGetSchedulerParameters; + virDomainSetSchedulerParameters; +} LIBVIRT_0.2.1; + +LIBVIRT_0.3.0 { + global: + virConnectGetHostname; + virConnectGetURI; + virDomainGetConnect; + virNetworkGetConnect; +} LIBVIRT_0.2.3; + +LIBVIRT_0.3.2 { + global: + virDomainMigrate; + virDomainBlockStats; + virDomainInterfaceStats; +} LIBVIRT_0.3.0; + +LIBVIRT_0.3.3 { + global: + virNodeGetCellsFreeMemory; + virNodeGetFreeMemory; +} LIBVIRT_0.3.2; + +LIBVIRT_0.4.0 { + global: + virConnectOpenAuth; + virConnectAuthPtrDefault; +} LIBVIRT_0.3.3; + +LIBVIRT_0.4.1 { + global: + virStoragePoolGetConnect; + virConnectNumOfStoragePools; + virConnectNumOfDefinedStoragePools; + virConnectListStoragePools; + virConnectListDefinedStoragePools; + virStoragePoolLookupByName; + virStoragePoolLookupByUUID; + virStoragePoolLookupByUUIDString; + virStoragePoolLookupByVolume; + virStoragePoolCreateXML; + virStoragePoolDefineXML; + virStoragePoolUndefine; + virStoragePoolCreate; + virStoragePoolBuild; + virStoragePoolDestroy; + virStoragePoolDelete; + virStoragePoolRefresh; + virStoragePoolFree; + virStoragePoolGetName; + virStoragePoolGetUUID; + virStoragePoolGetUUIDString; + virStoragePoolGetInfo; + virStoragePoolGetXMLDesc; + virStoragePoolSetAutostart; + virStoragePoolGetAutostart; + virStoragePoolNumOfVolumes; + virStoragePoolListVolumes; + + virConnectNumOfStorageVolumes; + virConnectListStorageVolumes; + virStorageVolGetConnect; + virStorageVolLookupByName; + virStorageVolLookupByKey; + virStorageVolLookupByPath; + virStorageVolCreateXML; + virStorageVolDelete; + virStorageVolFree; + virStorageVolGetName; + virStorageVolGetKey; + virStorageVolGetInfo; + virStorageVolGetXMLDesc; + virStorageVolGetPath; +} LIBVIRT_0.4.0; + +LIBVIRT_0.4.2 { + global: + virDomainBlockPeek; + virDomainMemoryPeek; +} LIBVIRT_0.4.1; + +LIBVIRT_0.4.5 { + global: + virConnectFindStoragePoolSources; +} LIBVIRT_0.4.2; + +LIBVIRT_0.5.0 { + global: + virDomainCreateXML; + virEventRegisterImpl; + virConnectDomainEventRegister; + virConnectDomainEventDeregister; +} LIBVIRT_0.4.5; + +/* .... define new API here using predicted next version number .... */ + + + + +/* + * Finally these symbols are private and semantics may change + * on every release, hence the version number is spliced in at + * build time. This ensures that if libvirtd, virsh, or a driver + * module was built against one libvirt release, it will refuse + * to load with another where symbols may have same names but + * different semantics. + * + * No header files are provided outside the source tree. + * + * Keep this section ordered alphabetically by header file name + * + * Symbols here are only for use by virsh, libvirtd and dlopen + * driver modules + */ +LIBVIRT_PRIVATE_@VERSION@ { + + global: + + /* buf.h */ + virBufferVSprintf; + virBufferAdd; + virBufferAddChar; + virBufferContentAndReset; + virBufferError; + + + /* conf.h */ + virConfNew; + virConfReadFile; + virConfReadMem; + virConfFree; + virConfGetValue; + virConfSetValue; + virConfWriteFile; + virConfWriteMem; + + + /* datatypes.h */ + virGetDomain; + virGetNetwork; + virGetStoragePool; + virGetStorageVol; + + + /* libvirt_internal.h */ + virStateInitialize; + virStateCleanup; + virStateReload; + virStateActive; + virStateSigDispatcher; + virDrvSupportsFeature; + virDomainMigratePrepare; + virDomainMigratePerform; + virDomainMigrateFinish; + + + /* memory.h */ + virAlloc; + virAllocN; + virReallocN; + virFree; + + + /* util.h */ + virFileReadAll; + virStrToLong_i; + virStrToLong_ull; + saferead; + safewrite; + virMacAddrCompare; + + + /* Finally everything else is totally private */ + local: + *; +}; diff -r 2a018ec3c877 src/memory.c --- a/src/memory.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/memory.c Thu Oct 30 10:46:19 2008 +0000 @@ -88,7 +88,7 @@ * * Returns -1 on failure to allocate, zero on success */ -int __virAlloc(void *ptrptr, size_t size) +int virAlloc(void *ptrptr, size_t size) { #if TEST_OOM if (virAllocTestFail()) { @@ -116,7 +116,7 @@ * * Returns -1 on failure to allocate, zero on success */ -int __virAllocN(void *ptrptr, size_t size, size_t count) +int virAllocN(void *ptrptr, size_t size, size_t count) { #if TEST_OOM if (virAllocTestFail()) { @@ -145,7 +145,7 @@ * * Returns -1 on failure to allocate, zero on success */ -int __virReallocN(void *ptrptr, size_t size, size_t count) +int virReallocN(void *ptrptr, size_t size, size_t count) { void *tmp; #if TEST_OOM @@ -172,7 +172,7 @@ * the 'ptrptr' variable. After release, 'ptrptr' will be * updated to point to NULL. */ -void __virFree(void *ptrptr) +void virFree(void *ptrptr) { free(*(void**)ptrptr); *(void**)ptrptr = NULL; diff -r 2a018ec3c877 src/memory.h --- a/src/memory.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/memory.h Thu Oct 30 10:46:19 2008 +0000 @@ -45,10 +45,10 @@ /* Don't call these directly - use the macros below */ -int __virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK; -int __virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; -int __virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; -void __virFree(void *ptrptr); +int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK; +int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; +int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK; +void virFree(void *ptrptr); /** * VIR_ALLOC: @@ -60,7 +60,7 @@ * * Returns -1 on failure, 0 on success */ -#define VIR_ALLOC(ptr) __virAlloc(&(ptr), sizeof(*(ptr))) +#define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr))) /** * VIR_ALLOC_N: @@ -73,7 +73,7 @@ * * Returns -1 on failure, 0 on success */ -#define VIR_ALLOC_N(ptr, count) __virAllocN(&(ptr), sizeof(*(ptr)), (count)) +#define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count)) /** * VIR_REALLOC_N: @@ -86,7 +86,7 @@ * * Returns -1 on failure, 0 on success */ -#define VIR_REALLOC_N(ptr, count) __virReallocN(&(ptr), sizeof(*(ptr)), (count)) +#define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count)) /** * VIR_FREE: @@ -95,7 +95,7 @@ * Free the memory stored in 'ptr' and update to point * to NULL. */ -#define VIR_FREE(ptr) __virFree(&(ptr)) +#define VIR_FREE(ptr) virFree(&(ptr)) #if TEST_OOM diff -r 2a018ec3c877 src/util-lib.c --- a/src/util-lib.c Thu Oct 30 10:11:40 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * common, generic utility functions - * - * Copyright (C) 2006, 2007, 2008 Red Hat, Inc. - * See COPYING.LIB for the License of this software - */ - -#include <config.h> - -#include <unistd.h> -#include <errno.h> - -#include "util-lib.h" - -/* Like read(), but restarts after EINTR */ -int saferead(int fd, void *buf, size_t count) -{ - size_t nread = 0; - while (count > 0) { - ssize_t r = read(fd, buf, count); - if (r < 0 && errno == EINTR) - continue; - if (r < 0) - return r; - if (r == 0) - return nread; - buf = (char *)buf + r; - count -= r; - nread += r; - } - return nread; -} - -/* Like write(), but restarts after EINTR */ -ssize_t safewrite(int fd, const void *buf, size_t count) -{ - size_t nwritten = 0; - while (count > 0) { - ssize_t r = write(fd, buf, count); - - if (r < 0 && errno == EINTR) - continue; - if (r < 0) - return r; - if (r == 0) - return nwritten; - buf = (const char *)buf + r; - count -= r; - nwritten += r; - } - return nwritten; -} diff -r 2a018ec3c877 src/util-lib.h --- a/src/util-lib.h Thu Oct 30 10:11:40 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/* - * private utility functions - * - * Copyright (C) 2008 Red Hat, Inc. - * See COPYING.LIB for the License of this software - */ - -#ifndef __UTIL_LIB_H__ -#define __UTIL_LIB_H__ - -#include <sys/types.h> - -/* - * To avoid a double definition of the function when compiling - * programs using both util-lib and libvirt, like virsh - */ -#ifdef IN_LIBVIRT -#define saferead libvirt_saferead -#define safewrite libvirt_safewrite -#endif - -int saferead(int fd, void *buf, size_t count); -ssize_t safewrite(int fd, const void *buf, size_t count); - -#endif diff -r 2a018ec3c877 src/util.c --- a/src/util.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/util.c Thu Oct 30 10:46:19 2008 +0000 @@ -52,7 +52,6 @@ #include "buf.h" #include "util.h" #include "memory.h" -#include "util-lib.c" #ifndef NSIG # define NSIG 32 @@ -64,11 +63,51 @@ #define virLog(msg...) fprintf(stderr, msg) -#ifndef PROXY #define ReportError(conn, code, fmt...) \ virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \ __FUNCTION__, __LINE__, fmt) + +/* Like read(), but restarts after EINTR */ +int saferead(int fd, void *buf, size_t count) +{ + size_t nread = 0; + while (count > 0) { + ssize_t r = read(fd, buf, count); + if (r < 0 && errno == EINTR) + continue; + if (r < 0) + return r; + if (r == 0) + return nread; + buf = (char *)buf + r; + count -= r; + nread += r; + } + return nread; +} + +/* Like write(), but restarts after EINTR */ +ssize_t safewrite(int fd, const void *buf, size_t count) +{ + size_t nwritten = 0; + while (count > 0) { + ssize_t r = write(fd, buf, count); + + if (r < 0 && errno == EINTR) + continue; + if (r < 0) + return r; + if (r == 0) + return nwritten; + buf = (const char *)buf + r; + count -= r; + nwritten += r; + } + return nwritten; +} + +#ifndef PROXY int virFileStripSuffix(char *str, const char *suffix) @@ -502,7 +541,7 @@ } /* Like virFileReadLimFP, but use a file descriptor rather than a FILE*. */ -int __virFileReadLimFD(int fd_arg, int maxlen, char **buf) +int virFileReadLimFD(int fd_arg, int maxlen, char **buf) { int fd = dup (fd_arg); if (fd >= 0) { @@ -522,7 +561,7 @@ return -1; } -int __virFileReadAll(const char *path, int maxlen, char **buf) +int virFileReadAll(const char *path, int maxlen, char **buf) { FILE *fh = fopen(path, "r"); if (fh == NULL) { @@ -812,7 +851,7 @@ validity. This function is careful to return -1 when the string S represents a number that is not representable as an "int". */ int -__virStrToLong_i(char const *s, char **end_ptr, int base, int *result) +virStrToLong_i(char const *s, char **end_ptr, int base, int *result) { long int val; char *p; @@ -869,7 +908,7 @@ /* Just like virStrToLong_i, above, but produce an "unsigned long long" value. */ int -__virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *result) +virStrToLong_ull(char const *s, char **end_ptr, int base, unsigned long long *result) { unsigned long long val; char *p; @@ -941,7 +980,7 @@ * as well as leading zeros. */ int -__virMacAddrCompare (const char *p, const char *q) +virMacAddrCompare (const char *p, const char *q) { unsigned char c, d; do { diff -r 2a018ec3c877 src/util.h --- a/src/util.h Thu Oct 30 10:11:40 2008 +0000 +++ b/src/util.h Thu Oct 30 10:46:19 2008 +0000 @@ -25,9 +25,11 @@ #ifndef __VIR_UTIL_H__ #define __VIR_UTIL_H__ -#include "util-lib.h" #include "verify.h" #include <sys/select.h> + +int saferead(int fd, void *buf, size_t count); +ssize_t safewrite(int fd, const void *buf, size_t count); enum { VIR_EXEC_NONE = 0, @@ -46,11 +48,9 @@ int flags); int virRun(virConnectPtr conn, const char *const*argv, int *status); -int __virFileReadLimFD(int fd, int maxlen, char **buf); -#define virFileReadLimFD(fd,m,b) __virFileReadLimFD((fd),(m),(b)) +int virFileReadLimFD(int fd, int maxlen, char **buf); -int __virFileReadAll(const char *path, int maxlen, char **buf); -#define virFileReadAll(p,m,b) __virFileReadAll((p),(m),(b)) +int virFileReadAll(const char *path, int maxlen, char **buf); int virFileMatchesNameSuffix(const char *file, const char *name, @@ -88,11 +88,10 @@ int virFileDeletePid(const char *dir, const char *name); -int __virStrToLong_i(char const *s, +int virStrToLong_i(char const *s, char **end_ptr, int base, int *result); -#define virStrToLong_i(s,e,b,r) __virStrToLong_i((s),(e),(b),(r)) int virStrToLong_ui(char const *s, char **end_ptr, @@ -102,14 +101,12 @@ char **end_ptr, int base, long long *result); -int __virStrToLong_ull(char const *s, - char **end_ptr, - int base, - unsigned long long *result); -#define virStrToLong_ull(s,e,b,r) __virStrToLong_ull((s),(e),(b),(r)) +int virStrToLong_ull(char const *s, + char **end_ptr, + int base, + unsigned long long *result); -int __virMacAddrCompare (const char *mac1, const char *mac2); -#define virMacAddrCompare(mac1,mac2) __virMacAddrCompare((mac1),(mac2)) +int virMacAddrCompare (const char *mac1, const char *mac2); void virSkipSpaces(const char **str); int virParseNumber(const char **str); diff -r 2a018ec3c877 src/virsh.c --- a/src/virsh.c Thu Oct 30 10:11:40 2008 +0000 +++ b/src/virsh.c Thu Oct 30 10:46:19 2008 +0000 @@ -47,7 +47,6 @@ #include "buf.h" #include "console.h" #include "util.h" -#include "util-lib.h" static char *progname; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:41:14PM +0000, Daniel P. Berrange wrote:
The libvirt.so file currently whitelists all the symbols in our public API. libvirtd and virsh, however, also want to use a bunch of our so called 'private' symbols which aren't in the public API. For saferead and safewrite() we dealt with this by compiling the code twice with some nasty macro tricks to give the function a different name to avoid dup symbols when statically linking. For the other APIs, we prefixed them with __ and then just added them to the exports.
Neither option is very good because they both impose a burden on the source code - needing to append __ everywhere and write crazy macros. Each time we want to export another symbol, we have to make lots of manual changes to add __. This was OK if it was just a handful of symbols, but we're now upto 30 odd, and its not scaling. When we make drivers modular we'll be adding 100's more symbols.
As an aside, we use ELF library versioning when linking, via the libtool -version-info flag. Since we maintain ABI compat going forwards though, the version in the eventual .so is always going to be 'libvirt.so.0'. This is sub-optimal because you may build a binary that requires 'virDomainBlockPeek' which appeared in libvirt 0.4.2, but the ELF version cannot validate this. There is nothing stopping your application launching against libvirt 0.3.0 and then aborting with a linker failure sometime while it is running when it eventually referneces the non-existant symbol. Likewise RPM automatic versioning hooks off the ELF version too, so that's not preventing you installing too old a libvirt for your app's needs.
A far better solution to all these problems has been sitting in front of us the whole time. Namely we need to make full use of the linkers symbol version scripts.
Our current libvirt_sym.version script is defining an unversioned set of symbols. This only enforces what's exported, and can do nothing about version compatability. So instead we need to switch to a fully versioned script, where every symbol we export is tagged with the libvirt version number at which it was introduced.
Taking the virDomainBlockPeek example again, this appeared in the libvirt 0.4.2 release, so we'd add a section to the linker script
LIBVIRT_0.4.2 { global: virDomainBlockPeek; virDomainMemoryPeek; } LIBVIRT_0.4.1;
Then 0.4.5 added in storage pool discovery so you get another section
LIBVIRT_0.4.5 { global: virConnectFindStoragePoolSources; } LIBVIRT_0.4.2;
And so on for every release.
The resulting libvirt.so file will thus gain metadata listing all the ABI versions for all symbols it includes.
That deals with public APIs. Now we also want to export some internal APIs whose semantics/syntax may arbitrarily change between releases. Thus they should not be included in any of the formal public version sections.
Instead they should be in a seperate versioned section, whose version changes on every release. This will ensure that if libvirtd or virsh link to some internal symbols, they are guareteened to only run against the exactly same libvirt.so they were linked to. This will avoid some nasty bugs our users have hit where they installed a custom libvirt version on their OS which already had another version installed, and then libvirtd crashed/behave wierdly/etc
To do this we rename libvirt_sym.version to libvirt_sym.version.in and add a section called
LIBVIRT_PRIVATE_@VERSION@ {
global: /* libvirt_internal.h */ debugFlag; virStateInitialize; virStateCleanup; virStateReload; virStateActive;
.... more private symbols... }
The @VERSION@ gets subsituted by the version number of the libvirt release by configure.
Do a build with this all active and look at the resulting libvirt.so using objdump (or eu-readelf).
# objdump -p src/.libs/libvirt.so Version definitions: 1 0x01 0x0e5a1d10 libvirt.so.0 2 0x00 0x0af6bd33 LIBVIRT_0.0.3 3 0x00 0x0af6bd35 LIBVIRT_0.0.5 LIBVIRT_0.0.3 4 0x00 0x0af6be30 LIBVIRT_0.1.0 LIBVIRT_0.0.5 5 0x00 0x0af6be31 LIBVIRT_0.1.1 LIBVIRT_0.1.0 6 0x00 0x0af6be34 LIBVIRT_0.1.4 LIBVIRT_0.1.1 7 0x00 0x0af6be35 LIBVIRT_0.1.5 LIBVIRT_0.1.4 8 0x00 0x0af6be39 LIBVIRT_0.1.9 LIBVIRT_0.1.5 9 0x00 0x0af6bb30 LIBVIRT_0.2.0 LIBVIRT_0.1.9 10 0x00 0x0af6bb31 LIBVIRT_0.2.1 LIBVIRT_0.2.0 11 0x00 0x0af6bb33 LIBVIRT_0.2.3 LIBVIRT_0.2.1 12 0x00 0x0af6bc30 LIBVIRT_0.3.0 LIBVIRT_0.2.3 13 0x00 0x0af6bc32 LIBVIRT_0.3.2 LIBVIRT_0.3.0 14 0x00 0x0af6bc33 LIBVIRT_0.3.3 LIBVIRT_0.3.2 15 0x00 0x0af6b930 LIBVIRT_0.4.0 LIBVIRT_0.3.3 16 0x00 0x0af6b931 LIBVIRT_0.4.1 LIBVIRT_0.4.0 17 0x00 0x0af6b932 LIBVIRT_0.4.2 LIBVIRT_0.4.1 18 0x00 0x0af6b935 LIBVIRT_0.4.5 LIBVIRT_0.4.2 19 0x00 0x0af6ba30 LIBVIRT_0.5.0 LIBVIRT_0.4.5 20 0x00 0x09e39b06 LIBVIRT_PRIVATE_0.4.6
You can see that as well as the main SONAME libvirt.so.0, we've got version info for each release which introduced new public API symbols, as well as our versioned private symbols. If you look at glibc's libc.so, you'll see a similar set of versioned interfaces.
Then take a look at the virsh binary, and see that it has references to all of the versions corresponding to symbols it uses. You can also see that it used some libvirt internal symbols, by presence of the LIBVIRT_PRIVATE_0.4.6 reference. This ensures that this virsh binary can't accidentally be used against libvirt 0.4.5 or 0.4.7 where it'd likely crash at runtime
# objdump -p src/.libs/virsh Version References: required from libpthread.so.0: 0x09691a75 0x00 10 GLIBC_2.2.5 required from libc.so.6: 0x0d696918 0x00 19 GLIBC_2.8 0x09691974 0x00 13 GLIBC_2.3.4 0x09691a75 0x00 04 GLIBC_2.2.5 required from libvirt.so.0: 0x0af6ba30 0x00 22 LIBVIRT_0.5.0 0x0af6bc30 0x00 21 LIBVIRT_0.3.0 0x0af6bc33 0x00 20 LIBVIRT_0.3.3 0x0af6be34 0x00 18 LIBVIRT_0.1.4 0x0af6be35 0x00 17 LIBVIRT_0.1.5 0x0af6b935 0x00 16 LIBVIRT_0.4.5 0x0af6be31 0x00 15 LIBVIRT_0.1.1 0x0af6bc32 0x00 14 LIBVIRT_0.3.2 0x0af6be39 0x00 12 LIBVIRT_0.1.9 0x0af6bd33 0x00 11 LIBVIRT_0.0.3 0x0af6bb31 0x00 09 LIBVIRT_0.2.1 0x09e39b06 0x00 08 LIBVIRT_PRIVATE_0.4.6 0x0af6b930 0x00 07 LIBVIRT_0.4.0 0x0af6bb30 0x00 06 LIBVIRT_0.2.0 0x0af6be30 0x00 05 LIBVIRT_0.1.0 0x0af6bb33 0x00 03 LIBVIRT_0.2.3 0x0af6b931 0x00 02 LIBVIRT_0.4.1
As a further example, of something using only a subset of the API, consider a really trivial 3 liner demo program which uses 3 functions: $ cat demo.c #include <stdio.h> #include <libvirt/libvirt.h> int main() { char buf[10]; virDomainPtr dom; virConnectPtr cb = virConnectOpen(NULL); dom = virDomainLookupByName(cb, "foo"); virDomainBlockPeek(dom, "hda", 0, 10, buf, 0); } $ gcc -o demo -lvirt demo.c $ objdump -p demo Version References: required from libc.so.6: 0x09691a75 0x00 03 GLIBC_2.2.5 required from libvirt.so.0: 0x0af6b932 0x00 04 LIBVIRT_0.4.2 0x0af6bd33 0x00 02 LIBVIRT_0.0.3 So you can see the linker only encodes the exact versions used by the 3 vir* methods it calls. 0.0.3 for virConnectOpen and virDomainLookupByName, and 0.4.2 for virDomainBlockPeek. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 04:56:30PM +0000, Daniel P. Berrange wrote:
On Thu, Oct 30, 2008 at 01:41:14PM +0000, Daniel P. Berrange wrote:
The libvirt.so file currently whitelists all the symbols in our public API. libvirtd and virsh, however, also want to use a bunch of our so called 'private' symbols which aren't in the public API. For saferead and safewrite() we dealt with this by compiling the code twice with some nasty macro tricks to give the function a different name to avoid dup symbols when statically linking. For the other APIs, we prefixed them with __ and then just added them to the exports.
Neither option is very good because they both impose a burden on the source code - needing to append __ everywhere and write crazy macros. Each time we want to export another symbol, we have to make lots of manual changes to add __. This was OK if it was just a handful of symbols, but we're now upto 30 odd, and its not scaling. When we make drivers modular we'll be adding 100's more symbols.
As an aside, we use ELF library versioning when linking, via the libtool -version-info flag. Since we maintain ABI compat going forwards though, the version in the eventual .so is always going to be 'libvirt.so.0'. This is sub-optimal because you may build a binary that requires 'virDomainBlockPeek' which appeared in libvirt 0.4.2, but the ELF version cannot validate this. There is nothing stopping your application launching against libvirt 0.3.0 and then aborting with a linker failure sometime while it is running when it eventually referneces the non-existant symbol. Likewise RPM automatic versioning hooks off the ELF version too, so that's not preventing you installing too old a libvirt for your app's needs.
A far better solution to all these problems has been sitting in front of us the whole time. Namely we need to make full use of the linkers symbol version scripts.
Our current libvirt_sym.version script is defining an unversioned set of symbols. This only enforces what's exported, and can do nothing about version compatability. So instead we need to switch to a fully versioned script, where every symbol we export is tagged with the libvirt version number at which it was introduced.
Taking the virDomainBlockPeek example again, this appeared in the libvirt 0.4.2 release, so we'd add a section to the linker script
LIBVIRT_0.4.2 { global: virDomainBlockPeek; virDomainMemoryPeek; } LIBVIRT_0.4.1;
Then 0.4.5 added in storage pool discovery so you get another section
LIBVIRT_0.4.5 { global: virConnectFindStoragePoolSources; } LIBVIRT_0.4.2;
And so on for every release.
The resulting libvirt.so file will thus gain metadata listing all the ABI versions for all symbols it includes.
That deals with public APIs. Now we also want to export some internal APIs whose semantics/syntax may arbitrarily change between releases. Thus they should not be included in any of the formal public version sections.
Instead they should be in a seperate versioned section, whose version changes on every release. This will ensure that if libvirtd or virsh link to some internal symbols, they are guareteened to only run against the exactly same libvirt.so they were linked to. This will avoid some nasty bugs our users have hit where they installed a custom libvirt version on their OS which already had another version installed, and then libvirtd crashed/behave wierdly/etc
To do this we rename libvirt_sym.version to libvirt_sym.version.in and add a section called
LIBVIRT_PRIVATE_@VERSION@ {
global: /* libvirt_internal.h */ debugFlag; virStateInitialize; virStateCleanup; virStateReload; virStateActive;
.... more private symbols... }
The @VERSION@ gets subsituted by the version number of the libvirt release by configure.
Do a build with this all active and look at the resulting libvirt.so using objdump (or eu-readelf).
# objdump -p src/.libs/libvirt.so Version definitions: 1 0x01 0x0e5a1d10 libvirt.so.0 2 0x00 0x0af6bd33 LIBVIRT_0.0.3 3 0x00 0x0af6bd35 LIBVIRT_0.0.5 LIBVIRT_0.0.3 4 0x00 0x0af6be30 LIBVIRT_0.1.0 LIBVIRT_0.0.5 5 0x00 0x0af6be31 LIBVIRT_0.1.1 LIBVIRT_0.1.0 6 0x00 0x0af6be34 LIBVIRT_0.1.4 LIBVIRT_0.1.1 7 0x00 0x0af6be35 LIBVIRT_0.1.5 LIBVIRT_0.1.4 8 0x00 0x0af6be39 LIBVIRT_0.1.9 LIBVIRT_0.1.5 9 0x00 0x0af6bb30 LIBVIRT_0.2.0 LIBVIRT_0.1.9 10 0x00 0x0af6bb31 LIBVIRT_0.2.1 LIBVIRT_0.2.0 11 0x00 0x0af6bb33 LIBVIRT_0.2.3 LIBVIRT_0.2.1 12 0x00 0x0af6bc30 LIBVIRT_0.3.0 LIBVIRT_0.2.3 13 0x00 0x0af6bc32 LIBVIRT_0.3.2 LIBVIRT_0.3.0 14 0x00 0x0af6bc33 LIBVIRT_0.3.3 LIBVIRT_0.3.2 15 0x00 0x0af6b930 LIBVIRT_0.4.0 LIBVIRT_0.3.3 16 0x00 0x0af6b931 LIBVIRT_0.4.1 LIBVIRT_0.4.0 17 0x00 0x0af6b932 LIBVIRT_0.4.2 LIBVIRT_0.4.1 18 0x00 0x0af6b935 LIBVIRT_0.4.5 LIBVIRT_0.4.2 19 0x00 0x0af6ba30 LIBVIRT_0.5.0 LIBVIRT_0.4.5 20 0x00 0x09e39b06 LIBVIRT_PRIVATE_0.4.6
You can see that as well as the main SONAME libvirt.so.0, we've got version info for each release which introduced new public API symbols, as well as our versioned private symbols. If you look at glibc's libc.so, you'll see a similar set of versioned interfaces.
Then take a look at the virsh binary, and see that it has references to all of the versions corresponding to symbols it uses. You can also see that it used some libvirt internal symbols, by presence of the LIBVIRT_PRIVATE_0.4.6 reference. This ensures that this virsh binary can't accidentally be used against libvirt 0.4.5 or 0.4.7 where it'd likely crash at runtime
# objdump -p src/.libs/virsh Version References: required from libpthread.so.0: 0x09691a75 0x00 10 GLIBC_2.2.5 required from libc.so.6: 0x0d696918 0x00 19 GLIBC_2.8 0x09691974 0x00 13 GLIBC_2.3.4 0x09691a75 0x00 04 GLIBC_2.2.5 required from libvirt.so.0: 0x0af6ba30 0x00 22 LIBVIRT_0.5.0 0x0af6bc30 0x00 21 LIBVIRT_0.3.0 0x0af6bc33 0x00 20 LIBVIRT_0.3.3 0x0af6be34 0x00 18 LIBVIRT_0.1.4 0x0af6be35 0x00 17 LIBVIRT_0.1.5 0x0af6b935 0x00 16 LIBVIRT_0.4.5 0x0af6be31 0x00 15 LIBVIRT_0.1.1 0x0af6bc32 0x00 14 LIBVIRT_0.3.2 0x0af6be39 0x00 12 LIBVIRT_0.1.9 0x0af6bd33 0x00 11 LIBVIRT_0.0.3 0x0af6bb31 0x00 09 LIBVIRT_0.2.1 0x09e39b06 0x00 08 LIBVIRT_PRIVATE_0.4.6 0x0af6b930 0x00 07 LIBVIRT_0.4.0 0x0af6bb30 0x00 06 LIBVIRT_0.2.0 0x0af6be30 0x00 05 LIBVIRT_0.1.0 0x0af6bb33 0x00 03 LIBVIRT_0.2.3 0x0af6b931 0x00 02 LIBVIRT_0.4.1
As a further example, of something using only a subset of the API, consider a really trivial 3 liner demo program which uses 3 functions:
$ cat demo.c #include <stdio.h> #include <libvirt/libvirt.h>
int main() { char buf[10]; virDomainPtr dom; virConnectPtr cb = virConnectOpen(NULL);
dom = virDomainLookupByName(cb, "foo"); virDomainBlockPeek(dom, "hda", 0, 10, buf, 0); }
$ gcc -o demo -lvirt demo.c $ objdump -p demo
Version References: required from libc.so.6: 0x09691a75 0x00 03 GLIBC_2.2.5 required from libvirt.so.0: 0x0af6b932 0x00 04 LIBVIRT_0.4.2 0x0af6bd33 0x00 02 LIBVIRT_0.0.3
So you can see the linker only encodes the exact versions used by the 3 vir* methods it calls. 0.0.3 for virConnectOpen and virDomainLookupByName, and 0.4.2 for virDomainBlockPeek.
Yes, i have no problem with the concept, I'm just worried about the fact that we can't go back if we jump. i was also worried for Solaris but as you pointed out they are using the same (actually it's probably the way around linux borrowed Solaris version control IIRC). My main concern is the maintainance of the script, I guess adding the new entry points is not a problem, except one need a bit of guessing on the next release version number, and the internally exported symbols should be no harder to keep aligned than before. So after thinking about this +1, yes this makes sense. A check from one of the Solaris users after this has been commited would be good too Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

There is an unfortunate cylic dependancy between the storage_backend.c file and all the storage backend implementations due to the statically declared table of drivers. This patch addresses the problem by making the table of backends dynamically registered. The storage driver will thus register each backend explicitly at its startup. The storage_backend.c file is thus now completely generic, and has no compile time dep on the individual drivers. I should have written it this way in the first place :-) storage_backend.c | 44 +++++++++++--------------------------------- storage_backend.h | 1 + storage_driver.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 33 deletions(-) Daniel diff -r d70577bacf78 src/storage_backend.c --- a/src/storage_backend.c Wed Oct 29 17:51:07 2008 +0000 +++ b/src/storage_backend.c Wed Oct 29 18:01:58 2008 +0000 @@ -47,49 +47,27 @@ #include "storage_backend.h" -#if WITH_STORAGE_LVM -#include "storage_backend_logical.h" -#endif -#if WITH_STORAGE_ISCSI -#include "storage_backend_iscsi.h" -#endif -#if WITH_STORAGE_DISK -#include "storage_backend_disk.h" -#endif -#if WITH_STORAGE_DIR -#include "storage_backend_fs.h" -#endif - VIR_ENUM_IMPL(virStorageBackendPartTable, VIR_STORAGE_POOL_DISK_LAST, "unknown", "dos", "dvh", "gpt", "mac", "bsd", "pc98", "sun", "lvm2"); -static virStorageBackendPtr backends[] = { -#if WITH_STORAGE_DIR - &virStorageBackendDirectory, -#endif -#if WITH_STORAGE_FS - &virStorageBackendFileSystem, - &virStorageBackendNetFileSystem, -#endif -#if WITH_STORAGE_LVM - &virStorageBackendLogical, -#endif -#if WITH_STORAGE_ISCSI - &virStorageBackendISCSI, -#endif -#if WITH_STORAGE_DISK - &virStorageBackendDisk, -#endif - NULL -}; +static unsigned nbackends = 0; +static virStorageBackendPtr *backends = NULL; + +int virStorageBackendRegister(virStorageBackendPtr bk) { + if (VIR_REALLOC_N(backends, nbackends+1) < 0) + return -1; + + backends[nbackends++] = bk; + return 0; +} virStorageBackendPtr virStorageBackendForType(int type) { unsigned int i; - for (i = 0; backends[i]; i++) + for (i = 0; i < nbackends; i++) if (backends[i]->type == type) return backends[i]; diff -r d70577bacf78 src/storage_backend.h --- a/src/storage_backend.h Wed Oct 29 17:51:07 2008 +0000 +++ b/src/storage_backend.h Wed Oct 29 18:01:58 2008 +0000 @@ -120,6 +120,7 @@ int volType; }; +int virStorageBackendRegister(virStorageBackendPtr bk); virStorageBackendPtr virStorageBackendForType(int type); virStorageBackendPoolOptionsPtr virStorageBackendPoolOptionsForType(int type); diff -r d70577bacf78 src/storage_driver.c --- a/src/storage_driver.c Wed Oct 29 17:51:07 2008 +0000 +++ b/src/storage_driver.c Wed Oct 29 18:01:58 2008 +0000 @@ -40,6 +40,20 @@ #include "storage_conf.h" #include "memory.h" #include "storage_backend.h" + + +#if WITH_STORAGE_LVM +#include "storage_backend_logical.h" +#endif +#if WITH_STORAGE_ISCSI +#include "storage_backend_iscsi.h" +#endif +#if WITH_STORAGE_DISK +#include "storage_backend_disk.h" +#endif +#if WITH_STORAGE_DIR +#include "storage_backend_fs.h" +#endif #define storageLog(msg...) fprintf(stderr, msg) @@ -96,6 +110,29 @@ struct passwd *pw; char *base = NULL; char driverConf[PATH_MAX]; + +#if WITH_STORAGE_DIR + if (virStorageBackendRegister(&virStorageBackendDirectory) < 0) + return -1; +#endif +#if WITH_STORAGE_FS + if (virStorageBackendRegister(&virStorageBackendFileSystem) < 0) + return -1; + if (virStorageBackendRegister(&virStorageBackendNetFileSystem) < 0) + return -1; +#endif +#if WITH_STORAGE_LVM + if (virStorageBackendRegister(&virStorageBackendLogical) < 0) + return -1; +#endif +#if WITH_STORAGE_ISCSI + if (virStorageBackendRegister(&virStorageBackendISCSI) < 0) + return -1; +#endif +#if WITH_STORAGE_DISK + if (virStorageBackendRegister(&virStorageBackendDisk) < 0) + return -1; +#endif if (VIR_ALLOC(driverState) < 0) return -1; -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:41:45PM +0000, Daniel P. Berrange wrote:
There is an unfortunate cylic dependancy between the storage_backend.c file and all the storage backend implementations due to the statically declared table of drivers. This patch addresses the problem by making the table of backends dynamically registered. The storage driver will thus register each backend explicitly at its startup. The storage_backend.c file is thus now completely generic, and has no compile time dep on the individual drivers. I should have written it this way in the first place :-)
Yup, sounds right and looks good, +1 Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patches changes the way some of the drivers are built. Specifically the stateful drivers (QEMU, LXC, Network and Storage) are no longer compiled into libvirt.so Instead they are linked directly to the libvirt binary. They could only ever be executed as part of the daemon, and we had code checks to ensure this, so this just makes it sane at build time. More importantly this is required for David Lively's host device support. That support uses HAL, which uses DBus, which is GPL/AFL licensed. As such we cannot ever link HAL/DBus against libvirt.so without loosing our LGPL status. With this patch, HAL/DBus bits will only ever be linked into the libvirtd daemon binary, so there is no LGPL compat problems in libvirt.so The changes this patch does are fairly simple - qemud/Makefile.am - add the libtool convenience libraries for qemu, lxc, storage and network drivers to libvirtd - src/Makefile.am - remove the libtool convenience libraries for qemu, lxc, storage & network drivers from libvirt.la - src/libvirt.c: Do not invoke the register methods for qemu, lxc, storage or network drivers in virInitialize() - qemud/qemud.c: Invoke the register methods for qemu, lxc, storage and network drivers after first calling virInitialize() - libvirt_sym.version.in: add all the internal symbols needed to be exported for qemu, lxc, storage & network drivers The end result here is functionally identical to before, with one annoying exception. If you passed a 'NULL' uri to virConnectOpen it would manually probe each driver to find a suitable URI. Since QEMU, LXC drivers are not in libvirt.so anymore this probing ceases to work. I've not figured out best way to deal with this yet. One option is to not actually move the drivers out of libvirt.so at all. Just do it for the forthcoming node devices driver. ANother option is to just have a tiny QEMU/LXC stub driver in libvirt.so solely containing the probe() code. A further option is to make the remote driver implement the probe() method, so it actally talks to libvirtd and asks that for a probed URI. qemud/Makefile.am | 20 +++++ qemud/qemud.c | 29 +++++++ src/Makefile.am | 13 ++- src/libvirt.c | 22 ----- src/libvirt_sym.version.in | 168 +++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 4 - 6 files changed, 227 insertions(+), 29 deletions(-) Daniel diff -r f19d084a0d4f qemud/Makefile.am --- a/qemud/Makefile.am Thu Oct 30 10:46:21 2008 +0000 +++ b/qemud/Makefile.am Thu Oct 30 11:04:27 2008 +0000 @@ -88,7 +88,25 @@ $(POLKIT_LIBS) libvirtd_DEPENDENCIES = ../src/libvirt.la -libvirtd_LDADD = ../src/libvirt.la ../gnulib/lib/libgnu.la +libvirtd_LDADD = \ + ../gnulib/lib/libgnu.la \ + ../src/libvirt.la + +if WITH_QEMU +libvirtd_LDADD += ../src/libvirt_driver_qemu.la +endif + +if WITH_LXC +libvirtd_LDADD += ../src/libvirt_driver_lxc.la +endif + +if WITH_STORAGE_DIR +libvirtd_LDADD += ../src/libvirt_driver_storage.la +endif + +if WITH_NETWORK +libvirtd_LDADD += ../src/libvirt_driver_network.la +endif if HAVE_POLKIT policydir = $(datadir)/PolicyKit/policy diff -r f19d084a0d4f qemud/qemud.c --- a/qemud/qemud.c Thu Oct 30 10:46:21 2008 +0000 +++ b/qemud/qemud.c Thu Oct 30 11:04:27 2008 +0000 @@ -60,6 +60,20 @@ #ifdef HAVE_AVAHI #include "mdns.h" #endif + +#ifdef WITH_QEMU +#include "qemu_driver.h" +#endif +#ifdef WITH_LXC +#include "lxc_driver.h" +#endif +#ifdef WITH_NETWORK +#include "network_driver.h" +#endif +#ifdef WITH_STORAGE_DIR +#include "storage_driver.h" +#endif + static int godaemon = 0; /* -d: Be a daemon */ static int verbose = 0; /* -v: Verbose mode */ @@ -727,6 +741,21 @@ } server->sigread = sigread; + + virInitialize(); + +#ifdef WITH_QEMU + qemudRegister(); +#endif +#ifdef WITH_LXC + lxcRegister(); +#endif +#ifdef WITH_NETWORK + networkRegister(); +#endif +#ifdef WITH_STORAGE_DIR + storageRegister(); +#endif virEventRegisterImpl(virEventAddHandleImpl, virEventUpdateHandleImpl, diff -r f19d084a0d4f src/Makefile.am --- a/src/Makefile.am Thu Oct 30 10:46:21 2008 +0000 +++ b/src/Makefile.am Thu Oct 30 11:04:27 2008 +0000 @@ -195,7 +195,8 @@ if WITH_QEMU noinst_LTLIBRARIES += libvirt_driver_qemu.la -libvirt_la_LIBADD += libvirt_driver_qemu.la +# Stateful, so linked to daemon instead +#libvirt_la_LIBADD += libvirt_driver_qemu.la libvirt_driver_qemu_la_CFLAGS = $(NUMACTL_CFLAGS) libvirt_driver_qemu_la_LDFLAGS = $(NUMACTL_LIBS) libvirt_driver_qemu_la_SOURCES = $(QEMU_DRIVER_SOURCES) @@ -203,14 +204,16 @@ if WITH_LXC noinst_LTLIBRARIES += libvirt_driver_lxc.la -libvirt_la_LIBADD += libvirt_driver_lxc.la +# Stateful, so linked to daemon instead +#libvirt_la_LIBADD += libvirt_driver_lxc.la libvirt_driver_lxc_la_SOURCES = $(LXC_DRIVER_SOURCES) endif if WITH_NETWORK noinst_LTLIBRARIES += libvirt_driver_network.la -libvirt_la_LIBADD += libvirt_driver_network.la +# Stateful, so linked to daemon instead +#libvirt_la_LIBADD += libvirt_driver_network.la libvirt_driver_network_la_SOURCES = $(NETWORK_DRIVER_SOURCES) endif @@ -218,7 +221,8 @@ libvirt_driver_storage_la_SOURCES = if WITH_STORAGE_DIR noinst_LTLIBRARIES += libvirt_driver_storage.la -libvirt_la_LIBADD += libvirt_driver_storage.la +# Stateful, so linked to daemon instead +#libvirt_la_LIBADD += libvirt_driver_storage.la libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SOURCES) libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif @@ -260,6 +264,7 @@ $(COVERAGE_CFLAGS:-f%=-Wc,-f%) \ @CYGWIN_EXTRA_LDFLAGS@ @MINGW_EXTRA_LDFLAGS@ libvirt_la_CFLAGS = $(COVERAGE_CFLAGS) -DIN_LIBVIRT +libvirt_la_DEPENDENCIES = $(libvirt_la_LIBADD) $(srcdir)/libvirt_sym.version # Create an automake "convenience library" version of libvirt_la, # just for testing, since the test harness requires access to internal diff -r f19d084a0d4f src/libvirt.c --- a/src/libvirt.c Thu Oct 30 10:46:21 2008 +0000 +++ b/src/libvirt.c Thu Oct 30 11:04:27 2008 +0000 @@ -49,18 +49,8 @@ #ifdef WITH_REMOTE #include "remote_internal.h" #endif -#ifdef WITH_QEMU -#include "qemu_driver.h" -#endif #ifdef WITH_OPENVZ #include "openvz_driver.h" -#endif -#ifdef WITH_LXC -#include "lxc_driver.h" -#endif -#include "storage_driver.h" -#ifdef WITH_NETWORK -#include "network_driver.h" #endif /* @@ -289,20 +279,8 @@ #ifdef WITH_XEN if (xenUnifiedRegister () == -1) return -1; #endif -#ifdef WITH_QEMU - if (qemudRegister() == -1) return -1; -#endif #ifdef WITH_OPENVZ if (openvzRegister() == -1) return -1; -#endif -#ifdef WITH_LXC - if (lxcRegister() == -1) return -1; -#endif -#ifdef WITH_NETWORK - if (networkRegister() == -1) return -1; -#endif -#ifdef WITH_STORAGE_DIR - if (storageRegister() == -1) return -1; #endif #ifdef WITH_REMOTE if (remoteRegister () == -1) return -1; diff -r f19d084a0d4f src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in Thu Oct 30 10:46:21 2008 +0000 +++ b/src/libvirt_sym.version.in Thu Oct 30 11:04:27 2008 +0000 @@ -257,6 +257,19 @@ LIBVIRT_PRIVATE_@VERSION@ { global: + /* bridge.h */ + brAddBridge; + brAddInterface; + brAddTap; + brDeleteBridge; + brInit; + brSetEnableSTP; + brSetForwardDelay; + brSetInetAddress; + brSetInetNetmask; + brSetInterfaceUp; + brShutdown; + /* buf.h */ virBufferVSprintf; @@ -264,6 +277,18 @@ virBufferAddChar; virBufferContentAndReset; virBufferError; + + + /* caps.h */ + virCapabilitiesAddGuest; + virCapabilitiesAddGuestDomain; + virCapabilitiesAddGuestFeature; + virCapabilitiesAddHostNUMACell; + virCapabilitiesDefaultGuestEmulator; + virCapabilitiesFormatXML; + virCapabilitiesFree; + virCapabilitiesNew; + virCapabilitiesSetMacPrefix; /* conf.h */ @@ -284,7 +309,62 @@ virGetStorageVol; + /* domain_conf.h */ + virDiskNameToBusDeviceIndex; + virDiskNameToIndex; + virDomainAssignDef; + virDomainConfigFile; + virDomainDefDefaultEmulator; + virDomainDefFormat; + virDomainDefFree; + virDomainDefParseFile; + virDomainDefParseString; + virDomainDeleteConfig; + virDomainDeviceDefParse; + virDomainDiskBusTypeToString; + virDomainDiskDeviceTypeToString; + virDomainDiskQSort; + virDomainEventCallbackListAdd; + virDomainEventCallbackListFree; + virDomainEventCallbackListRemove; + virDomainFindByID; + virDomainFindByName; + virDomainFindByUUID; + virDomainLoadAllConfigs; + virDomainObjListFree; + virDomainRemoveInactive; + virDomainSaveConfig; + virDomainSoundModelTypeToString; + virDomainVirtTypeToString; + + + /* iptables.h */ + iptablesAddForwardAllowCross; + iptablesAddForwardAllowIn; + iptablesAddForwardAllowOut; + iptablesAddForwardAllowRelatedIn; + iptablesAddForwardMasquerade; + iptablesAddForwardRejectIn; + iptablesAddForwardRejectOut; + iptablesAddTcpInput; + iptablesAddUdpInput; + iptablesContextFree; + iptablesContextNew; + iptablesReloadRules; + iptablesRemoveForwardAllowCross; + iptablesRemoveForwardAllowIn; + iptablesRemoveForwardAllowOut; + iptablesRemoveForwardAllowRelatedIn; + iptablesRemoveForwardMasquerade; + iptablesRemoveForwardRejectIn; + iptablesRemoveForwardRejectOut; + iptablesRemoveTcpInput; + iptablesRemoveUdpInput; + iptablesSaveRules; + + /* libvirt_internal.h */ + debugFlag; virStateInitialize; virStateCleanup; virStateReload; @@ -294,6 +374,10 @@ virDomainMigratePrepare; virDomainMigratePerform; virDomainMigrateFinish; + virRegisterDriver; + virRegisterNetworkDriver; + virRegisterStateDriver; + virRegisterStorageDriver; /* memory.h */ @@ -303,13 +387,97 @@ virFree; + /* network_conf.h */ + virNetworkAssignDef; + virNetworkDefFormat; + virNetworkDefFree; + virNetworkDefParseString; + virNetworkDeleteConfig; + virNetworkFindByName; + virNetworkFindByUUID; + virNetworkLoadAllConfigs; + virNetworkObjListFree; + virNetworkRemoveInactive; + virNetworkSaveConfig; + + + /* nodeinfo.h */ + virNodeInfoPopulate; + + + /* stats_linux.h */ + linuxDomainInterfaceStats; + + + /* storage_backend.h */ + virStorageBackendForType; + virStorageBackendFromString; + virStorageBackendPartTableTypeFromString; + virStorageBackendPartTableTypeToString; + virStorageBackendRegister; + virStorageBackendRunProgNul; + virStorageBackendRunProgRegex; + virStorageBackendStablePath; + virStorageBackendUpdateVolInfo; + virStorageBackendUpdateVolInfoFD; + + + /* storage_conf.h */ + virStoragePoolDefFormat; + virStoragePoolDefFree; + virStoragePoolDefParse; + virStoragePoolLoadAllConfigs; + virStoragePoolObjAssignDef; + virStoragePoolObjClearVols; + virStoragePoolObjDeleteDef; + virStoragePoolObjFindByName; + virStoragePoolObjFindByUUID; + virStoragePoolObjListFree; + virStoragePoolObjRemove; + virStoragePoolObjSaveDef; + virStoragePoolSourceFree; + virStoragePoolSourceListFormat; + virStorageVolDefFindByKey; + virStorageVolDefFindByName; + virStorageVolDefFindByPath; + virStorageVolDefFormat; + virStorageVolDefFree; + virStorageVolDefParse; + + /* util.h */ virFileReadAll; virStrToLong_i; + virStrToLong_ll; virStrToLong_ull; saferead; safewrite; virMacAddrCompare; + virEnumFromString; + virEnumToString; + virEventAddHandle; + virEventRemoveHandle; + virExec; + virFileDeletePid; + virFileExists; + virFileHasSuffix; + virFileMakePath; + virFileOpenTty; + virFileReadLimFD; + virFileReadPid; + virRun; + + + /* uuid.h */ + virUUIDFormat; + + + /* virterror_internal.h */ + virReportErrorHelper; + + + /* xml.h */ + virXPathString; /* Finally everything else is totally private */ diff -r f19d084a0d4f tests/Makefile.am --- a/tests/Makefile.am Thu Oct 30 10:46:21 2008 +0000 +++ b/tests/Makefile.am Thu Oct 30 11:04:27 2008 +0000 @@ -107,12 +107,12 @@ qemuxml2argvtest_SOURCES = \ qemuxml2argvtest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h -qemuxml2argvtest_LDADD = $(LDADDS) +qemuxml2argvtest_LDADD = ../src/libvirt_driver_qemu.la $(LDADDS) qemuxml2xmltest_SOURCES = \ qemuxml2xmltest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h -qemuxml2xmltest_LDADD = $(LDADDS) +qemuxml2xmltest_LDADD = ../src/libvirt_driver_qemu.la $(LDADDS) virshtest_SOURCES = \ virshtest.c \ -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:42:19PM +0000, Daniel P. Berrange wrote:
This patches changes the way some of the drivers are built. Specifically the stateful drivers (QEMU, LXC, Network and Storage) are no longer compiled into libvirt.so Instead they are linked directly to the libvirt binary. They could only ever be executed as part of the daemon, and we had code checks to ensure this, so this just makes it sane at build time.
Hum .... if you force the QEmu driver in the libvirtd daemon, hor do you implement qemu:///session ? I think I'm missing something there...
More importantly this is required for David Lively's host device support. That support uses HAL, which uses DBus, which is GPL/AFL licensed. As such we cannot ever link HAL/DBus against libvirt.so without loosing our LGPL status. With this patch, HAL/DBus bits will only ever be linked into the libvirtd daemon binary, so there is no LGPL compat problems in libvirt.so
Yup, understood and agreed. But all we need is force just the hardware discovery to be linkeable only by the daemon, not everything has to be linked that way.
The changes this patch does are fairly simple
- qemud/Makefile.am - add the libtool convenience libraries for qemu, lxc, storage and network drivers to libvirtd - src/Makefile.am - remove the libtool convenience libraries for qemu, lxc, storage & network drivers from libvirt.la - src/libvirt.c: Do not invoke the register methods for qemu, lxc, storage or network drivers in virInitialize() - qemud/qemud.c: Invoke the register methods for qemu, lxc, storage and network drivers after first calling virInitialize() - libvirt_sym.version.in: add all the internal symbols needed to be exported for qemu, lxc, storage & network drivers
The end result here is functionally identical to before, with one annoying exception. If you passed a 'NULL' uri to virConnectOpen it would manually probe each driver to find a suitable URI. Since QEMU, LXC drivers are not in libvirt.so anymore this probing ceases to work.
Hum, we should find a way to have the do_open(NULL) probe done into the server located on localhost. Maybe this means adding an extra remote operation querying the node for a default hypervisor. LIBVIRT_DEFAULT_URI is still being checked in the library code, so that default behaviour can still be overriden by the user if this leads to picking the wrong driver.
I've not figured out best way to deal with this yet. One option is to not actually move the drivers out of libvirt.so at all. Just do it for the forthcoming node devices driver. ANother option is to just have a tiny QEMU/LXC stub driver in libvirt.so solely containing the probe() code. A further option is to make the remote driver implement the probe() method, so it actally talks to libvirtd and asks that for a probed URI.
IMHO the 3rd solution is the one making most sense from an architecture POV. Maybe we can even get this to work for remote and be able to ask a remote node if it supports Xen or KVM by default (or something else ...)
--- a/src/libvirt_sym.version.in Thu Oct 30 10:46:21 2008 +0000 +++ b/src/libvirt_sym.version.in Thu Oct 30 11:04:27 2008 +0000 @@ -257,6 +257,19 @@ LIBVIRT_PRIVATE_@VERSION@ {
global: + /* bridge.h */ + brAddBridge; + brAddInterface; + brAddTap; + brDeleteBridge; + brInit; + brSetEnableSTP; + brSetForwardDelay; + brSetInetAddress; + brSetInetNetmask; + brSetInterfaceUp; + brShutdown; +
/* buf.h */ virBufferVSprintf; @@ -264,6 +277,18 @@ virBufferAddChar; virBufferContentAndReset; virBufferError; + + + /* caps.h */ + virCapabilitiesAddGuest; + virCapabilitiesAddGuestDomain; + virCapabilitiesAddGuestFeature; + virCapabilitiesAddHostNUMACell; + virCapabilitiesDefaultGuestEmulator; + virCapabilitiesFormatXML; + virCapabilitiesFree; + virCapabilitiesNew; + virCapabilitiesSetMacPrefix;
/* conf.h */ @@ -284,7 +309,62 @@ virGetStorageVol;
+ /* domain_conf.h */ + virDiskNameToBusDeviceIndex; + virDiskNameToIndex; + virDomainAssignDef; + virDomainConfigFile; + virDomainDefDefaultEmulator; + virDomainDefFormat; + virDomainDefFree; + virDomainDefParseFile; + virDomainDefParseString; + virDomainDeleteConfig; + virDomainDeviceDefParse; + virDomainDiskBusTypeToString; + virDomainDiskDeviceTypeToString; + virDomainDiskQSort; + virDomainEventCallbackListAdd; + virDomainEventCallbackListFree; + virDomainEventCallbackListRemove; + virDomainFindByID; + virDomainFindByName; + virDomainFindByUUID; + virDomainLoadAllConfigs; + virDomainObjListFree; + virDomainRemoveInactive; + virDomainSaveConfig; + virDomainSoundModelTypeToString; + virDomainVirtTypeToString; + + + /* iptables.h */ + iptablesAddForwardAllowCross; + iptablesAddForwardAllowIn; + iptablesAddForwardAllowOut; + iptablesAddForwardAllowRelatedIn; + iptablesAddForwardMasquerade; + iptablesAddForwardRejectIn; + iptablesAddForwardRejectOut; + iptablesAddTcpInput; + iptablesAddUdpInput; + iptablesContextFree; + iptablesContextNew; + iptablesReloadRules; + iptablesRemoveForwardAllowCross; + iptablesRemoveForwardAllowIn; + iptablesRemoveForwardAllowOut; + iptablesRemoveForwardAllowRelatedIn; + iptablesRemoveForwardMasquerade; + iptablesRemoveForwardRejectIn; + iptablesRemoveForwardRejectOut; + iptablesRemoveTcpInput; + iptablesRemoveUdpInput; + iptablesSaveRules; + + /* libvirt_internal.h */ + debugFlag; virStateInitialize; virStateCleanup; virStateReload; @@ -294,6 +374,10 @@ virDomainMigratePrepare; virDomainMigratePerform; virDomainMigrateFinish; + virRegisterDriver; + virRegisterNetworkDriver; + virRegisterStateDriver; + virRegisterStorageDriver;
/* memory.h */ @@ -303,13 +387,97 @@ virFree;
+ /* network_conf.h */ + virNetworkAssignDef; + virNetworkDefFormat; + virNetworkDefFree; + virNetworkDefParseString; + virNetworkDeleteConfig; + virNetworkFindByName; + virNetworkFindByUUID; + virNetworkLoadAllConfigs; + virNetworkObjListFree; + virNetworkRemoveInactive; + virNetworkSaveConfig; + + + /* nodeinfo.h */ + virNodeInfoPopulate; + + + /* stats_linux.h */ + linuxDomainInterfaceStats; + + + /* storage_backend.h */ + virStorageBackendForType; + virStorageBackendFromString; + virStorageBackendPartTableTypeFromString; + virStorageBackendPartTableTypeToString; + virStorageBackendRegister; + virStorageBackendRunProgNul; + virStorageBackendRunProgRegex; + virStorageBackendStablePath; + virStorageBackendUpdateVolInfo; + virStorageBackendUpdateVolInfoFD; + + + /* storage_conf.h */ + virStoragePoolDefFormat; + virStoragePoolDefFree; + virStoragePoolDefParse; + virStoragePoolLoadAllConfigs; + virStoragePoolObjAssignDef; + virStoragePoolObjClearVols; + virStoragePoolObjDeleteDef; + virStoragePoolObjFindByName; + virStoragePoolObjFindByUUID; + virStoragePoolObjListFree; + virStoragePoolObjRemove; + virStoragePoolObjSaveDef; + virStoragePoolSourceFree; + virStoragePoolSourceListFormat; + virStorageVolDefFindByKey; + virStorageVolDefFindByName; + virStorageVolDefFindByPath; + virStorageVolDefFormat; + virStorageVolDefFree; + virStorageVolDefParse; + + /* util.h */ virFileReadAll; virStrToLong_i; + virStrToLong_ll; virStrToLong_ull; saferead; safewrite; virMacAddrCompare; + virEnumFromString; + virEnumToString; + virEventAddHandle; + virEventRemoveHandle; + virExec; + virFileDeletePid; + virFileExists; + virFileHasSuffix; + virFileMakePath; + virFileOpenTty; + virFileReadLimFD; + virFileReadPid; + virRun; + + + /* uuid.h */ + virUUIDFormat; + + + /* virterror_internal.h */ + virReportErrorHelper; + + + /* xml.h */ + virXPathString;
/* Finally everything else is totally private */
So how many internal APIs do we end up with ? just curious ... That's the only patch in the serie so far where I am a bit worried of real regression for the users, unfortunately it's really needed for the discovery patches ... I'm still very surprized that the freedesktop guys really pushed a library like HAL as GPL instead of LGPL. I understand that the database code be under GPL, but the accessor libs really should be LGPL, that's weird. I'm fine pushing everything to CVS now, others may chime in of course :-), but maybe this patch and the following need a few more days of thinking and maybe try to avoid this NULL open problem. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This patch adds full support for dlopen()'ing of individual drivers. - configure.in gains a new command line flag --with-driver-modules. It defaults to off, producing a monolithic build. If enabled, it checks dlopen() in -ldl and dlfcn.h - src/Makefile.am if the WITH_DRIVER_MODULES conditional is defined, then instead of building each driver as a libtool convenience library and linking them into libvirt.la , they are instead build as libtool modules, and installed to $PREFIX/lib/libvirt/drivers/ - qemud/Makefile.am if the WITH_DRIVER_MODULES conditional is defined then don't link to the libtool convenience library for qemu/lxc/etc - libvirt_sym.version.in: Since we're loading drivers at runtime, we need to export more of our internal symbols. We'd already exported the vast majority in the previous patch to enable libvirtd to link to lxc, qemu, storage & network drivers. This just adds the few more used by the xen, remote & test drivers. - Renames qemudRegister() to qemuRegister() and xenUnifiedRegister() to just xenRegister(), so the prefix matches the module name - driver.c adds a virDriverLoadModule() method which given a module name like 'qemu', loads a file libvirt_driver_$NAME.so and runs the symbols ${NAME}Register(). It looks in $PREFIX/lib/libvirt/drivers/ by default, but can be override with LIBVIRT_DRIVER_DIR env variable eg, point it to $SOURCETREE/src/.libs to run against a non-installed libvirt build. - libvirt.c/qemud.c, if WITH_DRIVER_MODULES is defined, then instead of calling the XXXRegister() methods directly, call virDriverLoadModule() for each module So, as an example, having built with --enable-driver-modules, you can run the daemon directly from source tree with # LIBVIRT_DRIVER_DIR=`pwd`/src/.libs LIBVIRT_DEBUG=1 ./qemud/libvirtd DEBUG: libvirt.c: virInitialize (register drivers) DEBUG: libvirt.c: virRegisterDriver (registering Test as driver 0) DEBUG: libvirt.c: virRegisterNetworkDriver (registering Test as network driver 0) DEBUG: libvirt.c: virRegisterStorageDriver (registering Test as storage driver 0) DEBUG: libvirt.c: virRegisterDriver (registering Xen as driver 1) DEBUG: libvirt.c: virRegisterDriver (registering OPENVZ as driver 2) DEBUG: libvirt.c: virRegisterDriver (registering remote as driver 3) DEBUG: libvirt.c: virRegisterNetworkDriver (registering remote as network driver 1) DEBUG: libvirt.c: virRegisterStorageDriver (registering remote as storage driver 1) DEBUG: libvirt.c: virRegisterDriver (registering QEMU as driver 4) DEBUG: libvirt.c: virRegisterDriver (registering LXC as driver 5) DEBUG: libvirt.c: virRegisterNetworkDriver (registering Network as network driver 2) DEBUG: libvirt.c: virRegisterStorageDriver (registering storage as storage driver 2) And run virsh directly from source tree with $ LIBVIRT_DEBUG=1 LIBVIRT_DRIVER_DIR=`pwd`/.libs ./virsh --readonly --connect qemu:///system DEBUG: libvirt.c: virInitialize (register drivers) DEBUG: libvirt.c: virRegisterDriver (registering Test as driver 0) DEBUG: libvirt.c: virRegisterNetworkDriver (registering Test as network driver 0) DEBUG: libvirt.c: virRegisterStorageDriver (registering Test as storage driver 0) DEBUG: libvirt.c: virRegisterDriver (registering Xen as driver 1) DEBUG: libvirt.c: virRegisterDriver (registering OPENVZ as driver 2) DEBUG: libvirt.c: virRegisterDriver (registering remote as driver 3) DEBUG: libvirt.c: virRegisterNetworkDriver (registering remote as network driver 1) DEBUG: libvirt.c: virRegisterStorageDriver (registering remote as storage driver 1) DEBUG: libvirt.c: virConnectOpenAuth (name=qemu:///system, auth=0x3945e0, flags=1) DEBUG: libvirt.c: do_open (name "qemu:///system" to URI components: scheme qemu opaque (null) authority (null) server (null) user (null) port 0 path /system ) DEBUG: libvirt.c: do_open (trying driver 0 (Test) ...) DEBUG: libvirt.c: do_open (driver 0 Test returned DECLINED) DEBUG: libvirt.c: do_open (trying driver 1 (Xen) ...) DEBUG: libvirt.c: do_open (driver 1 Xen returned DECLINED) DEBUG: libvirt.c: do_open (trying driver 2 (OPENVZ) ...) DEBUG: libvirt.c: do_open (driver 2 OPENVZ returned DECLINED) DEBUG: libvirt.c: do_open (trying driver 3 (remote) ...) DEBUG: remote_internal.c: doRemoteOpen (proceeding with name = qemu:///system) DEBUG: remote_internal.c: doRemoteOpen (Adding Handler for remote events) DEBUG: remote_internal.c: doRemoteOpen (virEventAddHandle failed: No addHandleImpl defined. continuing without events.) DEBUG: libvirt.c: do_open (driver 3 remote returned SUCCESS) DEBUG: libvirt.c: do_open (network driver 0 Test returned DECLINED) DEBUG: libvirt.c: do_open (network driver 1 remote returned SUCCESS) DEBUG: libvirt.c: do_open (storage driver 0 Test returned DECLINED) DEBUG: libvirt.c: do_open (storage driver 1 remote returned SUCCESS) Welcome to lt-virsh, the virtualization interactive terminal. Type: 'help' for help with commands 'quit' to quit virsh > That said, if you commonly run stuff directly from the source tree, you're better off not building with modules, so you don't need to remember to set the module path. b/src/driver.c | 87 +++++++++++++++++++++++++++++++++++++++++++++ configure.in | 40 ++++++++++++++++++++ qemud/Makefile.am | 2 + qemud/qemud.c | 18 ++++++++- src/Makefile.am | 65 ++++++++++++++++++++++++++++++++- src/driver.h | 2 + src/libvirt.c | 22 ++++++++++- src/libvirt_sym.version.in | 74 +++++++++++++++++++++++++++++++++++++- src/qemu_driver.c | 2 - src/qemu_driver.h | 2 - src/xen_unified.c | 4 +- src/xen_unified.h | 2 - tests/Makefile.am | 8 ++-- 13 files changed, 314 insertions(+), 14 deletions(-) Daniel diff -r 3af981530f52 configure.in --- a/configure.in Thu Oct 30 11:04:28 2008 +0000 +++ b/configure.in Thu Oct 30 12:09:07 2008 +0000 @@ -1055,6 +1055,38 @@ AC_CHECK_TOOL([WINDRES], [windres], [no]) AM_CONDITIONAL([WITH_WIN_ICON], [test "$WINDRES" != "no"]) + + +dnl Driver-Modules library +AC_ARG_WITH([driver-modules], + [ --with-driver-modules build drivers as loadable modules], + [], + [with_driver_modules=no]) + +DRIVER_MODULES_CFLAGS= +DRIVER_MODULES_LIBS= +if test "x$with_driver_modules" = "xyes" ; then + old_cflags="$CFLAGS" + old_libs="$LIBS" + fail=0 + AC_CHECK_HEADER([dlfcn.h],[],[fail=1]) + AC_CHECK_LIB([dl], [dlopen],[],[fail=1]) + test $fail = 1 && + AC_MSG_ERROR([You must have dlfcn.h / dlopen() support to build driver modules]) + + CFLAGS="$old_cflags" + LIBS="$old_libs" +fi +if test "$with_driver_modules" = "yes"; then + DRIVER_MODULES_CFLAGS="-export-dynamic" + DRIVER_MODULES_LIBS="-ldl" + AC_DEFINE_UNQUOTED([WITH_DRIVER_MODULES], 1, [whether to build drivers as modules]) +fi +AM_CONDITIONAL([WITH_DRIVER_MODULES], [test "$with_driver_modules" != "no"]) +AC_SUBST([DRIVER_MODULES_CFLAGS]) +AC_SUBST([DRIVER_MODULES_LIBS]) + + # Set LV_LIBTOOL_OBJDIR to "." or $lt_cv_objdir, depending on whether # we're building shared libraries. This is the name of the directory # in which .o files will be created. @@ -1110,6 +1142,14 @@ AC_MSG_NOTICE([ iSCSI: $with_storage_iscsi]) AC_MSG_NOTICE([ Disk: $with_storage_disk]) AC_MSG_NOTICE([]) +AC_MSG_NOTICE([Driver Loadable Modules]) +AC_MSG_NOTICE([]) +if test "$with_driver_modules" != "no" ; then +AC_MSG_NOTICE([ dlopen: $DRIVER_MODULES_CFLAGS $DRIVER_MODULES_LIBS]) +else +AC_MSG_NOTICE([ dlopen: no]) +fi +AC_MSG_NOTICE([]) AC_MSG_NOTICE([Libraries]) AC_MSG_NOTICE([]) AC_MSG_NOTICE([ libxml: $LIBXML_CFLAGS $LIBXML_LIBS]) diff -r 3af981530f52 qemud/Makefile.am --- a/qemud/Makefile.am Thu Oct 30 11:04:28 2008 +0000 +++ b/qemud/Makefile.am Thu Oct 30 12:09:07 2008 +0000 @@ -92,6 +92,7 @@ ../gnulib/lib/libgnu.la \ ../src/libvirt.la +if ! WITH_DRIVER_MODULES if WITH_QEMU libvirtd_LDADD += ../src/libvirt_driver_qemu.la endif @@ -106,6 +107,7 @@ if WITH_NETWORK libvirtd_LDADD += ../src/libvirt_driver_network.la +endif endif if HAVE_POLKIT diff -r 3af981530f52 qemud/qemud.c --- a/qemud/qemud.c Thu Oct 30 11:04:28 2008 +0000 +++ b/qemud/qemud.c Thu Oct 30 12:09:07 2008 +0000 @@ -61,6 +61,9 @@ #include "mdns.h" #endif +#ifdef WITH_DRIVER_MODULES +#include "driver.h" +#else #ifdef WITH_QEMU #include "qemu_driver.h" #endif @@ -72,6 +75,7 @@ #endif #ifdef WITH_STORAGE_DIR #include "storage_driver.h" +#endif #endif @@ -744,8 +748,19 @@ virInitialize(); +#ifdef WITH_DRIVER_MODULES + /* We don't care if any of these fail, because the whole point + * is to allow users to only install modules they want to use. + * If they try to use a open a connection for a module that + * is not loaded they'll get a suitable error at that point + */ + virDriverLoadModule("qemu"); + virDriverLoadModule("lxc"); + virDriverLoadModule("network"); + virDriverLoadModule("storage"); +#else #ifdef WITH_QEMU - qemudRegister(); + qemuRegister(); #endif #ifdef WITH_LXC lxcRegister(); @@ -755,6 +770,7 @@ #endif #ifdef WITH_STORAGE_DIR storageRegister(); +#endif #endif virEventRegisterImpl(virEventAddHandleImpl, diff -r 3af981530f52 src/Makefile.am --- a/src/Makefile.am Thu Oct 30 11:04:28 2008 +0000 +++ b/src/Makefile.am Thu Oct 30 12:09:07 2008 +0000 @@ -6,7 +6,10 @@ -I@top_srcdir@/include \ -I@top_srcdir@/qemud \ $(LIBXML_CFLAGS) \ + $(XEN_CFLAGS) \ $(SELINUX_CFLAGS) \ + $(DRIVER_MODULE_CFLAGS) \ + -DLIBDIR=\""$(libdir)"\" \ -DBINDIR=\""$(libexecdir)"\" \ -DSBINDIR=\""$(sbindir)"\" \ -DSYSCONF_DIR="\"$(sysconfdir)\"" \ @@ -30,6 +33,10 @@ lib_LTLIBRARIES = libvirt.la +moddir = $(libdir)/libvirt/drivers +mod_LTLIBRARIES = + + # These files are not related to driver APIs. Simply generic # helper APIs for various purposes UTIL_SOURCES = \ @@ -48,7 +55,7 @@ # Internal generic driver infrastructure DRIVER_SOURCES = \ - driver.h \ + driver.c driver.h \ internal.h \ datatypes.c datatypes.h \ domain_event.c domain_event.h \ @@ -162,67 +169,120 @@ $(STORAGE_CONF_SOURCES) if WITH_TEST +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_test.la +else noinst_LTLIBRARIES += libvirt_driver_test.la libvirt_la_LIBADD += libvirt_driver_test.la +endif libvirt_driver_test_la_SOURCES = $(TEST_DRIVER_SOURCES) endif if WITH_REMOTE +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_remote.la +else noinst_LTLIBRARIES += libvirt_driver_remote.la libvirt_la_LIBADD += libvirt_driver_remote.la +endif libvirt_driver_remote_la_CFLAGS = \ $(GNUTLS_CFLAGS) \ $(SASL_CFLAGS) libvirt_driver_remote_la_LDFLAGS = \ $(GNUTLS_LIBS) \ $(SASL_LIBS) +if WITH_DRIVER_MODULES +libvirt_driver_remote_la_LDFLAGS += -module -avoid-version +endif libvirt_driver_remote_la_SOURCES = $(REMOTE_DRIVER_SOURCES) endif if WITH_XEN +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_xen.la +else noinst_LTLIBRARIES += libvirt_driver_xen.la libvirt_la_LIBADD += libvirt_driver_xen.la +endif libvirt_driver_xen_la_CFLAGS = $(XEN_CFLAGS) libvirt_driver_xen_la_LDFLAGS = $(XEN_LIBS) +if WITH_DRIVER_MODULES +libvirt_driver_xen_la_LDFLAGS += -module -avoid-version +endif libvirt_driver_xen_la_SOURCES = $(XEN_DRIVER_SOURCES) endif if WITH_OPENVZ +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_openvz.la +else noinst_LTLIBRARIES += libvirt_driver_openvz.la libvirt_la_LIBADD += libvirt_driver_openvz.la +endif +if WITH_DRIVER_MODULES +libvirt_driver_openvz_la_LDFLAGS = -module -avoid-version +endif libvirt_driver_openvz_la_SOURCES = $(OPENVZ_DRIVER_SOURCES) endif if WITH_QEMU +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_qemu.la +else noinst_LTLIBRARIES += libvirt_driver_qemu.la # Stateful, so linked to daemon instead #libvirt_la_LIBADD += libvirt_driver_qemu.la +endif libvirt_driver_qemu_la_CFLAGS = $(NUMACTL_CFLAGS) libvirt_driver_qemu_la_LDFLAGS = $(NUMACTL_LIBS) +if WITH_DRIVER_MODULES +libvirt_driver_qemu_la_LDFLAGS += -module -avoid-version +endif libvirt_driver_qemu_la_SOURCES = $(QEMU_DRIVER_SOURCES) endif if WITH_LXC +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_lxc.la +else noinst_LTLIBRARIES += libvirt_driver_lxc.la # Stateful, so linked to daemon instead #libvirt_la_LIBADD += libvirt_driver_lxc.la +endif +if WITH_DRIVER_MODULES +libvirt_driver_lxc_la_LDFLAGS = -module -avoid-version +endif libvirt_driver_lxc_la_SOURCES = $(LXC_DRIVER_SOURCES) endif if WITH_NETWORK +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_network.la +else noinst_LTLIBRARIES += libvirt_driver_network.la # Stateful, so linked to daemon instead #libvirt_la_LIBADD += libvirt_driver_network.la +endif +if WITH_DRIVER_MODULES +libvirt_driver_network_la_LDFLAGS = -module -avoid-version +endif libvirt_driver_network_la_SOURCES = $(NETWORK_DRIVER_SOURCES) endif # Needed to keep automake quiet about conditionals libvirt_driver_storage_la_SOURCES = if WITH_STORAGE_DIR +if WITH_DRIVER_MODULES +mod_LTLIBRARIES += libvirt_driver_storage.la +else noinst_LTLIBRARIES += libvirt_driver_storage.la # Stateful, so linked to daemon instead #libvirt_la_LIBADD += libvirt_driver_storage.la +endif +if WITH_DRIVER_MODULES +libvirt_driver_storage_la_LDFLAGS = -module -avoid-version +endif libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_SOURCES) libvirt_driver_storage_la_SOURCES += $(STORAGE_DRIVER_FS_SOURCES) endif @@ -257,7 +317,8 @@ # Empty source list - it merely links a bunch of convenience libs together libvirt_la_SOURCES = -libvirt_la_LIBADD += $(LIBXML_LIBS) $(SELINUX_LIBS) \ +libvirt_la_LIBADD += $(LIBXML_LIBS) $(XEN_LIBS) $(SELINUX_LIBS) \ + $(DRIVER_MODULE_LIBS) \ @CYGWIN_EXTRA_LIBADD@ ../gnulib/lib/libgnu.la libvirt_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libvirt_sym.version \ -version-info @LIBVIRT_VERSION_INFO@ \ diff -r 3af981530f52 src/driver.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/driver.c Thu Oct 30 12:09:07 2008 +0000 @@ -0,0 +1,87 @@ +/* + * driver.c: Helpers for loading drivers + * + * Copyright (C) 2006-2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +#include <config.h> + +#include <unistd.h> + +#include "driver.h" +#include "memory.h" + +#define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/drivers" + +#ifdef WITH_DRIVER_MODULES + +/* XXX re-implment this for other OS, or use libtools helper lib ? */ + +#include <dlfcn.h> + +void * +virDriverLoadModule(const char *name) +{ + const char *moddir = getenv("LIBVIRT_DRIVER_DIR"); + char *modfile, *regfunc; + void *handle; + int (*regsym)(void); + + if (moddir == NULL) + moddir = DEFAULT_DRIVER_DIR; + + if (asprintf(&modfile, "%s/libvirt_driver_%s.so", moddir, name) < 0) + return NULL; + + if (access(modfile, R_OK) < 0) { + VIR_FREE(modfile); + return NULL; + } + + handle = dlopen(modfile, RTLD_NOW | RTLD_LOCAL); + VIR_FREE(modfile); + if (!handle) { + fprintf(stderr, "failed to load module %s\n", dlerror()); + return NULL; + } + + if (asprintf(®func, "%sRegister", name) < 0) { + dlclose(handle); + return NULL; + } + + regsym = dlsym(handle, regfunc); + VIR_FREE(regfunc); + if (!regsym) { + dlclose(handle); + return NULL; + } + + if ((*regsym)() < 0) { + dlclose(handle); + return NULL; + } + + return handle; +} + + +/* XXX unload modules, but we can't until we can unregister libvirt drivers */ + +#endif diff -r 3af981530f52 src/driver.h --- a/src/driver.h Thu Oct 30 11:04:28 2008 +0000 +++ b/src/driver.h Thu Oct 30 12:09:07 2008 +0000 @@ -8,6 +8,7 @@ #include <libxml/uri.h> +#include "internal.h" /* * List of registered drivers numbers */ @@ -618,5 +619,6 @@ #ifdef WITH_LIBVIRTD int virRegisterStateDriver(virStateDriverPtr); #endif +void *virDriverLoadModule(const char *name); #endif /* __VIR_DRIVER_H__ */ diff -r 3af981530f52 src/libvirt.c --- a/src/libvirt.c Thu Oct 30 11:04:28 2008 +0000 +++ b/src/libvirt.c Thu Oct 30 12:09:07 2008 +0000 @@ -40,6 +40,7 @@ #include "util.h" #include "memory.h" +#ifndef WITH_DRIVER_MODULES #ifdef WITH_TEST #include "test.h" #endif @@ -51,6 +52,7 @@ #endif #ifdef WITH_OPENVZ #include "openvz_driver.h" +#endif #endif /* @@ -273,11 +275,22 @@ * Note that the order is important: the first ones have a higher * priority when calling virConnectOpen. */ +#ifdef WITH_DRIVER_MODULES + /* We don't care if any of these fail, because the whole point + * is to allow users to only install modules they want to use. + * If they try to use a open a connection for a module that + * is not loaded they'll get a suitable error at that point + */ + virDriverLoadModule("test"); + virDriverLoadModule("xen"); + virDriverLoadModule("openvz"); + virDriverLoadModule("remote"); +#else #ifdef WITH_TEST if (testRegister() == -1) return -1; #endif #ifdef WITH_XEN - if (xenUnifiedRegister () == -1) return -1; + if (xenRegister () == -1) return -1; #endif #ifdef WITH_OPENVZ if (openvzRegister() == -1) return -1; @@ -285,6 +298,7 @@ #ifdef WITH_REMOTE if (remoteRegister () == -1) return -1; #endif +#endif return(0); } @@ -461,6 +475,9 @@ return(-1); } + DEBUG ("registering %s as network driver %d", + driver->name, virNetworkDriverTabCount); + virNetworkDriverTab[virNetworkDriverTabCount] = driver; return virNetworkDriverTabCount++; } @@ -488,6 +505,9 @@ virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); return(-1); } + + DEBUG ("registering %s as storage driver %d", + driver->name, virStorageDriverTabCount); virStorageDriverTab[virStorageDriverTabCount] = driver; return virStorageDriverTabCount++; diff -r 3af981530f52 src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in Thu Oct 30 11:04:28 2008 +0000 +++ b/src/libvirt_sym.version.in Thu Oct 30 12:09:07 2008 +0000 @@ -283,8 +283,12 @@ virCapabilitiesAddGuest; virCapabilitiesAddGuestDomain; virCapabilitiesAddGuestFeature; + virCapabilitiesAddHostMigrateTransport; virCapabilitiesAddHostNUMACell; + virCapabilitiesAddHostFeature; + virCapabilitiesDefaultGuestArch; virCapabilitiesDefaultGuestEmulator; + virCapabilitiesDefaultGuestMachine; virCapabilitiesFormatXML; virCapabilitiesFree; virCapabilitiesNew; @@ -296,6 +300,7 @@ virConfReadFile; virConfReadMem; virConfFree; + virConfFreeValue; virConfGetValue; virConfSetValue; virConfWriteFile; @@ -307,6 +312,7 @@ virGetNetwork; virGetStoragePool; virGetStorageVol; + virUnrefDomain; /* domain_conf.h */ @@ -314,14 +320,22 @@ virDiskNameToIndex; virDomainAssignDef; virDomainConfigFile; + virDomainCpuSetFormat; + virDomainCpuSetParse; + virDomainChrDefFree; + virDomainChrTypeFromString; + virDomainChrTypeToString; virDomainDefDefaultEmulator; virDomainDefFormat; virDomainDefFree; virDomainDefParseFile; + virDomainDefParseNode; virDomainDefParseString; virDomainDeleteConfig; + virDomainDeviceDefFree; virDomainDeviceDefParse; virDomainDiskBusTypeToString; + virDomainDiskDefFree; virDomainDiskDeviceTypeToString; virDomainDiskQSort; virDomainEventCallbackListAdd; @@ -330,12 +344,52 @@ virDomainFindByID; virDomainFindByName; virDomainFindByUUID; + virDomainGraphicsTypeFromString; + virDomainGraphicsDefFree; + virDomainInputDefFree; + virDomainLifecycleTypeFromString; + virDomainLifecycleTypeToString; virDomainLoadAllConfigs; + virDomainNetDefFree; + virDomainObjFree; virDomainObjListFree; virDomainRemoveInactive; virDomainSaveConfig; + virDomainSoundDefFree; + virDomainSoundModelTypeFromString; virDomainSoundModelTypeToString; virDomainVirtTypeToString; + + + /* domain_event.h */ + virDomainEventQueueFree; + virDomainEventCallbackQueuePop; + virDomainEventCallbackQueuePush; + + + /* driver.h */ + virDriverLoadModule; + + + /* event.h */ + virEventAddHandle; + virEventAddTimeout; + virEventRemoveHandle; + virEventRemoveTimeout; + virEventUpdateHandle; + virEventUpdateTimeout; + + + /* hash.h */ + virHashAddEntry; + virHashCreate; + virHashForEach; + virHashFree; + virHashLookup; + virHashRemoveEntry; + virHashRemoveSet; + virHashSearch; + virHashSize; /* iptables.h */ @@ -391,12 +445,15 @@ virNetworkAssignDef; virNetworkDefFormat; virNetworkDefFree; + virNetworkDefParseFile; + virNetworkDefParseNode; virNetworkDefParseString; virNetworkDeleteConfig; virNetworkFindByName; virNetworkFindByUUID; virNetworkLoadAllConfigs; virNetworkObjListFree; + virNetworkDefParseNode; virNetworkRemoveInactive; virNetworkSaveConfig; @@ -405,8 +462,15 @@ virNodeInfoPopulate; + /* qparams.h */ + qparam_get_query; + qparam_query_parse; + free_qparam_set; + + /* stats_linux.h */ linuxDomainInterfaceStats; + xenLinuxDomainBlockStats; /* storage_backend.h */ @@ -465,20 +529,28 @@ virFileOpenTty; virFileReadLimFD; virFileReadPid; + virParseNumber; virRun; + virSkipSpaces; /* uuid.h */ virUUIDFormat; + virUUIDGenerate; + virUUIDParse; /* virterror_internal.h */ + virRaiseError; virReportErrorHelper; + virErrorMsg; /* xml.h */ + virXPathLong; + virXPathNodeSet; virXPathString; - + virXMLPropString; /* Finally everything else is totally private */ local: diff -r 3af981530f52 src/qemu_driver.c --- a/src/qemu_driver.c Thu Oct 30 11:04:28 2008 +0000 +++ b/src/qemu_driver.c Thu Oct 30 12:09:07 2008 +0000 @@ -3312,7 +3312,7 @@ .active = qemudActive, }; -int qemudRegister(void) { +int qemuRegister(void) { virRegisterDriver(&qemuDriver); virRegisterStateDriver(&qemuStateDriver); return 0; diff -r 3af981530f52 src/qemu_driver.h --- a/src/qemu_driver.h Thu Oct 30 11:04:28 2008 +0000 +++ b/src/qemu_driver.h Thu Oct 30 12:09:07 2008 +0000 @@ -47,6 +47,6 @@ # define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */ #endif -int qemudRegister(void); +int qemuRegister(void); #endif /* QEMUD_DRIVER_H */ diff -r 3af981530f52 src/xen_unified.c --- a/src/xen_unified.c Thu Oct 30 11:04:28 2008 +0000 +++ b/src/xen_unified.c Thu Oct 30 12:09:07 2008 +0000 @@ -1348,14 +1348,14 @@ }; /** - * xenUnifiedRegister: + * xenRegister: * * Register xen related drivers * * Returns the driver priority or -1 in case of error. */ int -xenUnifiedRegister (void) +xenRegister (void) { /* Ignore failures here. */ (void) xenHypervisorInit (); diff -r 3af981530f52 src/xen_unified.h --- a/src/xen_unified.h Thu Oct 30 11:04:28 2008 +0000 +++ b/src/xen_unified.h Thu Oct 30 12:09:07 2008 +0000 @@ -22,7 +22,7 @@ #include <winsock2.h> #endif -extern int xenUnifiedRegister (void); +extern int xenRegister (void); #define XEN_UNIFIED_HYPERVISOR_OFFSET 0 #define XEN_UNIFIED_PROXY_OFFSET 1 diff -r 3af981530f52 tests/Makefile.am --- a/tests/Makefile.am Thu Oct 30 11:04:28 2008 +0000 +++ b/tests/Makefile.am Thu Oct 30 12:09:07 2008 +0000 @@ -92,17 +92,17 @@ xml2sexprtest_SOURCES = \ xml2sexprtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h -xml2sexprtest_LDADD = $(LDADDS) +xml2sexprtest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS) sexpr2xmltest_SOURCES = \ sexpr2xmltest.c \ testutils.c testutils.h -sexpr2xmltest_LDADD = $(LDADDS) +sexpr2xmltest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS) xmconfigtest_SOURCES = \ xmconfigtest.c testutilsxen.c testutilsxen.h \ testutils.c testutils.h -xmconfigtest_LDADD = $(LDADDS) +xmconfigtest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS) qemuxml2argvtest_SOURCES = \ qemuxml2argvtest.c testutilsqemu.c testutilsqemu.h \ @@ -125,7 +125,7 @@ xencapstest_SOURCES = \ xencapstest.c testutils.h testutils.c -xencapstest_LDADD = $(LDADDS) +xencapstest_LDADD = ../src/libvirt_driver_xen.la $(LDADDS) nodeinfotest_SOURCES = \ nodeinfotest.c testutils.h testutils.c -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

As a convenience I've placed the entire patch series online for direct download avoiding email client mangling :-) http://berrange.fedorapeople.org/libvirt-dlopen/ On Thu, Oct 30, 2008 at 01:33:31PM +0000, Daniel P. Berrange wrote:
The following series of patches clean up our internal modularization to remove unneccessary dependancies between source files, and make everything follow a consistent pattern of XXXX.h declaring stuff in XXXX.c. Later in the series is plays some games with the linker scripts, and finally makes all hypervisor drivers fully modular, and optionally dlopen'able.
The 10'th patch in this series is a pre-requisite to enable us to merge David's host device patches, since it lets us avoid GPL/LGPL compat issues from DBus/HAL.
Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Thu, Oct 30, 2008 at 01:33:31PM +0000, Daniel P. Berrange wrote:
The following series of patches clean up our internal modularization to remove unneccessary dependancies between source files, and make everything follow a consistent pattern of XXXX.h declaring stuff in XXXX.c. Later in the series is plays some games with the linker scripts, and finally makes all hypervisor drivers fully modular, and optionally dlopen'able.
The 10'th patch in this series is a pre-requisite to enable us to merge David's host device patches, since it lets us avoid GPL/LGPL compat issues from DBus/HAL.
I have checked in patches 1 -> 6 in this series, since they were basically just moving code around. Need a little more review & testing of the later patches... Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (2)
-
Daniel P. Berrange
-
Daniel Veillard