Re: [libvirt] KVM/qemu: problems with autostart of vms with non-bridged nets

2008-11-30 Thread Gerd von Egidy
Hi,

> 2. missing virConnectPtr during autostart of the vm:
>
> in src/qemu_driver.c:145, qemudAutostartConfigs() you can find this call:
> int ret = qemudStartVMDaemon(NULL, driver, vm, NULL);
>
> This means virConnectPtr conn is NULL within qemudStartVMDaemon().
> Following the calls:
> qemudStartVMDaemon()
> -> qemudBuildCommandLine()
> -> qemudNetworkIfaceConnect()
> -> virNetworkLookupByName()
>
> virNetworkLookupByName bails out if called with invalid virConnectPtr. This
> means starting this vm fails.

I came up with the attached patch to fix this for me, but
a) I'm not sure if it is a clean use of the api to call virConnectOpen() from 
   within a state-initializer function
b) This is just for qemu/kvm, I haven't looked at any other drivers

It would be nice if an experienced libvirt-developer could take a look at
this. Thank you very much.

Kind regards,

Gerd


diff -r -u libvirt-0.5.0.orig/src/qemu_driver.c libvirt-0.5.0/src/qemu_driver.c
--- libvirt-0.5.0.orig/src/qemu_driver.c2008-11-21 13:47:32.0 
+0100
+++ libvirt-0.5.0/src/qemu_driver.c 2008-12-01 01:49:16.0 +0100
@@ -138,11 +138,14 @@
 qemudAutostartConfigs(struct qemud_driver *driver) {
 unsigned int i;
 
+/* we need a valid virConnectPtr for qemudStartVMDaemon to be able to 
connect to other drivers */
+virConnectPtr conn=virConnectOpen(getuid() ? "qemu:///session" : 
"qemu:///system");
+
 for (i = 0 ; i < driver->domains.count ; i++) {
 virDomainObjPtr vm = driver->domains.objs[i];
 if (vm->autostart &&
 !virDomainIsActive(vm)) {
-int ret = qemudStartVMDaemon(NULL, driver, vm, NULL);
+int ret = qemudStartVMDaemon(conn, driver, vm, NULL);
 if (ret < 0) {
 virErrorPtr err = virGetLastError();
 qemudLog(QEMUD_ERR, _("Failed to autostart VM '%s': %s\n"),
@@ -154,6 +157,8 @@
 }
 }
 }
+
+virConnectClose(conn);
 }
 
 /**
-- 
Address (better: trap) for people I really don't want to get mail from:
[EMAIL PROTECTED]

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] PATCH: 0/28: Thread safety for libvirtd daemon and drivers

2008-11-30 Thread Daniel P. Berrange
This is a diffstat summary for the combined series of 28 patches


 b/Makefile.maint |1 
 b/qemud/Makefile.am  |   24 
 b/qemud/THREADING.txt|   63 
 b/qemud/event.c  |  168 +
 b/qemud/event.h  |   14 
 b/qemud/libvirtd.aug |6 
 b/qemud/libvirtd.conf|   19 
 b/qemud/qemud.c  |  273 ++-
 b/qemud/qemud.h  |   34 
 b/qemud/remote.c | 3030 ++-
 b/qemud/remote_dispatch_args.h   |  101 +
 b/qemud/remote_dispatch_prototypes.h |  936 +-
 b/qemud/remote_dispatch_ret.h|   88 +
 b/qemud/remote_dispatch_table.h  |  594 ++
 b/qemud/remote_generate_stubs.pl |  197 --
 b/qemud/test_libvirtd.aug|   38 
 b/src/datatypes.c|1 
 b/src/datatypes.h|1 
 b/src/domain_conf.c  |   56 
 b/src/domain_conf.h  |4 
 b/src/domain_event.c |  191 +-
 b/src/domain_event.h |   51 
 b/src/libvirt.c  |   14 
 b/src/libvirt_sym.version.in |   25 
 b/src/lxc_conf.h |2 
 b/src/lxc_driver.c   |  453 +++--
 b/src/network_conf.c |   54 
 b/src/network_conf.h |5 
 b/src/network_driver.c   |  439 +++--
 b/src/node_device.c  |  118 +
 b/src/node_device.h  |4 
 b/src/node_device_conf.c |   36 
 b/src/node_device_conf.h |8 
 b/src/node_device_devkit.c   |   41 
 b/src/node_device_hal.c  |  166 +
 b/src/openvz_conf.h  |2 
 b/src/openvz_driver.c|  493 +++--
 b/src/qemu_conf.h|5 
 b/src/qemu_driver.c  | 2321 +++---
 b/src/remote_internal.c  |   93 -
 b/src/storage_conf.c |   44 
 b/src/storage_conf.h |7 
 b/src/storage_driver.c   |  860 ++---
 b/src/test.c | 2016 +--
 b/src/uml_conf.h |2 
 b/src/uml_driver.c   |  617 ---
 b/src/xen_inotify.c  |  135 -
 b/src/xen_unified.c  |   30 
 b/src/xen_unified.h  |4 
 b/src/xs_internal.c  |   56 
 b/tests/virsh-all|1 
 qemud/remote_dispatch_localvars.h|  185 --
 qemud/remote_dispatch_proc_switch.h  |  898 --
 54 files changed, 9513 insertions(+), 5594 deletions(-)

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] PATCH: 28/28: Remove unused param in QEMU monitor APIs

2008-11-30 Thread Daniel P. Berrange
The QEMU driver internal API for interacting with the monitor console takes
a 'struct qemud_driver *' parameter. This is a problem because any access
to this struct must be protected by a lock, but we do not want to hold the
global driver lock for all monitor operations since it would destroy any
hope of concurrency. Fortunately tracing down many levels of call reveals
this parameter is totally unused, so this patch removes it from a tonne of
internal APIs

 qemu_driver.c |  109 ++
 1 file changed, 49 insertions(+), 60 deletions(-)

Daniel

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -136,8 +136,7 @@ static void qemudShutdownVMDaemon(virCon
 
 static int qemudDomainGetMaxVcpus(virDomainPtr dom);
 
-static int qemudMonitorCommand (const struct qemud_driver *driver,
-const virDomainObjPtr vm,
+static int qemudMonitorCommand (const virDomainObjPtr vm,
 const char *cmd,
 char **reply);
 
@@ -386,14 +385,12 @@ qemudShutdown(void) {
 
 /* Return -1 for error, 1 to continue reading and 0 for success */
 typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
-  struct qemud_driver *driver,
   virDomainObjPtr vm,
   const char *output,
   int fd);
 
 static int
 qemudReadMonitorOutput(virConnectPtr conn,
-   struct qemud_driver *driver,
virDomainObjPtr vm,
int fd,
char *buf,
@@ -452,7 +449,7 @@ qemudReadMonitorOutput(virConnectPtr con
 } else {
 got += ret;
 buf[got] = '\0';
-if ((ret = func(conn, driver, vm, buf, fd)) != 1)
+if ((ret = func(conn, vm, buf, fd)) != 1)
 return ret;
 }
 }
@@ -466,7 +463,6 @@ qemudReadMonitorOutput(virConnectPtr con
 
 static int
 qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
-struct qemud_driver *driver ATTRIBUTE_UNUSED,
 virDomainObjPtr vm,
 const char *output,
 int fd)
