Devel
Threads by month
- ----- 2026 -----
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- 38 participants
- 40039 discussions
Attached is a preliminary patch implementing the python bindings for domain events, and the EventImpl code.
This implements a python test app equivalent to the code in the C event-test app. Contrary to what Daniel B originally suggested, I thought that the EventImpl would be useful to expose for apps that are strictly using python, and not integrating with glib, or another event loop. It also makes the test case easier to debug.
I have not marked this with [PATCH] in the subject, as I don't believe it is quite complete.
I am still having a few issues with the Refcounting in the C code, and I think there is still some cleanup code I haven't quite handled quite right.
That said - I would welcome some comments/suggestions on this thus far, to make sure I'm not going off in a direction contrary to where you think I should be.
examples/domain-events/events-python/event-test.py | 187 ++++++++
python/generator.py | 8
python/libvir.c | 454 +++++++++++++++++++++
python/libvir.py | 20
python/libvirt_wrap.h | 27 +
python/types.c | 48 ++
6 files changed, 740 insertions(+), 4 deletions(-)
3
4
[libvirt] PATCH: Move domain event helpers out of internal.h/libvirt.c
by Daniel P. Berrange 29 Oct '08
by Daniel P. Berrange 29 Oct '08
29 Oct '08
There are a bunch of helper functions relating to domain events, which
are only used internally by hypervisor drivers. Following the principle
that libvirt.c should only contain functions exported in the API, and
internal.h should not define any function signatures, these helpers
need to move.
So I'm inventing a domain_events.c, and domain_events.h file to contain
the domain events helper code, in much same way as domain_conf.c and
domain_conf.h contain the domain XML helper code.
Again no functional change here. With this patch applied, the cleanup
of internal.h is basically complete - at least more than good enough
for now. It'd be nice to move the struct definitions of virDomainPtr,
etc elsewhere, perhaps to src/libvirt.h because they're public API,
but not exported publically.
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 | 73 ---------------
src/libvirt.c | 201 -------------------------------------------
src/qemu_conf.h | 1
src/remote_internal.c | 1
9 files changed, 326 insertions(+), 278 deletions(-)
Daniel
diff -r 0325a25d1762 qemud/event.c
--- a/qemud/event.c Wed Oct 29 11:48:08 2008 +0000
+++ b/qemud/event.c Wed Oct 29 12:03:29 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 0325a25d1762 qemud/event.h
--- a/qemud/event.h Wed Oct 29 11:48:08 2008 +0000
+++ b/qemud/event.h Wed Oct 29 12:03:29 2008 +0000
@@ -105,4 +105,11 @@
*/
int virEventRunOnce(void);
+int
+virEventHandleTypeToPollEvent(int events);
+int
+virPollEventToEventHandleType(int events);
+
+
+
#endif /* __VIRTD_EVENT_H__ */
diff -r 0325a25d1762 src/Makefile.am
--- a/src/Makefile.am Wed Oct 29 11:48:08 2008 +0000
+++ b/src/Makefile.am Wed Oct 29 12:03:29 2008 +0000
@@ -150,6 +150,7 @@
hash.c hash.h \
internal.h \
libvirt.c \
+ domain_event.c domain_event.h \
$(GENERIC_LIB_SOURCES) \
$(DOMAIN_CONF_SOURCES) \
$(NETWORK_CONF_SOURCES) \
diff -r 0325a25d1762 src/domain_event.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/domain_event.c Wed Oct 29 12:03:29 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 "libvirt.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 0325a25d1762 src/domain_event.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/domain_event.h Wed Oct 29 12:03:29 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 0325a25d1762 src/internal.h
--- a/src/internal.h Wed Oct 29 11:48:08 2008 +0000
+++ b/src/internal.h Wed Oct 29 12:03:29 2008 +0000
@@ -294,77 +294,4 @@
char key[PATH_MAX]; /* unique key for storage vol */
};
-
-/**
- * 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 0325a25d1762 src/libvirt.c
--- a/src/libvirt.c Wed Oct 29 11:48:08 2008 +0000
+++ b/src/libvirt.c Wed Oct 29 12:03:29 2008 +0000
@@ -5371,207 +5371,6 @@
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 0325a25d1762 src/qemu_conf.h
--- a/src/qemu_conf.h Wed Oct 29 11:48:08 2008 +0000
+++ b/src/qemu_conf.h Wed Oct 29 12:03:29 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 0325a25d1762 src/remote_internal.c
--- a/src/remote_internal.c Wed Oct 29 11:48:08 2008 +0000
+++ b/src/remote_internal.c Wed Oct 29 12:03:29 2008 +0000
@@ -75,6 +75,7 @@
#include "virterror.h"
#include "libvirt.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 :|
3
2
[libvirt] PATCH Move misc functions out of hash.c/internal.h into libvirt.c
by Daniel P. Berrange 29 Oct '08
by Daniel P. Berrange 29 Oct '08
29 Oct '08
The hash.c file contains a nice generic implementation of hash tables, and
then adds a bunch of code for creating/deleting virDomainPtr, virConnectPtr,
virNetworkPtr and virStoragePoolPtr objects which is totally unrelated to
hash tables.
The internal.h file also contains function signatures for a bunch of
APIs which are exported in the libvirt.so, but not part of the official
public API in libvirt/libvirt.h. Their impl is mostly in libvirt.c,
along with the aforementioned stuff from hash.c
To improve internal modularization / cross-file dependancies, this patch
tries to isolate the impl of all exported functions in libvirt.c, and for
those API which are part of the public API, place their declaration in
the src/libvirt.h file.
So, the src/libvirt.h file gets the following exported, but not public
funtions, with the impl of the virGetXXX/virUnrefXXX moving out of hash.c
and into libvirt.c to be alongside other impls of public APIs.
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);
int __virStateInitialize(void);
int __virStateCleanup(void);
int __virStateReload(void);
int __virStateActive(void);
int __virStateSigDispatcher(siginfo_t *siginfo);
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);
Finally, the files for internal hypervisor drivers need to include this
new libvirt.h file.
This is step 2 in cleaning up the definitions visible in internal.h
As before, there should be no functional change in this patch, merely
a bunch of code moving, and #include fixups
b/src/libvirt.h | 98 ++++++
qemud/qemud.c | 2
qemud/remote.c | 2
src/hash.c | 726 -------------------------------------------------
src/internal.h | 52 ---
src/libvirt.c | 728 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/lxc_driver.c | 1
src/network_driver.c | 1
src/openvz_driver.c | 1
src/proxy_internal.h | 3
src/qemu_driver.c | 1
src/remote_internal.c | 1
src/storage_driver.c | 1
src/test.c | 1
src/xen_internal.c | 1
src/xend_internal.c | 1
src/xm_internal.c | 1
src/xs_internal.c | 1
18 files changed, 842 insertions(+), 780 deletions(-)
Daniel
diff -r ef2d00e6bc78 qemud/qemud.c
--- a/qemud/qemud.c Wed Oct 29 11:36:21 2008 +0000
+++ b/qemud/qemud.c Wed Oct 29 11:48:08 2008 +0000
@@ -49,7 +49,7 @@
#include <signal.h>
#include <netdb.h>
-#include "internal.h"
+#include "libvirt.h"
#include "qemud.h"
#include "util.h"
diff -r ef2d00e6bc78 qemud/remote.c
--- a/qemud/remote.c Wed Oct 29 11:36:21 2008 +0000
+++ b/qemud/remote.c Wed Oct 29 11:48:08 2008 +0000
@@ -48,7 +48,7 @@
#include <polkit-dbus/polkit-dbus.h>
#endif
-#include "internal.h"
+#include "libvirt.h"
#include "qemud.h"
#include "memory.h"
diff -r ef2d00e6bc78 src/hash.c
--- a/src/hash.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/hash.c Wed Oct 29 11:48:08 2008 +0000
@@ -25,6 +25,7 @@
#include <libxml/threads.h>
#include "virterror.h"
+#include "libvirt.h"
#include "hash.h"
#include "memory.h"
@@ -594,728 +595,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 ef2d00e6bc78 src/internal.h
--- a/src/internal.h Wed Oct 29 11:36:21 2008 +0000
+++ b/src/internal.h Wed Oct 29 11:48:08 2008 +0000
@@ -295,58 +295,6 @@
};
-
-/************************************************************************
- * *
- * 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);
-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);
-
-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 ef2d00e6bc78 src/libvirt.c
--- a/src/libvirt.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/libvirt.c Wed Oct 29 11:48:08 2008 +0000
@@ -32,6 +32,7 @@
#endif
#include "virterror.h"
+#include "libvirt.h"
#include "driver.h"
#include "uuid.h"
@@ -5570,3 +5571,730 @@
return 0;
}
+
+
+/************************************************************************
+ * *
+ * 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) {
+ 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 ef2d00e6bc78 src/libvirt.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/libvirt.h Wed Oct 29 11:48:08 2008 +0000
@@ -0,0 +1,98 @@
+/*
+ * 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"
+
+
+/************************************************************************
+ * *
+ * 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);
+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);
+
+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 ef2d00e6bc78 src/lxc_driver.c
--- a/src/lxc_driver.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/lxc_driver.c Wed Oct 29 11:48:08 2008 +0000
@@ -36,6 +36,7 @@
#include <wait.h>
#include "virterror.h"
+#include "libvirt.h"
#include "lxc_conf.h"
#include "lxc_container.h"
#include "lxc_driver.h"
diff -r ef2d00e6bc78 src/network_driver.c
--- a/src/network_driver.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/network_driver.c Wed Oct 29 11:48:08 2008 +0000
@@ -45,6 +45,7 @@
#include <sys/ioctl.h>
#include "virterror.h"
+#include "libvirt.h"
#include "network_driver.h"
#include "network_conf.h"
#include "driver.h"
diff -r ef2d00e6bc78 src/openvz_driver.c
--- a/src/openvz_driver.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/openvz_driver.c Wed Oct 29 11:48:08 2008 +0000
@@ -48,6 +48,7 @@
#include <sys/wait.h>
#include "virterror.h"
+#include "libvirt.h"
#include "openvz_driver.h"
#include "event.h"
#include "buf.h"
diff -r ef2d00e6bc78 src/proxy_internal.h
--- a/src/proxy_internal.h Wed Oct 29 11:36:21 2008 +0000
+++ b/src/proxy_internal.h Wed Oct 29 11:48:08 2008 +0000
@@ -12,7 +12,8 @@
#ifndef __LIBVIR_PROXY_H__
#define __LIBVIR_PROXY_H__
-#include "libvirt/libvirt.h"
+#include "internal.h"
+#include "libvirt.h"
#define PROXY_SOCKET_PATH "/tmp/livirt_proxy_conn"
#define PROXY_PROTO_VERSION 1
diff -r ef2d00e6bc78 src/qemu_driver.c
--- a/src/qemu_driver.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/qemu_driver.c Wed Oct 29 11:48:08 2008 +0000
@@ -53,6 +53,7 @@
#endif
#include "virterror.h"
+#include "libvirt.h"
#include "qemu_driver.h"
#include "qemu_conf.h"
#include "c-ctype.h"
diff -r ef2d00e6bc78 src/remote_internal.c
--- a/src/remote_internal.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/remote_internal.c Wed Oct 29 11:48:08 2008 +0000
@@ -74,6 +74,7 @@
#endif
#include "virterror.h"
+#include "libvirt.h"
#include "driver.h"
#include "buf.h"
#include "qparams.h"
diff -r ef2d00e6bc78 src/storage_driver.c
--- a/src/storage_driver.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/storage_driver.c Wed Oct 29 11:48:08 2008 +0000
@@ -33,6 +33,7 @@
#include <string.h>
#include "virterror.h"
+#include "libvirt.h"
#include "driver.h"
#include "util.h"
#include "storage_driver.h"
diff -r ef2d00e6bc78 src/test.c
--- a/src/test.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/test.c Wed Oct 29 11:48:08 2008 +0000
@@ -32,6 +32,7 @@
#include "virterror.h"
+#include "libvirt.h"
#include "test.h"
#include "buf.h"
#include "util.h"
diff -r ef2d00e6bc78 src/xen_internal.c
--- a/src/xen_internal.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/xen_internal.c Wed Oct 29 11:48:08 2008 +0000
@@ -41,6 +41,7 @@
#include <xen/sched.h>
#include "virterror.h"
+#include "libvirt.h"
#include "driver.h"
#include "util.h"
#include "xen_unified.h"
diff -r ef2d00e6bc78 src/xend_internal.c
--- a/src/xend_internal.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/xend_internal.c Wed Oct 29 11:48:08 2008 +0000
@@ -33,6 +33,7 @@
#include <errno.h>
#include "virterror.h"
+#include "libvirt.h"
#include "xend_internal.h"
#include "driver.h"
#include "util.h"
diff -r ef2d00e6bc78 src/xm_internal.c
--- a/src/xm_internal.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/xm_internal.c Wed Oct 29 11:48:08 2008 +0000
@@ -36,6 +36,7 @@
#include <xen/dom0_ops.h>
#include "virterror.h"
+#include "libvirt.h"
#include "xm_internal.h"
#include "xen_unified.h"
#include "xend_internal.h"
diff -r ef2d00e6bc78 src/xs_internal.c
--- a/src/xs_internal.c Wed Oct 29 11:36:21 2008 +0000
+++ b/src/xs_internal.c Wed Oct 29 11:48:08 2008 +0000
@@ -27,6 +27,7 @@
#include <xs.h>
#include "virterror.h"
+#include "libvirt.h"
#include "driver.h"
#include "xen_unified.h"
#include "xs_internal.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 :|
3
3
[libvirt] PATCH: Remove virStringList & improve virStoragePoolSourceList
by Daniel P. Berrange 29 Oct '08
by Daniel P. Berrange 29 Oct '08
29 Oct '08
Chris' recent patch removed use of the virStringList for the LVM discovery,
but it was still used in the NFS discovery code. I figured we might as well
make NFS discovery use virStoragePoolSourceList() too. This require a few
changes:
- Include pool type in virStoragePoolSourceList so XML formatter knows
what type of source information is available
- Factor out code to format a single virStoragePoolSourcePtr object
into a virStoragePoolSourceFormat method
- Make virStoragePoolDefFormat & virStoragePoolListFormat both call
this common method
- Make LVM discovery code set the pool type in source list
- Switch NFS discovery to use virStoragePoolSourceList
This also has benfit of giving proper indentation in the XML
# ./virsh find-storage-pool-sources-as logical
<sources>
<source>
<device path='/dev/sda2'/>
<name>HostVG</name>
<format type='lvm2'/>
</source>
</sources>
# ./virsh find-storage-pool-sources-as --host aubergine.redhat.com netfs
<sources>
<source>
<host name='aubergine.redhat.com'/>
<dir path='/mnt/export'/>
<format type='nfs'/>
</source>
<source>
<host name='aubergine.redhat.com'/>
<dir path='/home'/>
<format type='nfs'/>
</source>
</sources>
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 :|
2
1
[libvirt] libvirt adds ", boot-on" to qemu-kvm command line - prevents guest boot!
by Bruce Rogers 28 Oct '08
by Bruce Rogers 28 Oct '08
28 Oct '08
I'm experimenting with libvirt and qemu-kvm using a raw hard disk image that has a bootable DOS partition in it. I noticed that libvirt was adding the ",boot=on" option to the disk section of the qemu-kvm command line. This prevents the guest from booting somehow. If that option is removed, then the guest can boot just fine. What is that option used for and is there any way to cause libvirt to not add it in my scenario?
- Bruce Rogers
1
0
Last week, I set out simply to adjust libvirt to accommodate a
recent gnulib API change, whereby you now include the standard
<netdb.h> rather than the gnulib-made-up "getaddrinfo.h" header file.
That meant pulling in many gnulib updates (a lot's been happening
on the mingw portability front recently), and there's been some
churn, so I'd pull in an update, find that it exposes more portability
problems, fix them, (but that may have also added a new warning, so fix
that), pull in another update, find more, etc. Most of this has been
mingw-specific, but I addressed some of the test-related warnings by
removing ifdefs so that the same code is compiled in both mingw and
non-mingw cases.
I think we've settled on a local fixed point, with the result
triggering only the two XDR warnings I already wrote about.
This patch series includes all of the above (leaving out 10K
lines of automatically-pulled-from-gnulib diffs) and cleans up
the state of .cvsignore and .gitignore files:
1 exempt gnulib from ctype-macros prohibition
2 exempt gnulib from write-avoidance syntax check
3 use ARRAY_CARDINALITY more
4 * src/network_conf.c: Include <string.h> for declaration of memcmp.
5 adapt to API change in gnulib
6 use more gnulib modules
7 updates from gnulib (this is the 10K-line diff -- mostly omitted)
8 socketcompat.h: simplify, to match latest gnulib
9 use errno, not socket_errno()
10 remove duplicate inclusion of "remote_protocol.h" (before <config.h>!)
11 * src/remote_internal.c (remoteFindDaemonPath) [!WIN32]: Don't compile.
12 include netinet etc #ifndef HAVE_WINSOCK2_H
13 * qemud/remote_protocol.x: Include "remote_protocol.h" and <rpc/xdr.h>.
14 * remote_protocol.c, remote_protocol.h: regenerate
15 cvsignore mingw build artifacts: *.exe
16 avoid many mingw-specific warnings
17 avoid compiler warning when all storage backends are disabled
2
44
I'm looking into implementing emitting events from the xen driver, and I've run into a bit of a snag that I would like to discuss
I've attached an old version of my patch for reference.
However - from past discussions, I know that there was a desire to keep the xen driver stateless. However, given the semantics of xenstore watches, and events, I'm not sure I can see a way to preserve this.
Lets take the case of creating a new domain:
XenStore gives us the functionaliity to put a watch on the special xenstore key @introduceDomain.
However, when the watch fires - I see no mechanism of determining which domain has been introduced.
The only mechanism I can find is to maintain a list of domains, and keep this up to date with events.
So I'm wondering if anyone has any ideas, or if this will introduce unwanted, but necessary state into the driver?
Ben
2
1
Hi -
I'm about to start working on host device enumeration, along the
(HAL-ish) lines of what was discussed back in April:
https://www.redhat.com/archives/libvir-list/2008-April/msg00005.html
I know the xml details haven't been fully fleshed out, but there seems
to be agreement that it will be a fairly direct mapping from (a subset
of the) HAL info to the details that we need in the xml. Doubtless it
will take a while to figure out exactly what subset suffices (and, for
that matter, if everything needed is available via HAL ...), but I think
the work is well-defined for some of the obvious details (discussed in
the above thread) on which there's broad agreement.
Is anyone working on such an implementation?
Thanks,
Dave
3
37
All,
One thing that oVirt would like to have (and that might be useful for other
users) is a call that would do some basic sanity checking for live migration.
This call would go over to the remote libvirtd, do some checks, and
return whether we think migration is likely to succeed. Note that I say
"likely to succeed", because there are certainly things that can cause migration
to fail after we've made checks, but anything is better than what we have today
("try it and pray").
Now, in order for this call to be widely useful, I think we would have to allow
the caller to specify *which* of the available checks they would like to
perform, and then have some sort of return value that indicated if there are
show-stopper problems, or just problems that may cause things to be sub-optimal
on the remote side. The caller could then decide what action it wants to take.
There is also a corollary to the "is it sane for me to migrate", which is, given
two hosts A and B, what's the lowest common denominator I need to run my guest
at so that migration will likely be successful between them. This could also be
used by management apps to make sure things are configured properly for the
guest before ever starting it.
The biggest problem with implementing these calls, however, is that there is no
comprehensive list of things we should check. This e-mail is an attempt to
write down some of the more obvious things we need to check, and to garner
discussion of things I might have missed. Once I have a proper list, I'll add
it to the TODO page on the libvirt Wiki so it's at least somewhere permanent.
Note that we don't have to implement *all* of these as a first go at this; if we
leave it open enough, we can add more checks as we go along without breaking
compatibility.
MIGRATION CRITERIA:
0) Matching hypervisors - seems obvious, but I'm not sure if we have these
checks today. Make sure we don't try to migrate Xen to KVM or vice-versa. We
also might want to think of at least warning the caller if you try to migrate
from a "newer" hypervisor (say, Xen 3.2) to an "older" hypervisor (say, Xen
3.1). That should, in theory, work, but maybe the caller would prefer not to do
that if possible. Rich has pointed out that KVM and Xen are accidentally
incompatible in libvirt, but we should make it explicit.
1) Matching CPU architectures - also obvious, but as far as I know today,
there's no checking for this (well, at least in Xen; I don't know about
libvirt). So you can happily attempt to migrate from i386 -> ia64, and watch
the fireworks. We also need to make sure you can't migrate x86_64 -> i386. I
believe i386 -> x86_64 should work, but this might be hypervisor dependent.
2) Matching CPU vendors - this one isn't a hard requirement; given the things
below, we may still be likely to succeed even if we go from AMD to Intel or
vice-versa. It still might be useful information for the caller to know.
3) CPU flags - the CPU flags of the destination *must* be a superset of the CPU
flags that were presented to the guest at startup. Many OS's and application
check for CPU flags once at startup to choose optimized routines, and then never
check again; if they happened to select sse3, and sse3 is not there on the
destination, then they will (eventually) crash.
This is where the CPU masking technology and the lowest common denominator
libvirt call can make a big difference. If you make sure to mask some of the
CPU flags off of the guest when you are first creating it, then the destination
host just needs a superset of the flags that were presented to the guest at
bootup, which makes the problem easier.
4) Number of CPUs - generally, you want the destination to have at least one
physical CPU for each virtual CPU assigned to the guest. However, I can see use
cases where this might not be the case (temporary or emergency migrations). So
this would probably be a warning, and the caller can make the choice of whether
to proceed.
5a) Memory - non-NUMA -> non-NUMA - fairly straightforward. The destination
must have enough memory to fit the guest memory. We might want to do some
"extra" checking on the destination to make sure we aren't going to OOM the
destination as soon as we arrive.
5b) Memory - non-NUMA -> NUMA - A little trickier. There are no cpusets we
have to worry about, since we are coming from non-NUMA, but for absolute best
performance, we should try to fit the whole guest into a single NUMA node. Of
course, if that node is overloaded, that may be a bad idea. NUMA placement
problem, basically.
5c) Memory - NUMA -> non-NUMA - Less tricky. On the destination, all memory is
"equally" far away, so no need to worry about cpusets. Just have to make sure
that there is enough memory on the destination for the guest.
5d) Memory - NUMA -> NUMA - Tricky, just like case 5b). Need to determine if
there is enough memory in the machine first, then check if we can fit the guest
in a single node, and also check if we can match the cpuset from the source on
the destination.
6a) Networks - at the very least, the destination must have the same bridges
configured as the source side. Whether those bridges are hooked to the same
physical networks as the source or not is another question, and may be outside
the bounds of what we can/should check.
6b) Networks - we need to make sure that the device model on the remote side
supports the same devices as the source side. That is, if you have a e1000 nic
on the source side, but your destination doesn't support it, you are going to
fail the migration.
7a) Disks - we have to make sure that all of the disks on the source side are
available on the destination side, at the same paths. To be entirely clear, we
have to make sure that the file on the destination side is the *same* file as on
the source side, not just a file with the same name. For traditional
file-based, the best we can do may be path names. For device names (like LVM,
actual disk partitions, etc.), we might be able to take advantage of device
enumaration API's and validate that the device info is the same (UUID matching,
etc.).
7b) Disks - Additionally, we need to make sure that the device model on the
remote side supports the same devices as the source side. That is, if you have
a virtio drive on the source side, but your destination host doesn't support
virtio on the backend, you are going to fail. (virtio might be a bad example,
but there might be further things in the device model in the future that we
might not necessarily have on both ends).
------ That's the absolute basic criteria. More esoteric/less thought-out
criteria follow:
8) Time skew - this is less thought out at the moment, but if you calibrated
your lpj at boot time, and now you migrate to a host with a different clock
frequency, your time will run either fast or slow compared to what you expect.
Also synchronized vs. unsynchronized TSC could cause issues, etc.
9) PCI-passthrough - this is actually a check on the *source* side. If the
guest is using a PCI passthrough device, it *usually* doesn't make sense to
live migrate it. On the other hand, it looks like various groups are trying to
make this work (with the bonding of a PV NIC to a PCI-passthrough NIC), so we
need to keep that in mind, and not necessarily make this a hard failure.
10) MSR's?? - I've thought about this one before, but I'm not sure what the
answer is. Unfortunately, MSR's in virtualization are sort of done hodge-podge.
That is, some MSR's are emulated for the guests, some MSR's guests have direct
control over, and some aren't emulated at all. This one can get ugly fast; it's
probably something we want to leave until later.
11) CPUID?? - Not entirely sure about this one; there is a lot of
model-specific information encoded in the various CPUID calls (things like cache
size, cache line size, etc. etc). However, I don't know if CPUID instructions
are trapped-n-emulated under the different hypervisors, or if they are done
right on the processor itself. I guess if an OS or application called this at
startup, cached the information, and then checked again later it might get
upset, but it seems somewhat unlikely.
Things that I've missed?
Thanks,
Chris Lalancette
6
9
I've been building with mingw to make sure that my gnulib-upgrade-and-extend
patch doesn't break anything and found some compiler warnings.
I fixed most of them, but this one is ugly:
../qemud/remote_protocol.c:317: warning: assignment from incompatible pointer type
../qemud/remote_protocol.c:346: warning: assignment from incompatible pointer type
That's due to the fact that the mingw xdr.h header,
/usr/i686-pc-mingw32/sys-root/mingw/include/rpc/xdr.h, defines this
#define XDR_INLINE(xdrs, len) \
(*(xdrs)->x_ops->x_inline)(xdrs, len)
and has an x_inline member of type long*,
typedef struct {
enum xdr_op x_op; /* operation; fast additional param */
struct xdr_ops {
bool_t (*x_getlong)(); /* get a long from underlying stream */
bool_t (*x_putlong)(); /* put a long to " */
bool_t (*x_getbytes)();/* get some bytes from " */
bool_t (*x_putbytes)();/* put some bytes to " */
u_int (*x_getpostn)();/* returns bytes off from beginning */
bool_t (*x_setpostn)();/* lets you reposition the stream */
long * (*x_inline)(); /* buf quick ptr to buffered data */
while we're used to one with type matching buf: int32_t*:
If you're serious about getting rid of warnings even on mingw,
here's one approach:
diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c
index 68e9696..c8cf504 100644
--- a/qemud/remote_protocol.c
+++ b/qemud/remote_protocol.c
@@ -314,7 +314,7 @@ xdr_remote_node_get_info_ret (XDR *xdrs, remote_node_get_info_ret *objp)
return FALSE;
if (!xdr_quad_t (xdrs, &objp->memory))
return FALSE;
- buf = XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
+ buf = (void*)XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (!xdr_int (xdrs, &objp->cpus))
return FALSE;
@@ -343,7 +343,7 @@ xdr_remote_node_get_info_ret (XDR *xdrs, remote_node_get_info_ret *objp)
return FALSE;
if (!xdr_quad_t (xdrs, &objp->memory))
return FALSE;
- buf = XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
+ buf = (void*)XDR_INLINE (xdrs, 6 * BYTES_PER_XDR_UNIT);
if (buf == NULL) {
if (!xdr_int (xdrs, &objp->cpus))
return FALSE;
Better would be to fix the decl in xdr.h, but probably not feasible.
Alternatively, redefine XDR_INLINE for mingw, adding the void* cast in that.
But that means peeking inside (and copying) the current definition,
so I prefer the above.
So I'm leaning towards using the patch above.
3
3