@@ -480,7 +476,6 @@ qemudCheckMonitorPrompt(virConnectPtr co
 }
 
 static int qemudOpenMonitor(virConnectPtr conn,
-struct qemud_driver *driver,
 virDomainObjPtr vm,
 const char *monitor) {
 int monfd;
@@ -504,7 +499,7 @@ static int qemudOpenMonitor(virConnectPt
 }
 
 ret = qemudReadMonitorOutput(conn,
- driver, vm, monfd,
+ vm, monfd,
  buf, sizeof(buf),
  qemudCheckMonitorPrompt,
  "monitor");
@@ -564,7 +559,6 @@ static int qemudExtractMonitorPath(virCo
 
 static int
 qemudFindCharDevicePTYs(virConnectPtr conn,
-struct qemud_driver *driver,
 virDomainObjPtr vm,
 const char *output,
 int fd ATTRIBUTE_UNUSED)
@@ -603,7 +597,7 @@ qemudFindCharDevicePTYs(virConnectPtr co
 }
 
 /* Got them all, so now open the monitor console */
-ret = qemudOpenMonitor(conn, driver, vm, monitor);
+ret = qemudOpenMonitor(conn, vm, monitor);
 
 cleanup:
 VIR_FREE(monitor);
@@ -611,11 +605,10 @@ cleanup:
 }
 
 static int qemudWaitForMonitor(virConnectPtr conn,
-   struct qemud_driver *driver,
virDomainObjPtr vm) {
 char buf[1024]; /* Plenty of space to get startup greeting */
 int ret = qemudReadMonitorOutput(conn,
- driver, vm, vm->stderr_fd,
+ vm, vm->stderr_fd,
  buf, sizeof(buf),
  qemudFindCharDevicePTYs,
  "console");
@@ -632,7 +625,6 @@ static int qemudWaitForMonitor(virConnec
 
 static int
 qemudDetectVcpuPIDs(virConnectPtr conn,
-struct qemud_driver *driver,
 virDomainObjPtr vm) {
 char *qemucpus = NULL;
 char *line;
@@ -656,7 +648,7 @@ qemudDetectVcpuPIDs(virConnectPtr conn,
 return 0;
 }
 
-if (qemudMonitorCommand(driver, vm, "info cpus", &qemucpus) < 0) {
+if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
 qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
  "%s", _("cannot run monitor command to fetch CPU 
thread info"));
 VIR_FREE(vm->vcpupids);
@@ -732,7 +724,6 @@ error:
 
 static int
 qemudInitCpus(virConnectPtr conn,
-  struct qemud_driver *driver,
 

Re: [libvirt] PATCH: 27/28: Configurable threading in libvirtd

2008-11-30 Thread Daniel P. Berrange
This patch extends the libvirtd configuration file to allow various thread
related parameters to be tuned. It introduces a limit on the number of
client connections allowed over TCP socket to prevent DOS attacks on the
machine resources. It also adds a min/max worker thread pool size for
handling RPC calls. 

 libvirtd.aug  |6 ++
 libvirtd.conf |   19 +++
 qemud.c   |   17 -
 test_libvirtd.aug |   38 ++
 4 files changed, 79 insertions(+), 1 deletion(-)

Daniel

diff --git a/qemud/libvirtd.aug b/qemud/libvirtd.aug
--- a/qemud/libvirtd.aug
+++ b/qemud/libvirtd.aug
@@ -13,11 +13,13 @@ module Libvirtd =
 
let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\""
let bool_val = store /0|1/
+   let int_val = store /[0-9]+/
let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ ""
let str_array_val = counter "el" . array_start . ( str_array_element . ( 
array_sep . str_array_element ) * ) ? . array_end
 
let str_entry   (kw:string) = [ key kw . value_sep . str_val ]
let bool_entry  (kw:string) = [ key kw . value_sep . bool_val ]
+   let int_entry  (kw:string) = [ key kw . value_sep . int_val ]
let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ]
 
 
@@ -48,6 +50,9 @@ module Libvirtd =
| str_array_entry "tls_allowed_dn_list"
| str_array_entry "sasl_allowed_username_list"
 
+   let processing_entry = int_entry "min_workers"
+| int_entry "max_workers"
+| int_entry "max_clients"
 
(* Each enty in the config is one of the following three ... *)
let entry = network_entry
@@ -55,6 +60,7 @@ module Libvirtd =
  | authentication_entry
  | certificate_entry
  | authorization_entry
+ | processing_entry
let comment = [ label "#comment" . del /#[ \t]*/ "# " .  store /([^ 
\t\n][^\n]*)?/ . del /\n/ "\n" ]
let empty = [ label "#empty" . eol ]
 
diff --git a/qemud/libvirtd.conf b/qemud/libvirtd.conf
--- a/qemud/libvirtd.conf
+++ b/qemud/libvirtd.conf
@@ -225,3 +225,22 @@
 #sasl_allowed_username_list = ["[EMAIL PROTECTED]", "[EMAIL PROTECTED]" ]
 
 
+
+#
+#
+# Processing controls
+#
+
+# The maximum number of concurrent client connections to allow
+# over all sockets combined.
+# max_clients = 20
+
+
+# The minimum limit sets the number of workers to start up
+# initially. If the number of active clients exceeds this,
+# then more threads are spawned, upto max_workers limit.
+# Typically you'd want max_workers to equal maximum number
+# of clients allowed
+#min_workers = 5
+#max_workers = 20
+
diff --git a/qemud/qemud.c b/qemud/qemud.c
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -129,6 +129,10 @@ static char *crl_file = (char *) "";
 
 static gnutls_certificate_credentials_t x509_cred;
 static gnutls_dh_params_t dh_params;
+
+static int min_workers = 5;
+static int max_workers = 20;
+static int max_clients = 20;
 
 #define DH_BITS 1024
 
@@ -1167,6 +1171,12 @@ static int qemudDispatchServer(struct qe
 return -1;
 }
 
+if (server->nclients >= max_clients) {
+qemudLog(QEMUD_ERR, "%s", _("Too many active clients, dropping 
connection"));
+close(fd);
+return -1;
+}
+
 if (VIR_REALLOC_N(server->clients, server->nclients+1) < 0) {
 qemudLog(QEMUD_ERR, "%s", _("Out of memory allocating clients"));
 close(fd);
@@ -1825,7 +1835,7 @@ static int qemudRunLoop(struct qemud_ser
 
 pthread_mutex_lock(&server->lock);
 
-server->nworkers = 10;
+server->nworkers = min_workers;
 if (VIR_ALLOC_N(server->workers, server->nworkers) < 0) {
 qemudLog(QEMUD_ERR, "%s", _("Failed to allocate workers"));
 return -1;
@@ -2221,6 +2231,11 @@ remoteReadConfigFile (struct qemud_serve
 
 if (remoteReadSaslAllowedUsernameList (conf, server, filename) < 0)
 goto free_and_fail;
+
+
+GET_CONF_INT (conf, filename, min_workers);
+GET_CONF_INT (conf, filename, max_workers);
+GET_CONF_INT (conf, filename, max_clients);
 
 virConfFree (conf);
 return 0;
diff --git a/qemud/test_libvirtd.aug b/qemud/test_libvirtd.aug
--- a/qemud/test_libvirtd.aug
+++ b/qemud/test_libvirtd.aug
@@ -227,6 +227,25 @@ sasl_allowed_username_list = [
   \"[EMAIL PROTECTED]",
   \"[EMAIL PROTECTED]"
 ]
+
+
+#
+#
+# Processing controls
+#
+
+# The maximum number of concurrent client connections to allow
+# over all sockets combined.
+max_clients = 20
+
+
+# The minimum limit sets the number of workers to start up
+# initially. If the number of active clients exceeds this,
+# then more threads are spawned, upto max_workers limit.
+# Typically you'd want max_workers to equal maximum number
+# of clients allowed
+min_workers = 

Re: [libvirt] PATCH: 25/28: Thread safety for libvirtd event loop

2008-11-30 Thread Daniel P. Berrange
This patch makes the event loop in the libvirtd daemon thread safe, and
re-entrant. This allows one thread to add/remove/update timers/file handle
watches while other thread is doing the poll. This sometimes requires that
we wakeup the main thread to make it see changes to the poll FD list. We
use the traditional self-pipe trick for this task.

 event.c |  168 ++--
 event.h |   14 +
 qemud.c |   10 +++
 qemud.h |3 +
 4 files changed, 167 insertions(+), 28 deletions(-)

Daniel

diff --git a/qemud/event.c b/qemud/event.c
--- a/qemud/event.c
+++ b/qemud/event.c
@@ -28,12 +28,16 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "qemud.h"
 #include "event.h"
 #include "memory.h"
+#include "util.h"
 
 #define EVENT_DEBUG(fmt, ...) qemudDebug("EVENT: " fmt, __VA_ARGS__)
+
+static int virEventInterruptLocked(void);
 
 /* State for a single file handle being monitored */
 struct virEventHandle {
@@ -63,6 +67,9 @@ struct virEventTimeout {
 
 /* State for the main event loop */
 struct virEventLoop {
+pthread_mutex_t lock;
+pthread_t leader;
+int wakeupfd[2];
 int handlesCount;
 int handlesAlloc;
 struct virEventHandle *handles;
@@ -80,6 +87,16 @@ static int nextWatch = 0;
 /* Unique ID for the next timer to be registered */
 static int nextTimer = 0;
 
+static void virEventLock(void)
+{
+pthread_mutex_lock(&eventLoop.lock);
+}
+
+static void virEventUnlock(void)
+{
+pthread_mutex_unlock(&eventLoop.lock);
+}
+
 /*
  * Register a callback for monitoring file handle events.
  * NB, it *must* be safe to call this from within a callback
@@ -89,17 +106,23 @@ int virEventAddHandleImpl(int fd, int ev
   virEventHandleCallback cb,
   void *opaque,
   virFreeCallback ff) {
+int watch;
 EVENT_DEBUG("Add handle %d %d %p %p", fd, events, cb, opaque);
+virEventLock();
 if (eventLoop.handlesCount == eventLoop.handlesAlloc) {
 EVENT_DEBUG("Used %d handle slots, adding %d more",
 eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
 if (VIR_REALLOC_N(eventLoop.handles,
-  (eventLoop.handlesAlloc + EVENT_ALLOC_EXTENT)) < 0)
+  (eventLoop.handlesAlloc + EVENT_ALLOC_EXTENT)) < 0) {
+virEventUnlock();
 return -1;
+}
 eventLoop.handlesAlloc += EVENT_ALLOC_EXTENT;
 }
 
-eventLoop.handles[eventLoop.handlesCount].watch = nextWatch++;
+watch = nextWatch++;
+
+eventLoop.handles[eventLoop.handlesCount].watch = watch;
 eventLoop.handles[eventLoop.handlesCount].fd = fd;
 eventLoop.handles[eventLoop.handlesCount].events =
  virEventHandleTypeToPollEvent(events);
@@ -110,11 +133,15 @@ int virEventAddHandleImpl(int fd, int ev
 
 eventLoop.handlesCount++;
 
-return nextWatch-1;
+virEventInterruptLocked();
+virEventUnlock();
+
+return watch;
 }
 
 void virEventUpdateHandleImpl(int watch, int events) {
 int i;
+virEventLock();
 for (i = 0 ; i < eventLoop.handlesCount ; i++) {
 if (eventLoop.handles[i].watch == watch) {
 eventLoop.handles[i].events =
@@ -122,6 +149,8 @@ void virEventUpdateHandleImpl(int watch,
 break;
 }
 }
+virEventInterruptLocked();
+virEventUnlock();
 }
 
 /*
@@ -133,6 +162,7 @@ int virEventRemoveHandleImpl(int watch) 
 int virEventRemoveHandleImpl(int watch) {
 int i;
 EVENT_DEBUG("Remove handle %d", watch);
+virEventLock();
 for (i = 0 ; i < eventLoop.handlesCount ; i++) {
 if (eventLoop.handles[i].deleted)
 continue;
@@ -140,9 +170,12 @@ int virEventRemoveHandleImpl(int watch) 
 if (eventLoop.handles[i].watch == watch) {
 EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
 eventLoop.handles[i].deleted = 1;
+virEventUnlock();
 return 0;
 }
 }
+virEventInterruptLocked();
+virEventUnlock();
 return -1;
 }
 
@@ -157,17 +190,21 @@ int virEventAddTimeoutImpl(int frequency
void *opaque,
virFreeCallback ff) {
 struct timeval now;
+int ret;
 EVENT_DEBUG("Adding timer %d with %d ms freq", nextTimer, frequency);
 if (gettimeofday(&now, NULL) < 0) {
 return -1;
 }
 
+virEventLock();
 if (eventLoop.timeoutsCount == eventLoop.timeoutsAlloc) {
 EVENT_DEBUG("Used %d timeout slots, adding %d more",
 eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT);
 if (VIR_REALLOC_N(eventLoop.timeouts,
-  (eventLoop.timeoutsAlloc + EVENT_ALLOC_EXTENT)) < 0)
+  (eventLoop.timeoutsAlloc + EVENT_ALLOC_EXTENT)) < 0) 
{
+virEventUnlock();
 return -1;
+}
 eventLoop.timeoutsAlloc += E

Re: [libvirt] PATCH: 23/28: Replace client linked list with array

2008-11-30 Thread Daniel P. Berrange
This replaces the linked list of 'struct qemud_client' instances with an
array instead, allowing easy fine grained per-client locking

 qemud.c |   43 ---
 qemud.h |4 +---
 2 files changed, 25 insertions(+), 22 deletions(-)


Daniel

diff --git a/qemud/qemud.c b/qemud/qemud.c
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -1151,6 +1151,12 @@ static int qemudDispatchServer(struct qe
 return -1;
 }
 
+if (VIR_REALLOC_N(server->clients, server->nclients+1) < 0) {
+qemudLog(QEMUD_ERR, "%s", _("Out of memory allocating clients"));
+close(fd);
+return -1;
+}
+
 /* Disable Nagle.  Unix sockets will ignore this. */
 setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
 sizeof no_slow_start);
@@ -1231,9 +1237,7 @@ static int qemudDispatchServer(struct qe
 }
 }
 
-client->next = server->clients;
-server->clients = client;
-server->nclients++;
+server->clients[server->nclients++] = client;
 
 return 0;
 
@@ -1248,19 +1252,19 @@ static int qemudDispatchServer(struct qe
 
 
 static void qemudDispatchClientFailure(struct qemud_server *server, struct 
qemud_client *client) {
-struct qemud_client *tmp = server->clients;
-struct qemud_client *prev = NULL;
-while (tmp) {
-if (tmp == client) {
-if (prev == NULL)
-server->clients = client->next;
-else
-prev->next = client->next;
-server->nclients--;
+int i, n = -1;
+for (i = 0 ; i < server->nclients ; i++) {
+if (server->clients[i] == client) {
+n = i;
 break;
 }
-prev = tmp;
-tmp = tmp->next;
+}
+if (n != -1) {
+if (n < (server->nclients-1))
+memmove(server->clients + n,
+server->clients + n + 1,
+server->nclients - (n + 1));
+server->nclients--;
 }
 
 virEventRemoveHandleImpl(client->watch);
@@ -1629,13 +1633,14 @@ static void
 static void
 qemudDispatchClientEvent(int watch, int fd, int events, void *opaque) {
 struct qemud_server *server = (struct qemud_server *)opaque;
-struct qemud_client *client = server->clients;
+struct qemud_client *client = NULL;
+int i;
 
-while (client) {
-if (client->watch == watch)
+for (i = 0 ; i < server->nclients ; i++) {
+if (server->clients[i]->watch == watch) {
+client = server->clients[i];
 break;
-
-client = client->next;
+}
 }
 
 if (!client)
diff --git a/qemud/qemud.h b/qemud/qemud.h
--- a/qemud/qemud.h
+++ b/qemud/qemud.h
@@ -133,8 +133,6 @@ struct qemud_client {
 
 /* back-pointer to our server */
 struct qemud_server *server;
-
-struct qemud_client *next;
 };
 
 #define QEMUD_CLIENT_MAGIC 0x7788aaee
@@ -155,7 +153,7 @@ struct qemud_server {
 int nsockets;
 struct qemud_socket *sockets;
 int nclients;
-struct qemud_client *clients;
+struct qemud_client **clients;
 int sigread;
 char logDir[PATH_MAX];
 unsigned int shutdown : 1;

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] PATCH: 21/28: Fill in locking stubs

2008-11-30 Thread Daniel P. Berrange
This patch fills in the previous stub methods for locking/unlocking 
internal objects. 

With the following methods return a locked object

  virDomainFindByID
  virDomainFindByName
  virDomainFindByUUID
  virDomainAssignDef

All the other methods accepting a virDomainObjPtr instance, require that
the object first be locked.

For virDomainDefPtr objects, if they are standalone, no locking is
required (hence why the Xen driver isn't touched in any of these patches).
If they are associated with a virDomainObjPtr though, this parent object
must be locked.

The same applies for virNetworkObjPtr, virStoragePoolObjPtr and the
virNodeDeviceObjPtr objects & their methods.

 domain_conf.c  |   40 
 domain_conf.h  |2 ++
 network_conf.c |   46 ++
 network_conf.h |2 ++
 node_device_conf.c |   28 +++-
 node_device_conf.h |2 ++
 storage_conf.c |   35 ---
 storage_conf.h |2 ++
 8 files changed, 141 insertions(+), 16 deletions(-)

Daniel

diff --git a/src/domain_conf.c b/src/domain_conf.c
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -151,10 +151,13 @@ virDomainObjPtr virDomainFindByID(const 
 {
 unsigned int i;
 
-for (i = 0 ; i < doms->count ; i++)
+for (i = 0 ; i < doms->count ; i++) {
+virDomainObjLock(doms->objs[i]);
 if (virDomainIsActive(doms->objs[i]) &&
 doms->objs[i]->def->id == id)
 return doms->objs[i];
+virDomainObjUnlock(doms->objs[i]);
+}
 
 return NULL;
 }
@@ -165,9 +168,12 @@ virDomainObjPtr virDomainFindByUUID(cons
 {
 unsigned int i;
 
-for (i = 0 ; i < doms->count ; i++)
+for (i = 0 ; i < doms->count ; i++) {
+virDomainObjLock(doms->objs[i]);
 if (!memcmp(doms->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
 return doms->objs[i];
+virDomainObjUnlock(doms->objs[i]);
+}
 
 return NULL;
 }
@@ -177,9 +183,12 @@ virDomainObjPtr virDomainFindByName(cons
 {
 unsigned int i;
 
-for (i = 0 ; i < doms->count ; i++)
+for (i = 0 ; i < doms->count ; i++) {
+virDomainObjLock(doms->objs[i]);
 if (STREQ(doms->objs[i]->def->name, name))
 return doms->objs[i];
+virDomainObjUnlock(doms->objs[i]);
+}
 
 return NULL;
 }
@@ -455,6 +464,8 @@ virDomainObjPtr virDomainAssignDef(virCo
 return NULL;
 }
 
+pthread_mutex_init(&domain->lock, NULL);
+virDomainObjLock(domain);
 domain->state = VIR_DOMAIN_SHUTOFF;
 domain->def = def;
 
@@ -475,8 +486,12 @@ void virDomainRemoveInactive(virDomainOb
 {
 unsigned int i;
 
+virDomainObjUnlock(dom);
+
 for (i = 0 ; i < doms->count ; i++) {
+virDomainObjLock(doms->objs[i]);
 if (doms->objs[i] == dom) {
+virDomainObjUnlock(doms->objs[i]);
 virDomainObjFree(doms->objs[i]);
 
 if (i < (doms->count - 1))
@@ -490,6 +505,7 @@ void virDomainRemoveInactive(virDomainOb
 
 break;
 }
+virDomainObjUnlock(doms->objs[i]);
 }
 
 }
@@ -3337,8 +3353,10 @@ int virDomainLoadAllConfigs(virConnectPt
   entry->d_name,
   notify,
   opaque);
-if (dom)
+if (dom) {
+virDomainObjUnlock(dom);
 dom->persistent = 1;
+}
 }
 
 closedir(dir);
@@ -3459,6 +3477,19 @@ const char *virDomainDefDefaultEmulator(
 }
 
 
+#ifdef HAVE_PTHREAD_H
+
+void virDomainObjLock(virDomainObjPtr obj)
+{
+pthread_mutex_lock(&obj->lock);
+}
+
+void virDomainObjUnlock(virDomainObjPtr obj)
+{
+pthread_mutex_unlock(&obj->lock);
+}
+
+#else
 void virDomainObjLock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
 {
 }
@@ -3466,5 +3497,6 @@ void virDomainObjUnlock(virDomainObjPtr 
 void virDomainObjUnlock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
 {
 }
+#endif
 
 #endif /* ! PROXY */
diff --git a/src/domain_conf.h b/src/domain_conf.h
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -454,6 +454,8 @@ typedef struct _virDomainObj virDomainOb
 typedef struct _virDomainObj virDomainObj;
 typedef virDomainObj *virDomainObjPtr;
 struct _virDomainObj {
+PTHREAD_MUTEX_T(lock);
+
 int stdin_fd;
 int stdout_fd;
 int stdout_watch;
diff --git a/src/network_conf.c b/src/network_conf.c
--- a/src/network_conf.c
+++ b/src/network_conf.c
@@ -58,9 +58,12 @@ virNetworkObjPtr virNetworkFindByUUID(co
 {
 unsigned int i;
 
-for (i = 0 ; i < nets->count ; i++)
+for (i = 0 ; i < nets->count ; i++) {
+virNetworkObjLock(nets->objs[i]);
 if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
 return nets->objs[i];
+virNetworkObjUnlock(nets->objs[i]);
+}
 
 return NULL;
 }
@@ -70,9 +73,12 @@ virNetworkObjPtr virNetworkFindByName(co
 {
 unsigned int i;
 
-for (i = 0 ; i < ne

Re: [libvirt] PATCH: 20/28: Thread safety for node device driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the node device driver thread safe. Almost.

There is on outstanding problem in that the 'reload' method is implemented
by just calling shutdown/startup. This causes the mutex we're locking on
to be free'd and re-allocated. I'll fix this up later.

 libvirt_sym.version.in |1 
 node_device.c  |   53 ++-
 node_device.h  |4 +
 node_device_conf.h |3 
 node_device_devkit.c   |   41 
 node_device_hal.c  |  166 +
 6 files changed, 199 insertions(+), 69 deletions(-)


Daniel

diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in
--- a/src/libvirt_sym.version.in
+++ b/src/libvirt_sym.version.in
@@ -509,6 +509,7 @@ [EMAIL PROTECTED]@ {
virNodeDeviceDefFormat;
virNodeDeviceObjLock;
virNodeDeviceObjUnlock;
+   virNodeDeviceAssignDef;
 
 
/* qparams.h */
diff --git a/src/node_device.c b/src/node_device.c
--- a/src/node_device.c
+++ b/src/node_device.c
@@ -29,7 +29,7 @@
 #include "virterror_internal.h"
 #include "datatypes.h"
 #include "memory.h"
-
+#include "logging.h"
 #include "node_device_conf.h"
 #include "node_device.h"
 
@@ -44,6 +44,17 @@ static int dev_has_cap(const virNodeDevi
 return 0;
 }
 
+
+void nodeDeviceLock(virDeviceMonitorStatePtr driver)
+{
+DEBUG("LOCK node %p", driver);
+pthread_mutex_lock(&driver->lock);
+}
+void nodeDeviceUnlock(virDeviceMonitorStatePtr driver)
+{
+DEBUG("UNLOCK node %p", driver);
+pthread_mutex_unlock(&driver->lock);
+}
 
 static int nodeNumOfDevices(virConnectPtr conn,
 const char *cap,
@@ -71,15 +82,24 @@ nodeListDevices(virConnectPtr conn,
 int ndevs = 0;
 unsigned int i;
 
-for (i = 0; i < driver->devs.count && ndevs < maxnames; i++)
+nodeDeviceLock(driver);
+for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
+virNodeDeviceObjLock(driver->devs.objs[i]);
 if (cap == NULL ||
-dev_has_cap(driver->devs.objs[i], cap))
-if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == 
NULL)
+dev_has_cap(driver->devs.objs[i], cap)) {
+if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == 
NULL) {
+virNodeDeviceObjUnlock(driver->devs.objs[i]);
 goto failure;
+}
+}
+virNodeDeviceObjUnlock(driver->devs.objs[i]);
+}
+nodeDeviceUnlock(driver);
 
 return ndevs;
 
  failure:
+nodeDeviceUnlock(driver);
 --ndevs;
 while (--ndevs >= 0)
 VIR_FREE(names[ndevs]);
@@ -94,7 +114,10 @@ static virNodeDevicePtr nodeDeviceLookup
 virNodeDeviceObjPtr obj;
 virNodeDevicePtr ret = NULL;
 
+nodeDeviceLock(driver);
 obj = virNodeDeviceFindByName(&driver->devs, name);
+nodeDeviceUnlock(driver);
+
 if (!obj) {
 virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE,
  "%s", _("no node device with matching name"));
@@ -104,6 +127,8 @@ static virNodeDevicePtr nodeDeviceLookup
 ret = virGetNodeDevice(conn, name);
 
 cleanup:
+if (obj)
+virNodeDeviceObjUnlock(obj);
 return ret;
 }
 
@@ -114,7 +139,10 @@ static char *nodeDeviceDumpXML(virNodeDe
 virNodeDeviceObjPtr obj;
 char *ret = NULL;
 
+nodeDeviceLock(driver);
 obj = virNodeDeviceFindByName(&driver->devs, dev->name);
+nodeDeviceUnlock(driver);
+
 if (!obj) {
 virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
   "%s", _("no node device with matching name"));
@@ -124,6 +152,8 @@ static char *nodeDeviceDumpXML(virNodeDe
 ret = virNodeDeviceDefFormat(dev->conn, obj->def);
 
 cleanup:
+if (obj)
+virNodeDeviceObjUnlock(obj);
 return ret;
 }
 
@@ -134,7 +164,10 @@ static char *nodeDeviceGetParent(virNode
 virNodeDeviceObjPtr obj;
 char *ret = NULL;
 
+nodeDeviceLock(driver);
 obj = virNodeDeviceFindByName(&driver->devs, dev->name);
+nodeDeviceUnlock(driver);
+
 if (!obj) {
 virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
   "%s", _("no node device with matching name"));
@@ -144,6 +177,8 @@ static char *nodeDeviceGetParent(virNode
 ret = strdup(obj->def->parent);
 
 cleanup:
+if (obj)
+virNodeDeviceObjUnlock(obj);
 return ret;
 }
 
@@ -156,7 +191,10 @@ static int nodeDeviceNumOfCaps(virNodeDe
 int ncaps = 0;
 int ret = -1;
 
+nodeDeviceLock(driver);
 obj = virNodeDeviceFindByName(&driver->devs, dev->name);
+nodeDeviceUnlock(driver);
+
 if (!obj) {
 virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
   "%s", _("no node device with matching name"));
@@ -168,6 +206,8 @@ static int nodeDeviceNumOfCaps(virNodeDe
 ret = ncaps;
 
 cleanup:
+if (obj)
+virNodeDeviceObjUnlock(obj);
 return r

Re: [libvirt] PATCH: 19/28: Reduce return paths for node device driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of return paths in the node device driver
methods

In doing this I noticed an annoying problem in the public API contract
for  virNodeDeviceGetParent. It returns a 'const char *', but the remote
driver is actually returning an malloc'd string requiring the caller to
free it, while the node_device driver is returning a const string the
caller must not free. Ideally we would not have the 'const' annotation
but changing that now is ABI change, so instead I work around it, by
making all drivers return a malloc'd string, but then caching this in
the virNodeDevicePtr object. This mallc'd string is then free'd when
the object is released. This allows us to work around the public API
contract problem

 datatypes.c   |1 
 datatypes.h   |1 
 libvirt.c |   14 
 node_device.c |   65 ++
 4 files changed, 54 insertions(+), 27 deletions(-)


Daniel

diff --git a/src/datatypes.c b/src/datatypes.c
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -861,6 +861,7 @@ virReleaseNodeDevice(virNodeDevicePtr de
 
 dev->magic = -1;
 VIR_FREE(dev->name);
+VIR_FREE(dev->parent);
 VIR_FREE(dev);
 
 DEBUG("unref connection %p %d", conn, conn->refs);
diff --git a/src/datatypes.h b/src/datatypes.h
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -199,6 +199,7 @@ struct _virNodeDevice {
 int refs;   /* reference count */
 virConnectPtr conn; /* pointer back to the connection */
 char *name; /* device name (unique on node) */
+char *parent;   /* parent device name */
 };
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5689,11 +5689,15 @@ const char *virNodeDeviceGetParent(virNo
 return NULL;
 }
 
-if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceGetParent)
-return dev->conn->deviceMonitor->deviceGetParent (dev);
-
-virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
-return NULL;
+if (!dev->parent) {
+if (dev->conn->deviceMonitor && 
dev->conn->deviceMonitor->deviceGetParent) {
+dev->parent = dev->conn->deviceMonitor->deviceGetParent (dev);
+} else {
+virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+return NULL;
+}
+}
+return dev->parent;
 }
 
 /**
diff --git a/src/node_device.c b/src/node_device.c
--- a/src/node_device.c
+++ b/src/node_device.c
@@ -91,66 +91,84 @@ static virNodeDevicePtr nodeDeviceLookup
const char *name)
 {
 virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
-virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, name);
+virNodeDeviceObjPtr obj;
+virNodeDevicePtr ret = NULL;
 
+obj = virNodeDeviceFindByName(&driver->devs, name);
 if (!obj) {
 virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE,
  "%s", _("no node device with matching name"));
-return NULL;
+goto cleanup;
 }
 
-return virGetNodeDevice(conn, name);
+ret = virGetNodeDevice(conn, name);
 
+cleanup:
+return ret;
 }
 
 static char *nodeDeviceDumpXML(virNodeDevicePtr dev,
unsigned int flags ATTRIBUTE_UNUSED)
 {
 virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
-virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, 
dev->name);
+virNodeDeviceObjPtr obj;
+char *ret = NULL;
 
+obj = virNodeDeviceFindByName(&driver->devs, dev->name);
 if (!obj) {
 virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
   "%s", _("no node device with matching name"));
-return NULL;
+goto cleanup;
 }
 
-return virNodeDeviceDefFormat(dev->conn, obj->def);
+ret = virNodeDeviceDefFormat(dev->conn, obj->def);
+
+cleanup:
+return ret;
 }
 
 
 static char *nodeDeviceGetParent(virNodeDevicePtr dev)
 {
 virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
-virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, 
dev->name);
+virNodeDeviceObjPtr obj;
+char *ret = NULL;
 
+obj = virNodeDeviceFindByName(&driver->devs, dev->name);
 if (!obj) {
 virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
   "%s", _("no node device with matching name"));
-return NULL;
+goto cleanup;
 }
 
-return obj->def->parent;
+ret = strdup(obj->def->parent);
+
+cleanup:
+return ret;
 }
 
 
 static int nodeDeviceNumOfCaps(virNodeDevicePtr dev)
 {
 virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
-virNodeDeviceObjPtr obj = virNodeDeviceFindByName(&driver->devs, 
dev->name);
+virNodeDeviceObjPtr obj;
 virNodeDevCapsDefPtr caps;
 int nca

Re: [libvirt] PATCH: 18/28: Thread safety for OpenVZ driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the OpenVZ driver thread safe

 openvz_conf.h   |2 +
 openvz_driver.c |  103 ++--
 2 files changed, 102 insertions(+), 3 deletions(-)

Daniel

diff --git a/src/openvz_conf.h b/src/openvz_conf.h
--- a/src/openvz_conf.h
+++ b/src/openvz_conf.h
@@ -53,6 +53,8 @@ enum { OPENVZ_WARN, OPENVZ_ERR };
 #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
 
 struct openvz_driver {
+PTHREAD_MUTEX_T(lock);
+
 virCapsPtr caps;
 virDomainObjList domains;
 int version;
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -66,6 +66,16 @@ static int openvzGetMaxVCPUs(virConnectP
 static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
 static int openvzDomainGetMaxVcpus(virDomainPtr dom);
 static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus);
+
+static void openvzDriverLock(struct openvz_driver *driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+
+static void openvzDriverUnlock(struct openvz_driver *driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
 
 struct openvz_driver ovz_driver;
 
@@ -159,7 +169,10 @@ static virDomainPtr openvzDomainLookupBy
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+openvzDriverLock(driver);
 vm = virDomainFindByID(&driver->domains, id);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -170,12 +183,16 @@ static virDomainPtr openvzDomainLookupBy
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
 static int openvzGetVersion(virConnectPtr conn, unsigned long *version) {
 struct  openvz_driver *driver = conn->privateData;
+openvzDriverLock(driver);
 *version = driver->version;
+openvzDriverUnlock(driver);
 return 0;
 }
 
@@ -185,7 +202,10 @@ static char *openvzGetOSType(virDomainPt
 virDomainObjPtr vm;
 char *ret = NULL;
 
+openvzDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -195,6 +215,8 @@ static char *openvzGetOSType(virDomainPt
 openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return ret;
 }
 
@@ -205,7 +227,10 @@ static virDomainPtr openvzDomainLookupBy
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+openvzDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, uuid);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -216,6 +241,8 @@ static virDomainPtr openvzDomainLookupBy
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
@@ -225,7 +252,10 @@ static virDomainPtr openvzDomainLookupBy
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+openvzDriverLock(driver);
 vm = virDomainFindByName(&driver->domains, name);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -236,6 +266,8 @@ static virDomainPtr openvzDomainLookupBy
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
@@ -245,7 +277,10 @@ static int openvzDomainGetInfo(virDomain
 virDomainObjPtr vm;
 int ret = -1;
 
+openvzDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
 "%s", _("no domain with matching uuid"));
@@ -270,6 +305,8 @@ static int openvzDomainGetInfo(virDomain
 ret = 0;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return ret;
 }
 
@@ -279,7 +316,10 @@ static char *openvzDomainDumpXML(virDoma
 virDomainObjPtr vm;
 char *ret = NULL;
 
+openvzDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
 "%s", _("no domain with matching uuid"));
@@ -289,6 +329,8 @@ static char *openvzDomainDumpXML(virDoma
 ret = virDomainDefFormat(dom->conn, vm->def, flags);
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return ret;
 }
 
@@ -312,7 +354,10 @@ static int openvzDomainShutdown(virDomai
 const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL};
 int ret = -1;
 
+openvzDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+openvzDriverUnlock(driver);
+
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
 "%s", _("no domain with matching uui

Re: [libvirt] PATCH: 17/28: Reduce return paths in OpenVZ driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of exit paths in the OpenVZ driver methods

 openvz_driver.c |  392 
 1 file changed, 224 insertions(+), 168 deletions(-)

Daniel

diff --git a/src/openvz_driver.c b/src/openvz_driver.c
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -155,96 +155,101 @@ static int openvzDomainDefineCmd(virConn
 
 static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
int id) {
-struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
+struct openvz_driver *driver = conn->privateData;
 virDomainObjPtr vm;
-virDomainPtr dom;
+virDomainPtr dom = NULL;
 
 vm = virDomainFindByID(&driver->domains, id);
-
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (!dom)
-return NULL;
+if (dom)
+dom->id = vm->def->id;
 
-dom->id = vm->def->id;
+cleanup:
 return dom;
 }
 
 static int openvzGetVersion(virConnectPtr conn, unsigned long *version) {
-struct  openvz_driver *driver = (struct openvz_driver *)conn->privateData;
+struct  openvz_driver *driver = conn->privateData;
 *version = driver->version;
 return 0;
 }
 
 static char *openvzGetOSType(virDomainPtr dom)
 {
-struct  openvz_driver *driver = (struct openvz_driver 
*)dom->conn->privateData;
-virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
-char *ret;
+struct  openvz_driver *driver = dom->conn->privateData;
+virDomainObjPtr vm;
+char *ret = NULL;
 
+vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 if (!(ret = strdup(vm->def->os.type)))
 openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
 
+cleanup:
 return ret;
 }
 
 
 static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
  const unsigned char *uuid) {
-struct  openvz_driver *driver = (struct openvz_driver *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid);
-virDomainPtr dom;
+struct  openvz_driver *driver = conn->privateData;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByUUID(&driver->domains, uuid);
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (!dom)
-return NULL;
+if (dom)
+dom->id = vm->def->id;
 
-dom->id = vm->def->id;
+cleanup:
 return dom;
 }
 
 static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
- const char *name) {
-struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByName(&driver->domains, name);
-virDomainPtr dom;
+ const char *name) {
+struct openvz_driver *driver = conn->privateData;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByName(&driver->domains, name);
 if (!vm) {
 openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (!dom)
-return NULL;
+if (dom)
+dom->id = vm->def->id;
 
-dom->id = vm->def->id;
+cleanup:
 return dom;
 }
 
 static int openvzDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info) {
-struct openvz_driver *driver = (struct openvz_driver 
*)dom->conn->privateData;
-virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+struct openvz_driver *driver = dom->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
 
+vm = virDomainFindByUUID(&driver->domains, dom->uuid);
 if (!vm) {
 openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
 "%s", _("no domain with matching uuid"));
-return -1;
+goto cleanup;
 }
 
 info->state = vm->state;
@@ -255,80 +260,110 @@ static int openvzDomainGetInfo(virDomain
 if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
 openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
 _("cannot read cputime for domain %d"), dom->id);
-return -1;
+goto cleanup;
 }
 }
 
 info->maxMem = vm->def->maxmem;
 info->memory = vm->def->memory;
 info->nrVirtCpu = vm->def->vcpus;
-return 0;
+ret = 0;
+
+cleanup:
+return ret;
 }
 
 
 static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
-struct openvz_driver *driver = (struct openvz_driver 
*

Re: [libvirt] PATCH: 16/28: Thread safety for storage driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the storage driver thread safe

 storage_conf.h   |2 
 storage_driver.c |  240 +--
 2 files changed, 202 insertions(+), 40 deletions(-)


Daniel

diff --git a/src/storage_conf.h b/src/storage_conf.h
--- a/src/storage_conf.h
+++ b/src/storage_conf.h
@@ -248,6 +248,8 @@ typedef virStorageDriverState *virStorag
 typedef virStorageDriverState *virStorageDriverStatePtr;
 
 struct _virStorageDriverState {
+PTHREAD_MUTEX_T(lock);
+
 virStoragePoolObjList pools;
 
 char *configDir;
diff --git a/src/storage_driver.c b/src/storage_driver.c
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -47,6 +47,14 @@ static virStorageDriverStatePtr driverSt
 
 static int storageDriverShutdown(void);
 
+static void storageDriverLock(virStorageDriverStatePtr driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+static void storageDriverUnlock(virStorageDriverStatePtr driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
 
 static void
 storageDriverAutostart(virStorageDriverStatePtr driver) {
@@ -100,6 +108,9 @@ storageDriverStartup(void) {
 if (VIR_ALLOC(driverState) < 0)
 return -1;
 
+pthread_mutex_init(&driverState->lock, NULL);
+storageDriverLock(driverState);
+
 if (!uid) {
 if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
 goto out_of_memory;
@@ -132,8 +143,7 @@ storageDriverStartup(void) {
   "%s/storage/autostart", base) == -1)
 goto out_of_memory;
 
-free(base);
-base = NULL;
+VIR_FREE(base);
 
 /*
 if (virStorageLoadDriverConfig(driver, driverConf) < 0) {
@@ -145,19 +155,19 @@ storageDriverStartup(void) {
 if (virStoragePoolLoadAllConfigs(NULL,
  &driverState->pools,
  driverState->configDir,
- driverState->autostartDir) < 0) {
-storageDriverShutdown();
-return -1;
-}
+ driverState->autostartDir) < 0)
+goto error;
 storageDriverAutostart(driverState);
 
+storageDriverUnlock(driverState);
 return 0;
 
- out_of_memory:
+out_of_memory:
 storageLog("virStorageStartup: out of memory");
-free(base);
-free(driverState);
-driverState = NULL;
+error:
+VIR_FREE(base);
+storageDriverUnlock(driverState);
+storageDriverShutdown();
 return -1;
 }
 
@@ -172,11 +182,13 @@ storageDriverReload(void) {
 if (!driverState)
 return -1;
 
+storageDriverLock(driverState);
 virStoragePoolLoadAllConfigs(NULL,
  &driverState->pools,
  driverState->configDir,
  driverState->autostartDir);
 storageDriverAutostart(driverState);
+storageDriverUnlock(driverState);
 
 return 0;
 }
@@ -191,19 +203,22 @@ static int
 static int
 storageDriverActive(void) {
 unsigned int i;
+int active = 0;
 
 if (!driverState)
 return 0;
 
-/* If we've any active networks or guests, then we
- * mark this driver as active
- */
-for (i = 0 ; i < driverState->pools.count ; i++)
+storageDriverLock(driverState);
+
+for (i = 0 ; i < driverState->pools.count ; i++) {
+virStoragePoolObjLock(driverState->pools.objs[i]);
 if (virStoragePoolObjIsActive(driverState->pools.objs[i]))
-return 1;
+active = 1;
+virStoragePoolObjUnlock(driverState->pools.objs[i]);
+}
 
-/* Otherwise we're happy to deal with a shutdown */
-return 0;
+storageDriverUnlock(driverState);
+return active;
 }
 
 /**
@@ -218,6 +233,7 @@ storageDriverShutdown(void) {
 if (!driverState)
 return -1;
 
+storageDriverLock(driverState);
 /* shutdown active pools */
 for (i = 0 ; i < driverState->pools.count ; i++) {
 virStoragePoolObjPtr pool = driverState->pools.objs[i];
@@ -244,6 +260,7 @@ storageDriverShutdown(void) {
 
 VIR_FREE(driverState->configDir);
 VIR_FREE(driverState->autostartDir);
+storageDriverUnlock(driverState);
 VIR_FREE(driverState);
 
 return 0;
@@ -258,7 +275,10 @@ storagePoolLookupByUUID(virConnectPtr co
 virStoragePoolObjPtr pool;
 virStoragePoolPtr ret = NULL;
 
+storageDriverLock(driver);
 pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
+storageDriverUnlock(driver);
+
 if (!pool) {
 virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL,
   "%s", _("no pool with matching uuid"));
@@ -268,6 +288,8 @@ storagePoolLookupByUUID(virConnectPtr co
 ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
 
 cleanup:
+if (pool)
+virStoragePoolObjUnlock(pool);
 return ret;
 }
 
@@ -278,7 +300,10 @@ storagePoolLookupByName(virConnectPtr co
 virStoragePoolObjPtr pool;
 virStoragePoolPtr ret = NULL;
 
+storageDriverLo

Re: [libvirt] PATCH: 15/28: Reduce return points for storage driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of return points in the storage driver
methods

 storage_driver.c |  570 ++-
 1 file changed, 313 insertions(+), 257 deletions(-)

Daniel

diff --git a/src/storage_driver.c b/src/storage_driver.c
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -254,36 +254,40 @@ static virStoragePoolPtr
 static virStoragePoolPtr
 storagePoolLookupByUUID(virConnectPtr conn,
 const unsigned char *uuid) {
-virStorageDriverStatePtr driver =
-(virStorageDriverStatePtr)conn->storagePrivateData;
-virStoragePoolObjPtr pool = virStoragePoolObjFindByUUID(&driver->pools, 
uuid);
-virStoragePoolPtr ret;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
+virStoragePoolObjPtr pool;
+virStoragePoolPtr ret = NULL;
 
+pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
 if (!pool) {
 virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL,
   "%s", _("no pool with matching uuid"));
-return NULL;
+goto cleanup;
 }
 
 ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+
+cleanup:
 return ret;
 }
 
 static virStoragePoolPtr
 storagePoolLookupByName(virConnectPtr conn,
 const char *name) {
-virStorageDriverStatePtr driver =
-(virStorageDriverStatePtr)conn->storagePrivateData;
-virStoragePoolObjPtr pool = virStoragePoolObjFindByName(&driver->pools, 
name);
-virStoragePoolPtr ret;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
+virStoragePoolObjPtr pool;
+virStoragePoolPtr ret = NULL;
 
+pool = virStoragePoolObjFindByName(&driver->pools, name);
 if (!pool) {
 virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL,
   "%s", _("no pool with matching name"));
-return NULL;
+goto cleanup;
 }
 
 ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
+
+cleanup:
 return ret;
 }
 
@@ -311,8 +315,7 @@ storageClose(virConnectPtr conn) {
 
 static int
 storageNumPools(virConnectPtr conn) {
-virStorageDriverStatePtr driver
-= (virStorageDriverStatePtr)conn->storagePrivateData;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
 unsigned int i, nactive = 0;
 
 for (i = 0 ; i < driver->pools.count ; i++)
@@ -326,8 +329,7 @@ storageListPools(virConnectPtr conn,
 storageListPools(virConnectPtr conn,
  char **const names,
  int nnames) {
-virStorageDriverStatePtr driver =
-(virStorageDriverStatePtr)conn->storagePrivateData;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
 int got = 0, i;
 
 for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
@@ -353,8 +355,7 @@ storageListPools(virConnectPtr conn,
 
 static int
 storageNumDefinedPools(virConnectPtr conn) {
-virStorageDriverStatePtr driver
-= (virStorageDriverStatePtr)conn->storagePrivateData;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
 unsigned int i, nactive = 0;
 
 for (i = 0 ; i < driver->pools.count ; i++)
@@ -368,8 +369,7 @@ storageListDefinedPools(virConnectPtr co
 storageListDefinedPools(virConnectPtr conn,
 char **const names,
 int nnames) {
-virStorageDriverStatePtr driver
-= (virStorageDriverStatePtr)conn->storagePrivateData;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
 int got = 0, i;
 
 for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
@@ -401,19 +401,21 @@ storageFindPoolSources(virConnectPtr con
 {
 int backend_type;
 virStorageBackendPtr backend;
+char *ret = NULL;
 
 backend_type = virStoragePoolTypeFromString(type);
 if (backend_type < 0)
-return NULL;
+goto cleanup;
 
 backend = virStorageBackendForType(backend_type);
 if (backend == NULL)
-return NULL;
+goto cleanup;
 
 if (backend->findPoolSources)
-return backend->findPoolSources(conn, srcSpec, flags);
+ret = backend->findPoolSources(conn, srcSpec, flags);
 
-return NULL;
+cleanup:
+return ret;
 }
 
 
@@ -421,46 +423,47 @@ storagePoolCreate(virConnectPtr conn,
 storagePoolCreate(virConnectPtr conn,
   const char *xml,
   unsigned int flags ATTRIBUTE_UNUSED) {
-virStorageDriverStatePtr driver =
-(virStorageDriverStatePtr )conn->storagePrivateData;
+virStorageDriverStatePtr driver = conn->storagePrivateData;
 virStoragePoolDefPtr def;
 virStoragePoolObjPtr pool;
-virStoragePoolPtr ret;
+virStoragePoolPtr ret = NULL;
 virStorageBackendPtr backend;
 
 if (!(def = virStoragePoolDefParse(conn, xml, NULL)))
-return NULL;
+goto cleanup;
 
-if (virStoragePoolObjFindByUUID(&driver->pools, def->uuid) ||
-virStoragePoolObjFindByN

Re: [libvirt] PATCH: 14/28: Thread safety for network driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the network driver thread safe, following the pattern of
the earlier patches

 network_driver.c |  136 ++-
 1 file changed, 125 insertions(+), 11 deletions(-)

Daniel

diff --git a/src/network_driver.c b/src/network_driver.c
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -59,6 +59,8 @@
 
 /* Main driver state */
 struct network_driver {
+PTHREAD_MUTEX_T(lock);
+
 virNetworkObjList networks;
 
 iptablesContext *iptables;
@@ -67,6 +69,16 @@ struct network_driver {
 char *networkAutostartDir;
 char *logDir;
 };
+
+
+static void networkDriverLock(struct network_driver *driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+static void networkDriverUnlock(struct network_driver *driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
 
 static int networkShutdown(void);
 
@@ -95,6 +107,7 @@ networkAutostartConfigs(struct network_d
 unsigned int i;
 
 for (i = 0 ; i < driver->networks.count ; i++) {
+virNetworkObjLock(driver->networks.objs[i]);
 if (driver->networks.objs[i]->autostart &&
 !virNetworkIsActive(driver->networks.objs[i]) &&
 networkStartNetworkDaemon(NULL, driver, driver->networks.objs[i]) 
< 0) {
@@ -103,6 +116,7 @@ networkAutostartConfigs(struct network_d
driver->networks.objs[i]->def->name,
err ? err->message : NULL);
 }
+virNetworkObjUnlock(driver->networks.objs[i]);
 }
 }
 
@@ -119,6 +133,9 @@ networkStartup(void) {
 
 if (VIR_ALLOC(driverState) < 0)
 goto error;
+
+pthread_mutex_init(&driverState->lock, NULL);
+networkDriverLock(driverState);
 
 if (!uid) {
 if (asprintf(&driverState->logDir,
@@ -165,6 +182,8 @@ networkStartup(void) {
 
 networkAutostartConfigs(driverState);
 
+networkDriverUnlock(driverState);
+
 return 0;
 
 out_of_memory:
@@ -172,6 +191,9 @@ out_of_memory:
   "%s", _("networkStartup: out of memory\n"));
 
 error:
+if (driverState)
+networkDriverUnlock(driverState);
+
 VIR_FREE(base);
 networkShutdown();
 return -1;
@@ -188,6 +210,7 @@ networkReload(void) {
 if (!driverState)
 return 0;
 
+networkDriverLock(driverState);
 virNetworkLoadAllConfigs(NULL,
  &driverState->networks,
  driverState->networkConfigDir,
@@ -200,7 +223,7 @@ networkReload(void) {
 }
 
 networkAutostartConfigs(driverState);
-
+networkDriverUnlock(driverState);
 return 0;
 }
 
@@ -220,12 +243,15 @@ networkActive(void) {
 if (!driverState)
 return 0;
 
+networkDriverLock(driverState);
 for (i = 0 ; i < driverState->networks.count ; i++) {
 virNetworkObjPtr net = driverState->networks.objs[i];
+virNetworkObjLock(net);
 if (virNetworkIsActive(net))
 active = 1;
+virNetworkObjUnlock(net);
 }
-
+networkDriverUnlock(driverState);
 return active;
 }
 
@@ -241,12 +267,16 @@ networkShutdown(void) {
 if (!driverState)
 return -1;
 
+networkDriverLock(driverState);
+
 /* shutdown active networks */
 for (i = 0 ; i < driverState->networks.count ; i++) {
 virNetworkObjPtr net = driverState->networks.objs[i];
+virNetworkObjLock(net);
 if (virNetworkIsActive(net))
 networkShutdownNetworkDaemon(NULL, driverState,
  driverState->networks.objs[i]);
+virNetworkObjUnlock(net);
 }
 
 /* free inactive networks */
@@ -260,6 +290,8 @@ networkShutdown(void) {
 brShutdown(driverState->brctl);
 if (driverState->iptables)
 iptablesContextFree(driverState->iptables);
+
+networkDriverUnlock(driverState);
 
 VIR_FREE(driverState);
 
@@ -801,10 +833,6 @@ static int networkShutdownNetworkDaemon(
 network->newDef = NULL;
 }
 
-if (!network->configFile)
-virNetworkRemoveInactive(&driver->networks,
- network);
-
 return 0;
 }
 
@@ -815,7 +843,9 @@ static virNetworkPtr networkLookupByUUID
 virNetworkObjPtr network;
 virNetworkPtr ret = NULL;
 
+networkDriverLock(driver);
 network = virNetworkFindByUUID(&driver->networks, uuid);
+networkDriverUnlock(driver);
 if (!network) {
 networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
  "%s", _("no network with matching uuid"));
@@ -825,6 +855,8 @@ static virNetworkPtr networkLookupByUUID
 ret = virGetNetwork(conn, network->def->name, network->def->uuid);
 
 cleanup:
+if (network)
+virNetworkObjUnlock(network);
 return ret;
 }
 
@@ -834,7 +866,9 @@ static virNetworkPtr networkLookupByName
 virNetworkObjPtr network;
 virNetworkPtr ret = NULL;
 
+networkDriverLock(driver);
 network = virNetworkFindByName(&driver->networks, name);
+networkDriverUnlock

Re: [libvirt] PATCH: 13/28: Reduce return points in network driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of return points in the network driver
methods

 network_driver.c |  275 +++
 1 file changed, 159 insertions(+), 116 deletions(-)

Daniel

diff --git a/src/network_driver.c b/src/network_driver.c
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -118,7 +118,7 @@ networkStartup(void) {
 char *base = NULL;
 
 if (VIR_ALLOC(driverState) < 0)
-return -1;
+goto error;
 
 if (!uid) {
 if (asprintf(&driverState->logDir,
@@ -160,19 +160,20 @@ networkStartup(void) {
 if (virNetworkLoadAllConfigs(NULL,
  &driverState->networks,
  driverState->networkConfigDir,
- driverState->networkAutostartDir) < 0) {
-networkShutdown();
-return -1;
-}
+ driverState->networkAutostartDir) < 0)
+goto error;
+
 networkAutostartConfigs(driverState);
 
 return 0;
 
- out_of_memory:
+out_of_memory:
 networkLog (NETWORK_ERR,
   "%s", _("networkStartup: out of memory\n"));
+
+error:
 VIR_FREE(base);
-VIR_FREE(driverState);
+networkShutdown();
 return -1;
 }
 
@@ -214,16 +215,18 @@ static int
 static int
 networkActive(void) {
 unsigned int i;
+int active = 0;
 
 if (!driverState)
 return 0;
 
-for (i = 0 ; i < driverState->networks.count ; i++)
-if (virNetworkIsActive(driverState->networks.objs[i]))
-return 1;
+for (i = 0 ; i < driverState->networks.count ; i++) {
+virNetworkObjPtr net = driverState->networks.objs[i];
+if (virNetworkIsActive(net))
+active = 1;
+}
 
-/* Otherwise we're happy to deal with a shutdown */
-return 0;
+return active;
 }
 
 /**
@@ -239,10 +242,12 @@ networkShutdown(void) {
 return -1;
 
 /* shutdown active networks */
-for (i = 0 ; i < driverState->networks.count ; i++)
-if (virNetworkIsActive(driverState->networks.objs[i]))
+for (i = 0 ; i < driverState->networks.count ; i++) {
+virNetworkObjPtr net = driverState->networks.objs[i];
+if (virNetworkIsActive(net))
 networkShutdownNetworkDaemon(NULL, driverState,
  driverState->networks.objs[i]);
+}
 
 /* free inactive networks */
 virNetworkObjListFree(&driverState->networks);
@@ -804,35 +809,42 @@ static int networkShutdownNetworkDaemon(
 }
 
 
-static virNetworkPtr networkLookupByUUID(virConnectPtr conn ATTRIBUTE_UNUSED,
-  const unsigned char *uuid) {
-struct network_driver *driver = (struct network_driver 
*)conn->networkPrivateData;
-virNetworkObjPtr network = virNetworkFindByUUID(&driver->networks, uuid);
-virNetworkPtr net;
+static virNetworkPtr networkLookupByUUID(virConnectPtr conn,
+ const unsigned char *uuid) {
+struct network_driver *driver = conn->networkPrivateData;
+virNetworkObjPtr network;
+virNetworkPtr ret = NULL;
 
+network = virNetworkFindByUUID(&driver->networks, uuid);
 if (!network) {
 networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
  "%s", _("no network with matching uuid"));
-return NULL;
+goto cleanup;
 }
 
-net = virGetNetwork(conn, network->def->name, network->def->uuid);
-return net;
+ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+return ret;
 }
-static virNetworkPtr networkLookupByName(virConnectPtr conn ATTRIBUTE_UNUSED,
-  const char *name) {
-struct network_driver *driver = (struct network_driver 
*)conn->networkPrivateData;
-virNetworkObjPtr network = virNetworkFindByName(&driver->networks, name);
-virNetworkPtr net;
 
+static virNetworkPtr networkLookupByName(virConnectPtr conn,
+ const char *name) {
+struct network_driver *driver = conn->networkPrivateData;
+virNetworkObjPtr network;
+virNetworkPtr ret = NULL;
+
+network = virNetworkFindByName(&driver->networks, name);
 if (!network) {
 networkReportError(conn, NULL, NULL, VIR_ERR_NO_NETWORK,
  "%s", _("no network with matching name"));
-return NULL;
+goto cleanup;
 }
 
-net = virGetNetwork(conn, network->def->name, network->def->uuid);
-return net;
+ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+return ret;
 }
 
 static virDrvOpenStatus networkOpenNetwork(virConnectPtr conn,
@@ -852,7 +864,7 @@ static int networkCloseNetwork(virConnec
 
 static int networkNumNetworks(virConnectPtr conn) {
 int nactive = 0, i;
-struct network_driver *driver = (struct network_driver 
*)conn->networkPrivateData;
+struct network_driver *d

Re: [libvirt] PATCH: 12/28: Thread safety for UML driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the UML driver thread safe

 uml_conf.h   |2 
 uml_driver.c |  209 +++
 2 files changed, 172 insertions(+), 39 deletions(-)

Daniel

diff --git a/src/uml_conf.h b/src/uml_conf.h
--- a/src/uml_conf.h
+++ b/src/uml_conf.h
@@ -39,6 +39,8 @@
 
 /* Main driver state */
 struct uml_driver {
+PTHREAD_MUTEX_T(lock);
+
 unsigned int umlVersion;
 int nextvmid;
 
diff --git a/src/uml_driver.c b/src/uml_driver.c
--- a/src/uml_driver.c
+++ b/src/uml_driver.c
@@ -73,6 +73,15 @@ static int umlShutdown(void);
 #define DEBUG0(msg) VIR_DEBUG(__FILE__, "%s", msg)
 
 #define umlLog(level, msg...) fprintf(stderr, msg)
+
+static void umlDriverLock(struct uml_driver *driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+static void umlDriverUnlock(struct uml_driver *driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
 
 
 static int umlOpenMonitor(virConnectPtr conn,
@@ -288,13 +297,16 @@ umlStartup(void) {
 if (VIR_ALLOC(uml_driver) < 0)
 return -1;
 
+pthread_mutex_init(¨_driver->lock, NULL);
+umlDriverLock(uml_driver);
+
 /* Don't have a dom0 so start from 1 */
 uml_driver->nextvmid = 1;
 
 if (!(pw = getpwuid(uid))) {
 umlLog(UML_ERR, _("Failed to find user record for uid '%d': %s\n"),
uid, strerror(errno));
-goto out_nouid;
+goto error;
 }
 
 if (!uid) {
@@ -338,49 +350,45 @@ umlStartup(void) {
 
 if ((uml_driver->inotifyFD = inotify_init()) < 0) {
 umlLog(UML_ERR, "%s", _("cannot initialize inotify"));
-goto out_nouid;
+goto error;
 }
 
 if (virFileMakePath(uml_driver->monitorDir) < 0) {
 umlLog(UML_ERR, _("Failed to create monitor directory %s: %s"),
uml_driver->monitorDir, strerror(errno));
-umlShutdown();
-return -1;
+goto error;
 }
 
 if ((uml_driver->inotifyWatch =
  inotify_add_watch(uml_driver->inotifyFD,
uml_driver->monitorDir,
-   IN_CREATE | IN_MODIFY | IN_DELETE)) < 0) {
-umlShutdown();
-return -1;
-}
+   IN_CREATE | IN_MODIFY | IN_DELETE)) < 0)
+goto error;
 
 if (virEventAddHandle(uml_driver->inotifyFD, POLLIN,
-  umlInotifyEvent, uml_driver, NULL) < 0) {
-umlShutdown();
-return -1;
-}
+  umlInotifyEvent, uml_driver, NULL) < 0)
+goto error;
 
 if (virDomainLoadAllConfigs(NULL,
 uml_driver->caps,
 ¨_driver->domains,
 uml_driver->configDir,
 uml_driver->autostartDir,
-NULL, NULL) < 0) {
-umlShutdown();
-return -1;
-}
+NULL, NULL) < 0)
+goto error;
+
 umlAutostartConfigs(uml_driver);
 
+umlDriverUnlock(uml_driver);
 return 0;
 
- out_of_memory:
+out_of_memory:
 umlLog (UML_ERR,
   "%s", _("umlStartup: out of memory\n"));
- out_nouid:
+error:
 VIR_FREE(base);
-VIR_FREE(uml_driver);
+umlDriverUnlock(uml_driver);
+umlShutdown();
 return -1;
 }
 
@@ -395,6 +403,7 @@ umlReload(void) {
 if (!uml_driver)
 return 0;
 
+umlDriverLock(uml_driver);
 virDomainLoadAllConfigs(NULL,
 uml_driver->caps,
 ¨_driver->domains,
@@ -403,6 +412,7 @@ umlReload(void) {
 NULL, NULL);
 
 umlAutostartConfigs(uml_driver);
+umlDriverUnlock(uml_driver);
 
 return 0;
 }
@@ -418,16 +428,21 @@ static int
 static int
 umlActive(void) {
 unsigned int i;
+int active = 0;
 
 if (!uml_driver)
 return 0;
 
-for (i = 0 ; i < uml_driver->domains.count ; i++)
+umlDriverLock(uml_driver);
+for (i = 0 ; i < uml_driver->domains.count ; i++) {
+virDomainObjLock(uml_driver->domains.objs[i]);
 if (virDomainIsActive(uml_driver->domains.objs[i]))
-return 1;
+active = 1;
+virDomainObjUnlock(uml_driver->domains.objs[i]);
+}
+umlDriverUnlock(uml_driver);
 
-/* Otherwise we're happy to deal with a shutdown */
-return 0;
+return active;
 }
 
 /**
@@ -442,6 +457,7 @@ umlShutdown(void) {
 if (!uml_driver)
 return -1;
 
+umlDriverLock(uml_driver);
 virEventRemoveHandle(uml_driver->inotifyWatch);
 close(uml_driver->inotifyFD);
 virCapabilitiesFree(uml_driver->caps);
@@ -451,9 +467,6 @@ umlShutdown(void) {
 virDomainObjPtr dom = uml_driver->domains.objs[i];
 if (virDomainIsActive(dom))
 umlShutdownVMDaemon(NULL, uml_driver, dom);
-if (!dom->persistent)
-virDomainRemoveInactive(¨_driver->domains,
-dom);
 }
 
 virDomainObjListFree(

Re: [libvirt] PATCH: 11/28: Reduce return points for UML driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of return points in the UML driver methods

 Makefile.maint   |1 
 src/uml_driver.c |  410 ---
 2 files changed, 243 insertions(+), 168 deletions(-)


Daniel

diff --git a/Makefile.maint b/Makefile.maint
--- a/Makefile.maint
+++ b/Makefile.maint
@@ -355,6 +355,7 @@ msg_gen_function += virDomainReportError
 msg_gen_function += virDomainReportError
 msg_gen_function += virReportErrorHelper
 msg_gen_function += lxcError
+msg_gen_function += umlError
 
 # Uncomment the following and run "make syntax-check" to see diagnostics
 # that are not yet marked for translation, but that need to be rewritten
diff --git a/src/uml_driver.c b/src/uml_driver.c
--- a/src/uml_driver.c
+++ b/src/uml_driver.c
@@ -883,7 +883,7 @@ static virDrvOpenStatus umlOpen(virConne
 }
 
 static int umlClose(virConnectPtr conn) {
-/*struct uml_driver *driver = (struct uml_driver *)conn->privateData;*/
+/*struct uml_driver *driver = conn->privateData;*/
 
 conn->privateData = NULL;
 
@@ -904,11 +904,9 @@ static char *umlGetCapabilities(virConne
 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
 char *xml;
 
-if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) {
+if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
 umlReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
  "%s", _("failed to allocate space for capabilities support"));
-return NULL;
-}
 
 return xml;
 }
@@ -922,11 +920,12 @@ umlNodeGetCellsFreeMemory(virConnectPtr 
 int maxCells)
 {
 int n, lastCell, numCells;
+int ret = -1;
 
 if (numa_available() < 0) {
 umlReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
  "%s", _("NUMA not supported on this host"));
-return -1;
+goto cleanup;
 }
 lastCell = startCell + maxCells - 1;
 if (lastCell > numa_max_node())
@@ -937,22 +936,27 @@ umlNodeGetCellsFreeMemory(virConnectPtr 
 if (numa_node_size64(n, &mem) < 0) {
 umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
  "%s", _("Failed to query NUMA free memory"));
-return -1;
+goto cleanup;
 }
 freeMems[numCells++] = mem;
 }
-return numCells;
+ret = numCells;
+
+cleanup:
+return ret;
 }
 
 static unsigned long long
 umlNodeGetFreeMemory (virConnectPtr conn)
 {
 unsigned long long freeMem = 0;
+unsigned long long ret = -1;
 int n;
+
 if (numa_available() < 0) {
 umlReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
  "%s", _("NUMA not supported on this host"));
-return -1;
+goto cleanup;
 }
 
 for (n = 0 ; n <= numa_max_node() ; n++) {
@@ -960,12 +964,14 @@ umlNodeGetFreeMemory (virConnectPtr conn
 if (numa_node_size64(n, &mem) < 0) {
 umlReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
  "%s", _("Failed to query NUMA free memory"));
-return -1;
+goto cleanup;
 }
 freeMem += mem;
 }
+ret = freeMem;
 
-return freeMem;
+cleanup:
+return ret;
 }
 
 #endif
@@ -1009,46 +1015,57 @@ static virDomainPtr umlDomainLookupByID(
 static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
   int id) {
 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByID(&driver->domains, id);
-virDomainPtr dom;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByID(&driver->domains, id);
 if (!vm) {
 umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 if (dom) dom->id = vm->def->id;
+
+cleanup:
 return dom;
 }
+
 static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
 const unsigned char *uuid) {
 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid);
-virDomainPtr dom;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByUUID(&driver->domains, uuid);
 if (!vm) {
 umlReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
 if (dom) dom->id = vm->def->id;
+
+cleanup:
 return dom;
 }
+
 static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
 const char *name) {
 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByName(&driver->domains, name);
-virDomainPtr dom;
+virDo

Re: [libvirt] PATCH: 10/28: Thread safety for LXC driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the LXC driver thread safe following the same pattern
as the Test/QEMU drivers

 lxc_conf.h   |2 
 lxc_driver.c |  187 +++
 2 files changed, 151 insertions(+), 38 deletions(-)

Daniel

diff --git a/src/lxc_conf.h b/src/lxc_conf.h
--- a/src/lxc_conf.h
+++ b/src/lxc_conf.h
@@ -36,6 +36,8 @@
 
 typedef struct __lxc_driver lxc_driver_t;
 struct __lxc_driver {
+PTHREAD_MUTEX_T(lock);
+
 virCapsPtr caps;
 
 virDomainObjList domains;
diff --git a/src/lxc_driver.c b/src/lxc_driver.c
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -54,6 +54,16 @@ static lxc_driver_t *lxc_driver = NULL;
 static lxc_driver_t *lxc_driver = NULL;
 
 /* Functions */
+
+static void lxcDriverLock(lxc_driver_t *driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+static void lxcDriverUnlock(lxc_driver_t *driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
+
 
 static int lxcProbe(void)
 {
@@ -107,7 +117,10 @@ static virDomainPtr lxcDomainLookupByID(
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+lxcDriverLock(driver);
 vm = virDomainFindByID(&driver->domains, id);
+lxcDriverUnlock(driver);
+
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -118,6 +131,8 @@ static virDomainPtr lxcDomainLookupByID(
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
@@ -128,7 +143,10 @@ static virDomainPtr lxcDomainLookupByUUI
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+lxcDriverLock(driver);
 vm = virDomainFindByUUID(&driver->domains, uuid);
+lxcDriverUnlock(driver);
+
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -139,6 +157,8 @@ static virDomainPtr lxcDomainLookupByUUI
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
@@ -149,7 +169,9 @@ static virDomainPtr lxcDomainLookupByNam
 virDomainObjPtr vm;
 virDomainPtr dom = NULL;
 
+lxcDriverLock(driver);
 vm = virDomainFindByName(&driver->domains, name);
+lxcDriverUnlock(driver);
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
 goto cleanup;
@@ -160,6 +182,8 @@ static virDomainPtr lxcDomainLookupByNam
 dom->id = vm->def->id;
 
 cleanup:
+if (vm)
+virDomainObjUnlock(vm);
 return dom;
 }
 
@@ -167,9 +191,14 @@ static int lxcListDomains(virConnectPtr 
 lxc_driver_t *driver = conn->privateData;
 int got = 0, i;
 
-for (i = 0 ; i < driver->domains.count && got < nids ; i++)
+lxcDriverLock(driver);
+for (i = 0 ; i < driver->domains.count && got < nids ; i++) {
+virDomainObjLock(driver->domains.objs[i]);
 if (virDomainIsActive(driver->domains.objs[i]))
 ids[got++] = driver->domains.objs[i]->def->id;
+virDomainObjUnlock(driver->domains.objs[i]);
+}
+lxcDriverUnlock(driver);
 
 return got;
 }
@@ -178,9 +207,14 @@ static int lxcNumDomains(virConnectPtr c
 lxc_driver_t *driver = conn->privateData;
 int n = 0, i;
 
-for (i = 0 ; i < driver->domains.count ; i++)
+lxcDriverLock(driver);
+for (i = 0 ; i < driver->domains.count ; i++) {
+virDomainObjLock(driver->domains.objs[i]);
 if (virDomainIsActive(driver->domains.objs[i]))
 n++;
+virDomainObjUnlock(driver->domains.objs[i]);
+}
+lxcDriverUnlock(driver);
 
 return n;
 }
@@ -190,21 +224,27 @@ static int lxcListDefinedDomains(virConn
 lxc_driver_t *driver = conn->privateData;
 int got = 0, i;
 
+lxcDriverLock(driver);
 for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
+virDomainObjLock(driver->domains.objs[i]);
 if (!virDomainIsActive(driver->domains.objs[i])) {
 if (!(names[got++] = strdup(driver->domains.objs[i]->def->name))) {
 lxcError(conn, NULL, VIR_ERR_NO_MEMORY,
  "%s", _("failed to allocate space for VM name 
string"));
+virDomainObjUnlock(driver->domains.objs[i]);
 goto cleanup;
 }
 }
+virDomainObjUnlock(driver->domains.objs[i]);
 }
+lxcDriverUnlock(driver);
 
 return got;
 
  cleanup:
 for (i = 0 ; i < got ; i++)
 VIR_FREE(names[i]);
+lxcDriverUnlock(driver);
 return -1;
 }
 
@@ -213,9 +253,14 @@ static int lxcNumDefinedDomains(virConne
 lxc_driver_t *driver = conn->privateData;
 int n = 0, i;
 
-for (i = 0 ; i < driver->domains.count ; i++)
+lxcDriverLock(driver);
+for (i = 0 ; i < driver->domains.count ; i++) {
+virDomainObjLock(driver->domains.objs[i]);
 if (!virDomainIsActive(driver->domains.objs[i]))
 n++;
+virDomainObjUnlock(driver->domains.objs[i]);
+}
+lxcDriverUnlock(driver);
 
 return n;
 }
@@ -226,9 +271,10 @@ static virDomainPtr l

Re: [libvirt] PATCH: 9/28: Reduce exit paths for LXC driver

2008-11-30 Thread Daniel P. Berrange
This patch reduces the number of exit paths in the LXC driver, much like
the earlier patches for other drivers

 lxc_driver.c |  278 ---
 1 file changed, 154 insertions(+), 124 deletions(-)

Daniel

diff --git a/src/lxc_driver.c b/src/lxc_driver.c
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -103,65 +103,68 @@ static virDomainPtr lxcDomainLookupByID(
 static virDomainPtr lxcDomainLookupByID(virConnectPtr conn,
 int id)
 {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByID(&driver->domains, id);
-virDomainPtr dom;
+lxc_driver_t *driver = conn->privateData;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByID(&driver->domains, id);
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (dom) {
+if (dom)
 dom->id = vm->def->id;
-}
 
+cleanup:
 return dom;
 }
 
 static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn,
   const unsigned char *uuid)
 {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid);
-virDomainPtr dom;
+lxc_driver_t *driver = conn->privateData;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByUUID(&driver->domains, uuid);
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (dom) {
+if (dom)
 dom->id = vm->def->id;
-}
 
+cleanup:
 return dom;
 }
 
 static virDomainPtr lxcDomainLookupByName(virConnectPtr conn,
   const char *name)
 {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
-virDomainObjPtr vm = virDomainFindByName(&driver->domains, name);
-virDomainPtr dom;
+lxc_driver_t *driver = conn->privateData;
+virDomainObjPtr vm;
+virDomainPtr dom = NULL;
 
+vm = virDomainFindByName(&driver->domains, name);
 if (!vm) {
 lxcError(conn, NULL, VIR_ERR_NO_DOMAIN, NULL);
-return NULL;
+goto cleanup;
 }
 
 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
-if (dom) {
+if (dom)
 dom->id = vm->def->id;
-}
 
+cleanup:
 return dom;
 }
 
 static int lxcListDomains(virConnectPtr conn, int *ids, int nids) {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
+lxc_driver_t *driver = conn->privateData;
 int got = 0, i;
 
 for (i = 0 ; i < driver->domains.count && got < nids ; i++)
@@ -170,8 +173,9 @@ static int lxcListDomains(virConnectPtr 
 
 return got;
 }
+
 static int lxcNumDomains(virConnectPtr conn) {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
+lxc_driver_t *driver = conn->privateData;
 int n = 0, i;
 
 for (i = 0 ; i < driver->domains.count ; i++)
@@ -183,7 +187,7 @@ static int lxcNumDomains(virConnectPtr c
 
 static int lxcListDefinedDomains(virConnectPtr conn,
  char **const names, int nnames) {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
+lxc_driver_t *driver = conn->privateData;
 int got = 0, i;
 
 for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
@@ -206,7 +210,7 @@ static int lxcListDefinedDomains(virConn
 
 
 static int lxcNumDefinedDomains(virConnectPtr conn) {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
+lxc_driver_t *driver = conn->privateData;
 int n = 0, i;
 
 for (i = 0 ; i < driver->domains.count ; i++)
@@ -220,86 +224,91 @@ static int lxcNumDefinedDomains(virConne
 
 static virDomainPtr lxcDomainDefine(virConnectPtr conn, const char *xml)
 {
-lxc_driver_t *driver = (lxc_driver_t *)conn->privateData;
-virDomainDefPtr def;
+lxc_driver_t *driver = conn->privateData;
+virDomainDefPtr def = NULL;
 virDomainObjPtr vm;
-virDomainPtr dom;
+virDomainPtr dom = NULL;
 
 if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
-return NULL;
+goto cleanup;
 
 if ((def->nets != NULL) && !(driver->have_netns)) {
 lxcError(conn, NULL, VIR_ERR_NO_SUPPORT,
  "%s", _("System lacks NETNS support"));
-virDomainDefFree(def);
-return NULL;
+goto cleanup;
 }
 
-if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) {
-virDomainDefFree(def);
-return NULL;
-}
+if (!(vm = virDomainAssignDef(conn, &driver->domains, def)))
+goto cleanup;
+def = NULL;
 vm->persistent = 1;
 
 if (virDomainSaveConfig(conn,
 driver->configDir,
   

Re: [libvirt] PATCH: 8/28: Thread safety for domain events code

2008-11-30 Thread Daniel P. Berrange
This patch adds thread safety to the domain events processing code of
the QEMU driver. This entailed rather a large refactoring of the domain
events code and its quite complicated to explain.

- A convenient helper is added for creating event queues

virDomainEventQueuePtr virDomainEventQueueNew(void);

- Convenient helpers are added for creating virDomainEventPtr instances
  from a variety of sources - each driver has different needs

   virDomainEventPtr virDomainEventNew(int id, const char *name, const unsigned 
char *uuid, int type, int detail);
   virDomainEventPtr virDomainEventNewFromDom(virDomainPtr dom, int type, int 
detail);
   virDomainEventPtr virDomainEventNewFromObj(virDomainObjPtr obj, int type, 
int detail);
   virDomainEventPtr virDomainEventNewFromDef(virDomainDefPtr def, int type, 
int detail);

- The virDomainEvent struct held a reference to a virDomainPtr object.
  This is replaced with a direct triple (id, name, uuid), avoiding the
  need to instantiate virDomainPtr objects deep inside the QEMU code.

- The virDomainEventQueuePush() method is changed to take a
  virDomainEventPtr object, rather than a virDomainPtr object

These last two changes are important to allow safe re-entrancy of the 
event dispatch process. The virDomainEventPtr instance can be allocated
within a critical section lockde on the virDomainObjPtr instance, while
the event is queued outside the critical section, while only the driver
lock is held. Without this we'd have to hold the per-driver lock over
a much larger block of code which hurts concurrancy.

The QEMU driver cannot directly dispatch events, instead we have to
follow the remote driver and maintain a queue of pending events, and
use a timer to flush them. Again this is neccessary to improve
concurrency & provide safe re-entrancy.

Since we have two driver maintaining queues of evnts I add more 
helper functions to allow code sharing

 - Send a single vent to a list of callbacks:

  void virDomainEventDispatch(virDomainEventPtr event,
  virDomainEventCallbackListPtr cbs,
  virDomainEventDispatchFunc dispatch,
  void *opaque);

 - Send a set of queued events to a list of callbacks

  void virDomainEventQueueDispatch(virDomainEventQueuePtr queue,
   virDomainEventCallbackListPtr cbs,
   virDomainEventDispatchFunc dispatch,
   void *opaque);

The virDomainEventDispatchFunc is what is invoked to finally dispatch
a single event, to a single registered callback. The default impl just
invokes the callback directly. The QEMU driver, however, uses a wrapper
which first releases its driver lock, invokes the callback, and then
re-aquires the lock.

As a further complication it is not safe for virDomainEventUnregister
to actually remove the callback from the list directly. Instead we
add a helper that simply marks it as removed, and then actually 
purge it from a safe point in the code, when its guarenteed that the
driver isn't in the middle of dispatching.

As well as making the QEMU driver thread safe, this also takes the
opportunity to refactor the Xen / remote drivers to use more helpers


 domain_event.c |  191 +++
 domain_event.h |   51 ++-
 libvirt_sym.version.in |   16 ++
 qemu_conf.h|3 
 qemu_driver.c  |  339 +++--
 remote_internal.c  |   93 +
 xen_inotify.c  |  135 ++-
 xen_unified.c  |   30 +---
 xen_unified.h  |4 
 xs_internal.c  |   56 +++-
 10 files changed, 594 insertions(+), 324 deletions(-)

Daniel

diff --git a/src/domain_event.c b/src/domain_event.c
--- a/src/domain_event.c
+++ b/src/domain_event.c
@@ -125,6 +125,49 @@ virDomainEventCallbackListRemoveConn(vir
 return 0;
 }
 
+int virDomainEventCallbackListMarkDelete(virConnectPtr conn,
+ virDomainEventCallbackListPtr cbList,
+ virConnectDomainEventCallback 
callback)
+{
+int i;
+for (i = 0 ; i < cbList->count ; i++) {
+if (cbList->callbacks[i]->conn == conn &&
+cbList->callbacks[i]->cb == callback) {
+cbList->callbacks[i]->deleted = 1;
+return 0;
+}
+}
+return -1;
+}
+
+int virDomainEventCallbackListPurgeMarked(virDomainEventCallbackListPtr cbList)
+{
+int old_count = cbList->count;
+int i;
+for (i = 0 ; i < cbList->count ; i++) {
+if (cbList->callbacks[i]->deleted) {
+virFreeCallback freecb = cbList->callbacks[i]->freecb;
+if (freecb)
+(*freecb)(cbList->callbacks[i]->opaque);
+virUnrefConnect(cbList->callbacks[i]->conn);
+VIR_FREE(cbList->callbacks[i]);
+
+if (i < (cbList->count - 1))
+  

Re: [libvirt] PATCH: 7/28: Thread safety for QEMU driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the QEMU driver threadsafe with the exception of the
domain events code.

 qemu_conf.h   |2 
 qemu_driver.c |  458 ++
 2 files changed, 337 insertions(+), 123 deletions(-)


Daniel

diff --git a/src/qemu_conf.h b/src/qemu_conf.h
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -51,6 +51,8 @@ enum qemud_cmd_flags {
 
 /* Main driver state */
 struct qemud_driver {
+PTHREAD_MUTEX_T(lock);
+
 unsigned int qemuVersion;
 int nextvmid;
 
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -76,6 +76,15 @@ static int qemudShutdown(void);
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
 
+static void qemuDriverLock(struct qemud_driver *driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+static void qemuDriverUnlock(struct qemud_driver *driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
+
 static int qemudSetCloseExec(int fd) {
 int flags;
 if ((flags = fcntl(fd, F_GETFD)) < 0)
@@ -141,6 +150,7 @@ qemudAutostartConfigs(struct qemud_drive
 
 for (i = 0 ; i < driver->domains.count ; i++) {
 virDomainObjPtr vm = driver->domains.objs[i];
+virDomainObjLock(vm);
 if (vm->autostart &&
 !virDomainIsActive(vm)) {
 int ret = qemudStartVMDaemon(NULL, driver, vm, NULL);
@@ -154,6 +164,7 @@ qemudAutostartConfigs(struct qemud_drive
  VIR_DOMAIN_EVENT_STARTED_BOOTED);
 }
 }
+virDomainObjUnlock(vm);
 }
 }
 
@@ -172,12 +183,15 @@ qemudStartup(void) {
 if (VIR_ALLOC(qemu_driver) < 0)
 return -1;
 
+pthread_mutex_init(&qemu_driver->lock, NULL);
+qemuDriverLock(qemu_driver);
+
 /* Don't have a dom0 so start from 1 */
 qemu_driver->nextvmid = 1;
 
 /* Init callback list */
 if(VIR_ALLOC(qemu_driver->domainEventCallbacks) < 0)
-return -1;
+goto out_of_memory;
 
 if (!uid) {
 if (asprintf(&qemu_driver->logDir,
@@ -190,7 +204,7 @@ qemudStartup(void) {
 if (!(pw = getpwuid(uid))) {
 qemudLog(QEMUD_ERR, _("Failed to find user record for uid '%d': 
%s\n"),
  uid, strerror(errno));
-goto out_nouid;
+goto error;
 }
 
 if (asprintf(&qemu_driver->logDir,
@@ -229,20 +243,22 @@ qemudStartup(void) {
 &qemu_driver->domains,
 qemu_driver->configDir,
 qemu_driver->autostartDir,
-NULL, NULL) < 0) {
-qemudShutdown();
-return -1;
-}
+NULL, NULL) < 0)
+goto error;
 qemudAutostartConfigs(qemu_driver);
 
-return 0;
-
- out_of_memory:
+qemuDriverUnlock(qemu_driver);
+
+return 0;
+
+out_of_memory:
 qemudLog (QEMUD_ERR,
   "%s", _("qemudStartup: out of memory\n"));
- out_nouid:
+error:
+if (qemu_driver)
+qemuDriverUnlock(qemu_driver);
 VIR_FREE(base);
-VIR_FREE(qemu_driver);
+qemudShutdown();
 return -1;
 }
 
@@ -267,6 +283,7 @@ qemudReload(void) {
 if (!qemu_driver)
 return 0;
 
+qemuDriverLock(qemu_driver);
 virDomainLoadAllConfigs(NULL,
 qemu_driver->caps,
 &qemu_driver->domains,
@@ -275,6 +292,7 @@ qemudReload(void) {
 qemudNotifyLoadDomain, qemu_driver);
 
 qemudAutostartConfigs(qemu_driver);
+qemuDriverUnlock(qemu_driver);
 
 return 0;
 }
@@ -290,16 +308,18 @@ static int
 static int
 qemudActive(void) {
 unsigned int i;
+int active = 0;
 
 if (!qemu_driver)
 return 0;
 
+qemuDriverLock(qemu_driver);
 for (i = 0 ; i < qemu_driver->domains.count ; i++)
 if (virDomainIsActive(qemu_driver->domains.objs[i]))
-return 1;
-
-/* Otherwise we're happy to deal with a shutdown */
-return 0;
+active = 1;
+
+qemuDriverUnlock(qemu_driver);
+return active;
 }
 
 /**
@@ -314,16 +334,16 @@ qemudShutdown(void) {
 if (!qemu_driver)
 return -1;
 
+qemuDriverLock(qemu_driver);
 virCapabilitiesFree(qemu_driver->caps);
 
 /* shutdown active VMs */
 for (i = 0 ; i < qemu_driver->domains.count ; i++) {
 virDomainObjPtr dom = qemu_driver->domains.objs[i];
+virDomainObjLock(dom);
 if (virDomainIsActive(dom))
 qemudShutdownVMDaemon(NULL, qemu_driver, dom);
-if (!dom->persistent)
-virDomainRemoveInactive(&qemu_driver->domains,
-dom);
+virDomainObjUnlock(dom);
 }
 
 virDomainObjListFree(&qemu_driver->domains);
@@ -340,6 +360,7 @@ qemudShutdown(void) {
 if (qemu_driver->brctl)
 brShutdown(qemu_driver->brctl);
 
+qemuDriverUnlock(qemu_driver);
 VIR_FREE(qemu_driver);
 
 return 0

Re: [libvirt] PATCH: 5/28: Stub out node device APIs in test driver

2008-11-30 Thread Daniel P. Berrange
When adding the node device APIs we never added a stub for the test driver,
so  the test driver was connecting to the daemon for node device APIS,
which rather defeats the purpose of the test driver. This patch doesn't
implement the node device APIs, just stubs out the open/close methods
so we don't call into the daemon. 

 test.c |   27 +++
 1 file changed, 27 insertions(+)


Daniel

diff --git a/src/test.c b/src/test.c
--- a/src/test.c
+++ b/src/test.c
@@ -3220,6 +3220,22 @@ cleanup:
 }
 
 
+static virDrvOpenStatus testDevMonOpen(virConnectPtr conn,
+   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+   int flags ATTRIBUTE_UNUSED) {
+if (STRNEQ(conn->driver->name, "Test"))
+return VIR_DRV_OPEN_DECLINED;
+
+conn->devMonPrivateData = conn->privateData;
+return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int testDevMonClose(virConnectPtr conn) {
+conn->devMonPrivateData = NULL;
+return 0;
+}
+
+
 static virDriver testDriver = {
 VIR_DRV_TEST,
 "Test",
@@ -3343,6 +3359,14 @@ static virStorageDriver testStorageDrive
 .volGetPath = testStorageVolumeGetPath,
 };
 
+static virDeviceMonitor testDevMonitor = {
+.name = "Test",
+.open = testDevMonOpen,
+.close = testDevMonClose,
+};
+
+
+
 /**
  * testRegister:
  *
@@ -3357,5 +3381,8 @@ testRegister(void)
 return -1;
 if (virRegisterStorageDriver(&testStorageDriver) < 0)
 return -1;
+if (virRegisterDeviceMonitor(&testDevMonitor) < 0)
+return -1;
+
 return 0;
 }

-- 
|: 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 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] PATCH: 4/28: Thread safety for test driver

2008-11-30 Thread Daniel P. Berrange
This patch makes the test driver thread safe, adding a global driver lock,
and the neccessary locking calls on domain/network/storagepool objects.

You'll notice there are many calls to

 virDomainObjUnlock

but very few corresponding  calls to

   virDomainObjLock

This is because the contract of  virDomainFindByUUID declares that the
object it returns is already locked.

Methods which create / delete virDomainObj instances have to keep the
global driver lock held for their whole duration, but others can drop
it immediately after getting the virDomainObjPtr instance.

 src/test.c  |  460 +++-
 tests/virsh-all |1 
 2 files changed, 420 insertions(+), 41 deletions(-)

Daniel

diff --git a/src/test.c b/src/test.c
--- a/src/test.c
+++ b/src/test.c
@@ -58,6 +58,8 @@ typedef struct _testCell *testCellPtr;
 #define MAX_CELLS 128
 
 struct _testConn {
+PTHREAD_MUTEX_T(lock);
+
 char path[PATH_MAX];
 int nextDomID;
 virCapsPtr caps;
@@ -90,6 +92,16 @@ static const virNodeInfo defaultNodeInfo
 #define testError(conn, code, fmt...)   \
 virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
+
+static void testDriverLock(testConnPtr driver)
+{
+pthread_mutex_lock(&driver->lock);
+}
+
+static void testDriverUnlock(testConnPtr driver)
+{
+pthread_mutex_unlock(&driver->lock);
+}
 
 static virCapsPtr
 testBuildCapabilities(virConnectPtr conn) {
@@ -200,6 +212,8 @@ static int testOpenDefault(virConnectPtr
 return VIR_DRV_OPEN_ERROR;
 }
 conn->privateData = privconn;
+pthread_mutex_init(&privconn->lock, NULL);
+testDriverLock(privconn);
 
 if (gettimeofday(&tv, NULL) < 0) {
 testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of 
day"));
@@ -232,6 +246,7 @@ static int testOpenDefault(virConnectPtr
 domobj->def->id = privconn->nextDomID++;
 domobj->state = VIR_DOMAIN_RUNNING;
 domobj->persistent = 1;
+virDomainObjUnlock(domobj);
 
 if (!(netdef = virNetworkDefParseString(conn, defaultNetworkXML)))
 goto error;
@@ -241,6 +256,7 @@ static int testOpenDefault(virConnectPtr
 }
 netobj->active = 1;
 netobj->persistent = 1;
+virNetworkObjUnlock(netobj);
 
 if (!(pooldef = virStoragePoolDefParse(conn, defaultPoolXML, NULL)))
 goto error;
@@ -250,10 +266,15 @@ static int testOpenDefault(virConnectPtr
 virStoragePoolDefFree(pooldef);
 goto error;
 }
-if (testStoragePoolObjSetDefaults(poolobj) == -1)
+
+if (testStoragePoolObjSetDefaults(poolobj) == -1) {
+virStoragePoolObjUnlock(poolobj);
 goto error;
+}
 poolobj->active = 1;
+virStoragePoolObjUnlock(poolobj);
 
+testDriverUnlock(privconn);
 return VIR_DRV_OPEN_SUCCESS;
 
 error:
@@ -261,6 +282,7 @@ error:
 virNetworkObjListFree(&privconn->networks);
 virStoragePoolObjListFree(&privconn->pools);
 virCapabilitiesFree(privconn->caps);
+testDriverUnlock(privconn);
 VIR_FREE(privconn);
 return VIR_DRV_OPEN_ERROR;
 }
@@ -307,6 +329,8 @@ static int testOpenFromFile(virConnectPt
 return VIR_DRV_OPEN_ERROR;
 }
 conn->privateData = privconn;
+pthread_mutex_init(&privconn->lock, NULL);
+testDriverLock(privconn);
 
 if (!(privconn->caps = testBuildCapabilities(conn)))
 goto error;
@@ -445,6 +469,7 @@ static int testOpenFromFile(virConnectPt
 dom->state = VIR_DOMAIN_RUNNING;
 dom->def->id = privconn->nextDomID++;
 dom->persistent = 1;
+virDomainObjUnlock(dom);
 }
 if (domains != NULL)
 VIR_FREE(domains);
@@ -478,8 +503,8 @@ static int testOpenFromFile(virConnectPt
 virNetworkDefFree(def);
 goto error;
 }
-
 net->persistent = 1;
+virNetworkObjUnlock(net);
 }
 if (networks != NULL)
 VIR_FREE(networks);
@@ -529,15 +554,19 @@ static int testOpenFromFile(virConnectPt
 goto error;
 }
 
-if (testStoragePoolObjSetDefaults(pool) == -1)
+if (testStoragePoolObjSetDefaults(pool) == -1) {
+virStoragePoolObjUnlock(pool);
 goto error;
+}
 pool->active = 1;
+virStoragePoolObjUnlock(pool);
 }
 if (pools != NULL)
 VIR_FREE(pools);
 
 xmlXPathFreeContext(ctxt);
 xmlFreeDoc(xml);
+testDriverUnlock(privconn);
 
 return (0);
 
@@ -552,6 +581,7 @@ static int testOpenFromFile(virConnectPt
 virDomainObjListFree(&privconn->domains);
 virNetworkObjListFree(&privconn->networks);
 virStoragePoolObjListFree(&privconn->pools);
+testDriverUnlock(privconn);
 VIR_FREE(privconn);
 conn->privateData = NULL;
 return VIR_DRV_OPEN_ERROR;
@@ -598,11 +628,12 @@ static int testClose(virConnectPtr conn)
 static int testClose(virConnectPtr conn)
 {
 testConnPtr privconn = conn->p

[libvirt] KVM/qemu: problems with autostart of vms with non-bridged nets

2008-11-30 Thread Gerd von Egidy
Hi,

I'm using libvirt 0.5.0 to manage my kvm domains. Everything works fine except 
autostarting vms which use a network device not directly bridged to hw. I 
have the following net defined (and set to autostart):


  local
  7ec7a457-0b8e-4670-3b4a-2d0914288daa
  
  

  

  


When a vm using this net is autostarted I get the following error:

libvir: error : invalid connection pointer in virNetworkLookupByName
libvir: QEMU error : internal error Network 'local' not found
Failed to autostart VM 'testlocalnet': internal error Network 'local' not 
found

I took a dive into the code and found two problems causing this:

1. initialization order: 

qemuStateDriver is registered (and thus initialized) before 
networkStateDriver. This means the network is not up yet when qemu does it's 
autostart.

I could fix this with the attached patch.

2. missing virConnectPtr during autostart of the vm:

in src/qemu_driver.c:145, qemudAutostartConfigs() you can find this call:
int ret = qemudStartVMDaemon(NULL, driver, vm, NULL);

This means virConnectPtr conn is NULL within qemudStartVMDaemon(). 
Following the calls:
qemudStartVMDaemon()
-> qemudBuildCommandLine()
-> qemudNetworkIfaceConnect()
-> virNetworkLookupByName()

virNetworkLookupByName bails out if called with invalid virConnectPtr. This 
means starting this vm fails.

Currently I'm not familiar enough with the libvirt structures to come up with 
an idea how to fix this. 

Could anybody with a deeper knowledge of the code take a look at this? Thank 
you very much.

Kind regards,

Gerd


diff -r -u libvirt-0.5.0.orig/qemud/qemud.c libvirt-0.5.0/qemud/qemud.c
--- libvirt-0.5.0.orig/qemud/qemud.c2008-11-21 13:47:32.0 +0100
+++ libvirt-0.5.0/qemud/qemud.c 2008-11-30 21:27:06.0 +0100
@@ -761,22 +761,13 @@
  * If they try to use a open a connection for a module that
  * is not loaded they'll get a suitable error at that point
  */
-virDriverLoadModule("qemu");
-virDriverLoadModule("lxc");
-virDriverLoadModule("uml");
 virDriverLoadModule("network");
 virDriverLoadModule("storage");
 virDriverLoadModule("nodedev");
+virDriverLoadModule("qemu");
+virDriverLoadModule("lxc");
+virDriverLoadModule("uml");
 #else
-#ifdef WITH_QEMU
-qemuRegister();
-#endif
-#ifdef WITH_LXC
-lxcRegister();
-#endif
-#ifdef WITH_UML
-umlRegister();
-#endif
 #ifdef WITH_NETWORK
 networkRegister();
 #endif
@@ -786,6 +777,15 @@
 #if defined(HAVE_HAL) || defined(HAVE_DEVKIT)
 nodedevRegister();
 #endif
+#ifdef WITH_QEMU
+qemuRegister();
+#endif
+#ifdef WITH_LXC
+lxcRegister();
+#endif
+#ifdef WITH_UML
+umlRegister();
+#endif
 #endif
 
 virEventRegisterImpl(virEventAddHandleImpl,
-- 
Address (better: trap) for people I really don't want to get mail from:
[EMAIL PROTECTED]

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] PATCH: 2/28: Kill off macros in test driver

2008-11-30 Thread Daniel P. Berrange

The test driver has alot of convenience macros for for fetching the private
internal object impls from the public API parameters. Unfortunately these
rather obscure/hide code flow & variable accesses in the test driver, making
it hard to determine whether a method is thread safe. So this patch removes
all the macros, bringing this driver inline with the style of the other
drivers

 test.c |  899 -
 1 file changed, 670 insertions(+), 229 deletions(-)

Daniel

diff --git a/src/test.c b/src/test.c
--- a/src/test.c
+++ b/src/test.c
@@ -86,80 +86,22 @@ static const virNodeInfo defaultNodeInfo
 2,
 };
 
-#define GET_DOMAIN(dom, ret)\
-testConnPtr privconn;   \
-virDomainObjPtr privdom;\
-\
-privconn = (testConnPtr)dom->conn->privateData; \
-do {\
-if ((privdom = virDomainFindByName(&privconn->domains,   \
-(dom)->name)) == NULL) {\
-testError((dom)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);  \
-return (ret);   \
-}   \
-} while (0)
 
-#define GET_NETWORK(net, ret)   \
-testConnPtr privconn;   \
-virNetworkObjPtr privnet;   \
-\
-privconn = (testConnPtr)net->conn->privateData; \
-do {\
-if ((privnet = virNetworkFindByName(&privconn->networks,\
-(net)->name)) == NULL) {\
-testError((net)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);  \
-return (ret);   \
-}   \
-} while (0)
 
-#define GET_POOL(pool, ret) \
-testConnPtr privconn;   \
-virStoragePoolObjPtr privpool;  \
-\
-privconn = (testConnPtr)pool->conn->privateData;\
-do {\
-if ((privpool = virStoragePoolObjFindByName(&privconn->pools,   \
-(pool)->name)) == NULL) {\
-testError((pool)->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); \
-return (ret);   \
-}   \
-} while (0)
 
-#define GET_POOL_FROM_VOL(vol, ret) \
-GET_POOL(testStoragePoolLookupByName((virConnectPtr)\
- vol->conn, \
- vol->pool), ret)
 
-#define GET_VOL(vol, pool, ret) \
-virStorageVolDefPtr privvol;\
-\
-privvol = virStorageVolDefFindByName(pool, vol->name);  \
-do {\
-if (!privvol) { \
-testError(vol->conn, VIR_ERR_INVALID_STORAGE_VOL,   \
-  _("no storage vol with matching name '%s'"),  \
-  vol->name);   \
-return (ret);   \
-}   \
-} while (0) \
 
-
-#define GET_CONNECTION(conn)\
-testConnPtr privconn;   \
-\
-privconn = (testConnPtr)conn->privateData;
-
-#define POOL_IS_ACTIVE(pool, ret)   \
-if (!virStoragePoolObjIsActive(pool)) { \
-testError(obj->conn, VIR_ERR_INTERNAL_ERROR,\
-  _("storage pool '%s' is not active"), pool->def->name); \
-   return (ret)

Re: [libvirt] PATCH: 1/28: Stubs for object locking APIs

2008-11-30 Thread Daniel P. Berrange
To facilitate later patches this introduces lock & unlock API calls for
each internal object which are just no-ops. Once all the drivers are
updated to call this at appropriate places, the stubs will be filled
out with actual locking impls. This ensures each intermediate patch
still results in a functional system

 domain_conf.c  |8 
 domain_conf.h  |2 ++
 libvirt_sym.version.in |8 
 network_conf.c |8 
 network_conf.h |3 +++
 node_device_conf.c |8 
 node_device_conf.h |3 +++
 storage_conf.c |9 +
 storage_conf.h |3 +++
 9 files changed, 52 insertions(+)

Daniel

diff --git a/src/domain_conf.c b/src/domain_conf.c
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -3459,4 +3459,12 @@ const char *virDomainDefDefaultEmulator(
 }
 
 
+void virDomainObjLock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
+
+void virDomainObjUnlock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
+
 #endif /* ! PROXY */
diff --git a/src/domain_conf.h b/src/domain_conf.h
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -591,6 +591,8 @@ const char *virDomainDefDefaultEmulator(
 virDomainDefPtr def,
 virCapsPtr caps);
 
+void virDomainObjLock(virDomainObjPtr obj);
+void virDomainObjUnlock(virDomainObjPtr obj);
 
 VIR_ENUM_DECL(virDomainVirt)
 VIR_ENUM_DECL(virDomainBoot)
diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in
--- a/src/libvirt_sym.version.in
+++ b/src/libvirt_sym.version.in
@@ -373,6 +373,8 @@ [EMAIL PROTECTED]@ {
virDomainSoundModelTypeToString;
virDomainVirtTypeToString;
virDomainFSDefFree;
+   virDomainObjLock;
+   virDomainObjUnlock;
 
 
/* domain_event.h */
@@ -477,6 +479,8 @@ [EMAIL PROTECTED]@ {
virNetworkDefParseNode;
virNetworkRemoveInactive;
virNetworkSaveConfig;
+   virNetworkObjLock;
+   virNetworkObjUnlock;
 
 
/* nodeinfo.h */
@@ -491,6 +495,8 @@ [EMAIL PROTECTED]@ {
virNodeDeviceDefFree;
virNodeDevCapsDefFree;
virNodeDeviceDefFormat;
+   virNodeDeviceObjLock;
+   virNodeDeviceObjUnlock;
 
 
/* qparams.h */
@@ -544,6 +550,8 @@ [EMAIL PROTECTED]@ {
virStoragePoolFormatFileSystemNetTypeToString;
virStorageVolFormatFileSystemTypeToString;
virStoragePoolTypeFromString;
+   virStoragePoolObjLock;
+   virStoragePoolObjUnlock;
 
 
/* util.h */
diff --git a/src/network_conf.c b/src/network_conf.c
--- a/src/network_conf.c
+++ b/src/network_conf.c
@@ -811,3 +811,11 @@ int virNetworkDeleteConfig(virConnectPtr
 
 return 0;
 }
+
+void virNetworkObjLock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
+
+void virNetworkObjUnlock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
diff --git a/src/network_conf.h b/src/network_conf.h
--- a/src/network_conf.h
+++ b/src/network_conf.h
@@ -155,5 +155,8 @@ int virNetworkDeleteConfig(virConnectPtr
 int virNetworkDeleteConfig(virConnectPtr conn,
virNetworkObjPtr net);
 
+void virNetworkObjLock(virNetworkObjPtr obj);
+void virNetworkObjUnlock(virNetworkObjPtr obj);
+
 #endif /* __NETWORK_CONF_H__ */
 
diff --git a/src/node_device_conf.c b/src/node_device_conf.c
--- a/src/node_device_conf.c
+++ b/src/node_device_conf.c
@@ -397,3 +397,11 @@ void virNodeDevCapsDefFree(virNodeDevCap
 VIR_FREE(caps);
 }
 
+
+void virNodeDeviceObjLock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
+
+void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
diff --git a/src/node_device_conf.h b/src/node_device_conf.h
--- a/src/node_device_conf.h
+++ b/src/node_device_conf.h
@@ -190,4 +190,7 @@ void virNodeDeviceObjListFree(virNodeDev
 
 void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps);
 
+void virNodeDeviceObjLock(virNodeDeviceObjPtr obj);
+void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj);
+
 #endif /* __VIR_NODE_DEVICE_CONF_H__ */
diff --git a/src/storage_conf.c b/src/storage_conf.c
--- a/src/storage_conf.c
+++ b/src/storage_conf.c
@@ -1497,3 +1497,12 @@ char *virStoragePoolSourceListFormat(vir
 free(virBufferContentAndReset(&buf));
 return NULL;
 }
+
+
+void virStoragePoolObjLock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
+
+void virStoragePoolObjUnlock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED)
+{
+}
diff --git a/src/storage_conf.h b/src/storage_conf.h
--- a/src/storage_conf.h
+++ b/src/storage_conf.h
@@ -326,6 +326,9 @@ char *virStoragePoolSourceListFormat(vir
 char *virStoragePoolSourceListFormat(virConnectPtr conn,
  virStoragePoolSourceListPtr def);
 
+void virStoragePoolObjLock(virStoragePoolObjPtr obj);
+void virStoragePoolObjUnlock(virStoragePoolObjPtr obj);
+
 
 enum virStoragePoolFormatFileSystem {
 VIR_STORAGE_POOL_FS_AUTO = 0,

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|

[libvirt] PATCH: 0/28: Thread safety for libvirtd daemon and drivers

2008-11-30 Thread Daniel P. Berrange
The following huge series of patches adds thread safety for the libvirtd
daemon and drivers, and makes the daemon multi-threaded in processing
RPC calls. This enables multiple clients to be processed in parallel, 
without blocking each other. It does not change the thread rules for the
virConnectPtr object though, so each individual client is still serialized.

There are two core places where we have to have synchronization in the
threading model this patch series introduces

 - The libvirt daemon code 
   - A single global server lock (aka struct qemud_server)
   - One lock per client connection  (aka struct qemud_client)

 - The driver implementations
   - One lock per driver (aka QEMU, LXC, Test, UML, OpenVZ, Network,
 Storage, Node Devices)
   - One lock per primary object in a driver (virDomainObjPtr,
 virNetworkObjPtr, virStoragePoolObjPtr, virNodeDeviceObjptr
 instances)

For most cases, the big global server / driver locks are only held while
obtaining one of the finer grained locks. This gives a fairly good level
of concurrency for operations touching different objects. Once this core
infrastructure is merged, it will be possible to iterate on impl of
drivers to reduce the time locks are held - eg avoid holding a lock while
talking to the QEMU monitor interface.

To try and make it easier to spot thread locking problems this series
refactors alot of methods so that there is only a single return point
where the unlock call can be placed, rather than multiple return point
which increases the chances of missing an unlock call.

This touches a huge amount of code, so I'd like to get this all merged 
ASAP as it'll be really hard to keep it synced with ongoing changes.

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Concerning umlInotifyEvent

2008-11-30 Thread Ron Yorston
"Daniel P. Berrange" <[EMAIL PROTECTED]> wrote:
>That's a symptom of a bug earlier on. Try this patch:

Thanks, Daniel, that seems to have fixed it.

Ron

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Memory leak in xen_inotify.c

2008-11-30 Thread Daniel P. Berrange
On Sat, Nov 29, 2008 at 01:15:52PM -0800, Niraj Tolia wrote:
> Hi,
> 
> It looks like xenInotifyOpen() in xen_inotify.c has an opendir() call.
> However, as there is no corresponding closedir() and opendir() uses
> malloc internally, valgrind reports this as a memory leak. Adding a
> closedir() to the end of this function should fix this.

Thanks for the bug info, I've committed the following patch:

diff -u -r1.1 xen_inotify.c
--- xen_inotify.c   25 Nov 2008 10:44:53 -  1.1
+++ xen_inotify.c   30 Nov 2008 18:36:00 -
@@ -395,7 +395,7 @@
 return -1;
 }
 }
-
+closedir(dh);
 }
 
 if ((priv->inotifyFD = inotify_init()) < 0) {

Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Concerning umlInotifyEvent

2008-11-30 Thread Daniel P. Berrange
On Sun, Nov 30, 2008 at 03:17:04PM +, Ron Yorston wrote:
> At the top of umlInotifyEvent in uml_driver.c there is this test:
> 
> if (watch != driver->inotifyWatch)
> return;
> 
> This doesn't seem to be correct.  I have to comment out the test to get
> libvirtd to work with UML.

That's a symptom of a bug earlier on. Try this patch:

Index: src/uml_driver.c
===
RCS file: /data/cvs/libvirt/src/uml_driver.c,v
retrieving revision 1.4
diff -u -p -r1.4 uml_driver.c
--- src/uml_driver.c28 Nov 2008 12:03:20 -  1.4
+++ src/uml_driver.c30 Nov 2008 18:34:43 -
@@ -348,16 +348,16 @@ umlStartup(void) {
 return -1;
 }
 
-if ((uml_driver->inotifyWatch =
- inotify_add_watch(uml_driver->inotifyFD,
-   uml_driver->monitorDir,
-   IN_CREATE | IN_MODIFY | IN_DELETE)) < 0) {
+if (inotify_add_watch(uml_driver->inotifyFD,
+  uml_driver->monitorDir,
+  IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
 umlShutdown();
 return -1;
 }
 
-if (virEventAddHandle(uml_driver->inotifyFD, POLLIN,
-  umlInotifyEvent, uml_driver, NULL) < 0) {
+if ((uml_driver->inotifyWatch =
+ virEventAddHandle(uml_driver->inotifyFD, POLLIN,
+   umlInotifyEvent, uml_driver, NULL)) < 0) {
 umlShutdown();
 return -1;
 }


Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org   -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] Concerning umlInotifyEvent

2008-11-30 Thread Ron Yorston
At the top of umlInotifyEvent in uml_driver.c there is this test:

if (watch != driver->inotifyWatch)
return;

This doesn't seem to be correct.  I have to comment out the test to get
libvirtd to work with UML.

Ron

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] Re: [PATCH/RFC] kvm/qemu vs libvirtd restarts

2008-11-30 Thread Guido Günther
On Wed, Nov 26, 2008 at 08:54:40PM +, Daniel P. Berrange wrote:
[..snip..]
> Hmm, interesting idea - we already have a variant for parsing based
> off an arbitrary XML node, rather than assuming the root, 
> 
>   virDomainDefPtr virDomainDefParseNode(virConnectPtr conn,
> virCapsPtr caps,
> xmlDocPtr doc,
> xmlNodePtr root);
> 
> So we could add a wrapper function which writes out a XML doc
> 
>
>  
>  
>   ... normal domain XML config ...
>  
>
> 
> And so have a function
> 
>virDomainObjPtr virDomainObjParse(const char *filename)
> 
> which'd parse the custom QEMU state, and then just invoke  the
> virDomainDefParseNode for the nested  tag.
Yes, nice - this simplifies things. I'll try that.

> Now, some things like VNC port, domain ID really are easily tracked
> in the regular domain XML - rather than adding VIR_DOMAIN_XML_STATE
> I've a slight alternative idea.
> 
> The formatXML methods already accept a flag VIR_DOMAIN_XML_INACTIVE
> which when passed causes it to skip some attributes which only
> make sense for running VMs - VNC port, ID, VIF name
> 
> The parseXML methods, just hardcode this and always skip these
> attributes. We should fix this so the parsing only skips these
> attrs if this same VIR_DOMAIN_XML_INACTIVE flag is passed. Then
> just make sure all existing code is changed to set this flag
> when parsing XML. The code for loading VM from disk can simply
> not set this flag. Technically the LXC driver shold be doing
> this already, precisely for the VIF name issue.
Like the attached patch?
 -- Guido
>From 87db4a698ed9b49294c0f94137fc6beef13bd4e8 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Guido=20G=C3=BCnther?= <[EMAIL PROTECTED]>
Date: Tue, 25 Nov 2008 13:02:43 +0100
Subject: [PATCH] differentiate between active and inactive configs

by honoring the VIR_DOMAIN_XML_INACTIVE flag.
---
 src/domain_conf.c|   35 +++
 src/domain_conf.h|6 --
 src/lxc_controller.c |3 ++-
 src/lxc_driver.c |2 +-
 src/test.c   |6 --
 tests/qemuxml2argvtest.c |3 ++-
 6 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/src/domain_conf.c b/src/domain_conf.c
index 4adab69..292cecf 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -1318,7 +1318,7 @@ error:
 /* Parse the XML definition for a graphics device */
 static virDomainGraphicsDefPtr
 virDomainGraphicsDefParseXML(virConnectPtr conn,
- xmlNodePtr node) {
+ xmlNodePtr node, int flags) {
 virDomainGraphicsDefPtr def;
 char *type = NULL;
 
@@ -1355,7 +1355,8 @@ virDomainGraphicsDefParseXML(virConnectPtr conn,
 VIR_FREE(port);
 /* Legacy compat syntax, used -1 for auto-port */
 if (def->data.vnc.port == -1) {
-def->data.vnc.port = 0;
+if (flags & VIR_DOMAIN_XML_INACTIVE)
+def->data.vnc.port = 0;
 def->data.vnc.autoport = 1;
 }
 } else {
@@ -1365,7 +1366,8 @@ virDomainGraphicsDefParseXML(virConnectPtr conn,
 
 if ((autoport = virXMLPropString(node, "autoport")) != NULL) {
 if (STREQ(autoport, "yes")) {
-def->data.vnc.port = 0;
+if (flags & VIR_DOMAIN_XML_INACTIVE)
+def->data.vnc.port = 0;
 def->data.vnc.autoport = 1;
 }
 VIR_FREE(autoport);
@@ -1699,11 +1701,12 @@ int virDomainDiskQSort(const void *a, const void *b)
 #ifndef PROXY
 static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
 virCapsPtr caps,
-xmlXPathContextPtr ctxt)
+xmlXPathContextPtr ctxt, int flags)
 {
 xmlNodePtr *nodes = NULL, node = NULL;
 char *tmp = NULL;
 int i, n;
+long id = -1;
 virDomainDefPtr def;
 
 if (VIR_ALLOC(def) < 0) {
@@ -1711,7 +1714,11 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
  "%s", _("failed to allocate space for xmlXPathContext"));
 return NULL;
 }
-def->id = -1;
+
+if (!(flags & VIR_DOMAIN_XML_INACTIVE))
+if((virXPathLong(conn, "string(./@id)", ctxt, &id)) < 0)
+id = -1;
+def->id = (int)id;
 
 /* Find out what type of virtualization to use */
 if (!(tmp = virXPathString(conn, "string(./@type)", ctxt))) {
@@ -2101,7 +2108,8 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
 }
 if (n > 0) {
 virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(conn,
-nodes[0]);
+nodes[0],
+