Add locking for thread safety to nodedevice drivers

This commit is contained in:
Daniel P. Berrange 2008-12-04 21:48:31 +00:00
parent e8a4ea75a3
commit d48717054c
7 changed files with 207 additions and 70 deletions

View File

@ -1,3 +1,10 @@
Thu Dec 4 21:48:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/libvirt_sym.version.in, src/node_device.c,
src/node_device.h, src/node_device_conf.h,
src/node_device_devkit.c, src/node_device_hal.c: Add
locking for thread safety of driver APIs
Thu Dec 4 21:46:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com> Thu Dec 4 21:46:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/libvirt.c, src/datatypes.h, src/datatypes.c: Cache * src/libvirt.c, src/datatypes.h, src/datatypes.c: Cache

View File

@ -510,6 +510,7 @@ LIBVIRT_PRIVATE_@VERSION@ {
virNodeDeviceDefFormat; virNodeDeviceDefFormat;
virNodeDeviceObjLock; virNodeDeviceObjLock;
virNodeDeviceObjUnlock; virNodeDeviceObjUnlock;
virNodeDeviceAssignDef;
/* qparams.h */ /* qparams.h */

View File

@ -29,7 +29,7 @@
#include "virterror_internal.h" #include "virterror_internal.h"
#include "datatypes.h" #include "datatypes.h"
#include "memory.h" #include "memory.h"
#include "logging.h"
#include "node_device_conf.h" #include "node_device_conf.h"
#include "node_device.h" #include "node_device.h"
@ -45,6 +45,17 @@ static int dev_has_cap(const virNodeDeviceObjPtr dev, const char *cap)
} }
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, static int nodeNumOfDevices(virConnectPtr conn,
const char *cap, const char *cap,
unsigned int flags ATTRIBUTE_UNUSED) unsigned int flags ATTRIBUTE_UNUSED)
@ -71,15 +82,24 @@ nodeListDevices(virConnectPtr conn,
int ndevs = 0; int ndevs = 0;
unsigned int i; 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 || if (cap == NULL ||
dev_has_cap(driver->devs.objs[i], cap)) dev_has_cap(driver->devs.objs[i], cap)) {
if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) {
virNodeDeviceObjUnlock(driver->devs.objs[i]);
goto failure; goto failure;
}
}
virNodeDeviceObjUnlock(driver->devs.objs[i]);
}
nodeDeviceUnlock(driver);
return ndevs; return ndevs;
failure: failure:
nodeDeviceUnlock(driver);
--ndevs; --ndevs;
while (--ndevs >= 0) while (--ndevs >= 0)
VIR_FREE(names[ndevs]); VIR_FREE(names[ndevs]);
@ -94,7 +114,10 @@ static virNodeDevicePtr nodeDeviceLookupByName(virConnectPtr conn,
virNodeDeviceObjPtr obj; virNodeDeviceObjPtr obj;
virNodeDevicePtr ret = NULL; virNodeDevicePtr ret = NULL;
nodeDeviceLock(driver);
obj = virNodeDeviceFindByName(&driver->devs, name); obj = virNodeDeviceFindByName(&driver->devs, name);
nodeDeviceUnlock(driver);
if (!obj) { if (!obj) {
virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE, virNodeDeviceReportError(conn, VIR_ERR_INVALID_NODE_DEVICE,
"%s", _("no node device with matching name")); "%s", _("no node device with matching name"));
@ -104,6 +127,8 @@ static virNodeDevicePtr nodeDeviceLookupByName(virConnectPtr conn,
ret = virGetNodeDevice(conn, name); ret = virGetNodeDevice(conn, name);
cleanup: cleanup:
if (obj)
virNodeDeviceObjUnlock(obj);
return ret; return ret;
} }
@ -114,7 +139,10 @@ static char *nodeDeviceDumpXML(virNodeDevicePtr dev,
virNodeDeviceObjPtr obj; virNodeDeviceObjPtr obj;
char *ret = NULL; char *ret = NULL;
nodeDeviceLock(driver);
obj = virNodeDeviceFindByName(&driver->devs, dev->name); obj = virNodeDeviceFindByName(&driver->devs, dev->name);
nodeDeviceUnlock(driver);
if (!obj) { if (!obj) {
virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
"%s", _("no node device with matching name")); "%s", _("no node device with matching name"));
@ -124,6 +152,8 @@ static char *nodeDeviceDumpXML(virNodeDevicePtr dev,
ret = virNodeDeviceDefFormat(dev->conn, obj->def); ret = virNodeDeviceDefFormat(dev->conn, obj->def);
cleanup: cleanup:
if (obj)
virNodeDeviceObjUnlock(obj);
return ret; return ret;
} }
@ -134,7 +164,10 @@ static char *nodeDeviceGetParent(virNodeDevicePtr dev)
virNodeDeviceObjPtr obj; virNodeDeviceObjPtr obj;
char *ret = NULL; char *ret = NULL;
nodeDeviceLock(driver);
obj = virNodeDeviceFindByName(&driver->devs, dev->name); obj = virNodeDeviceFindByName(&driver->devs, dev->name);
nodeDeviceUnlock(driver);
if (!obj) { if (!obj) {
virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
"%s", _("no node device with matching name")); "%s", _("no node device with matching name"));
@ -146,6 +179,8 @@ static char *nodeDeviceGetParent(virNodeDevicePtr dev)
virNodeDeviceReportError(dev->conn, VIR_ERR_NO_MEMORY, NULL); virNodeDeviceReportError(dev->conn, VIR_ERR_NO_MEMORY, NULL);
cleanup: cleanup:
if (obj)
virNodeDeviceObjUnlock(obj);
return ret; return ret;
} }
@ -158,7 +193,10 @@ static int nodeDeviceNumOfCaps(virNodeDevicePtr dev)
int ncaps = 0; int ncaps = 0;
int ret = -1; int ret = -1;
nodeDeviceLock(driver);
obj = virNodeDeviceFindByName(&driver->devs, dev->name); obj = virNodeDeviceFindByName(&driver->devs, dev->name);
nodeDeviceUnlock(driver);
if (!obj) { if (!obj) {
virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
"%s", _("no node device with matching name")); "%s", _("no node device with matching name"));
@ -170,6 +208,8 @@ static int nodeDeviceNumOfCaps(virNodeDevicePtr dev)
ret = ncaps; ret = ncaps;
cleanup: cleanup:
if (obj)
virNodeDeviceObjUnlock(obj);
return ret; return ret;
} }
@ -183,7 +223,10 @@ nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
int ncaps = 0; int ncaps = 0;
int ret = -1; int ret = -1;
nodeDeviceLock(driver);
obj = virNodeDeviceFindByName(&driver->devs, dev->name); obj = virNodeDeviceFindByName(&driver->devs, dev->name);
nodeDeviceUnlock(driver);
if (!obj) { if (!obj) {
virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE, virNodeDeviceReportError(dev->conn, VIR_ERR_INVALID_NODE_DEVICE,
"%s", _("no node device with matching name")); "%s", _("no node device with matching name"));
@ -198,6 +241,8 @@ nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
ret = ncaps; ret = ncaps;
cleanup: cleanup:
if (obj)
virNodeDeviceObjUnlock(obj);
if (ret == -1) { if (ret == -1) {
--ncaps; --ncaps;
while (--ncaps >= 0) while (--ncaps >= 0)

View File

@ -26,6 +26,7 @@
#include "internal.h" #include "internal.h"
#include "driver.h" #include "driver.h"
#include "node_device_conf.h"
#ifdef HAVE_HAL #ifdef HAVE_HAL
int halNodeRegister(void); int halNodeRegister(void);
@ -34,6 +35,9 @@ int halNodeRegister(void);
int devkitNodeRegister(void); int devkitNodeRegister(void);
#endif #endif
void nodeDeviceLock(virDeviceMonitorStatePtr driver);
void nodeDeviceUnlock(virDeviceMonitorStatePtr driver);
void registerCommonNodeFuncs(virDeviceMonitorPtr mon); void registerCommonNodeFuncs(virDeviceMonitorPtr mon);
int nodedevRegister(void); int nodedevRegister(void);

View File

@ -158,7 +158,8 @@ struct _virNodeDeviceObjList {
typedef struct _virDeviceMonitorState virDeviceMonitorState; typedef struct _virDeviceMonitorState virDeviceMonitorState;
typedef virDeviceMonitorState *virDeviceMonitorStatePtr; typedef virDeviceMonitorState *virDeviceMonitorStatePtr;
struct _virDeviceMonitorState { struct _virDeviceMonitorState {
int dbusWatch; PTHREAD_MUTEX_T(lock);
virNodeDeviceObjList devs; /* currently-known devices */ virNodeDeviceObjList devs; /* currently-known devices */
void *privateData; /* driver-specific private data */ void *privateData; /* driver-specific private data */
}; };

View File

@ -237,6 +237,7 @@ static void dev_create(void *_dkdev, void *_dkclient ATTRIBUTE_UNUSED)
DevkitDevice *dkdev = _dkdev; DevkitDevice *dkdev = _dkdev;
const char *sysfs_path = devkit_device_get_native_path(dkdev); const char *sysfs_path = devkit_device_get_native_path(dkdev);
virNodeDeviceObjPtr dev = NULL; virNodeDeviceObjPtr dev = NULL;
virNodeDeviceDefPtr def = NULL;
const char *name; const char *name;
int rv; int rv;
@ -250,31 +251,39 @@ static void dev_create(void *_dkdev, void *_dkclient ATTRIBUTE_UNUSED)
else else
++name; ++name;
if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0) if (VIR_ALLOC(def) < 0)
goto failure; goto failure;
dev->privateData = dkdev; if ((def->name = strdup(name)) == NULL)
if ((dev->def->name = strdup(name)) == NULL)
goto failure; goto failure;
// TODO: Find device parent, if any // TODO: Find device parent, if any
rv = gather_capabilities(dkdev, &dev->def->caps); rv = gather_capabilities(dkdev, &def->caps);
if (rv != 0) goto failure; if (rv != 0) goto failure;
if (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0) nodeDeviceLock(driverState);
goto failure; dev = virNodeDeviceAssignDef(NULL,
&driverState->devs,
def);
driverState->devs.objs[driverState->devs.count++] = dev; if (!dev) {
nodeDeviceUnlock(driverState);
goto failure;
}
dev->privateData = dkdev;
dev->privateFree = NULL; /* XXX some free func needed ? */
virNodeDeviceObjUnlock(dev);
nodeDeviceUnlock(driverState);
return; return;
failure: failure:
DEBUG("FAILED TO ADD dev %s", name); DEBUG("FAILED TO ADD dev %s", name);
if (dev) if (def)
virNodeDeviceDefFree(dev->def); virNodeDeviceDefFree(def);
VIR_FREE(dev);
} }
@ -292,8 +301,8 @@ static int devkitDeviceMonitorStartup(void)
if (VIR_ALLOC(driverState) < 0) if (VIR_ALLOC(driverState) < 0)
return -1; return -1;
// TODO: Is it really ok to call this multiple times?? pthread_mutex_init(&driverState->lock, NULL);
// Is there something analogous to call on close?
g_type_init(); g_type_init();
/* Get new devkit_client and connect to daemon */ /* Get new devkit_client and connect to daemon */
@ -362,10 +371,14 @@ static int devkitDeviceMonitorStartup(void)
static int devkitDeviceMonitorShutdown(void) static int devkitDeviceMonitorShutdown(void)
{ {
if (driverState) { if (driverState) {
DevkitClient *devkit_client = DRV_STATE_DKCLIENT(driverState); DevkitClient *devkit_client;
nodeDeviceLock(driverState);
devkit_client = DRV_STATE_DKCLIENT(driverState);
virNodeDeviceObjListFree(&driverState->devs); virNodeDeviceObjListFree(&driverState->devs);
if (devkit_client) if (devkit_client)
g_object_unref(devkit_client); g_object_unref(devkit_client);
nodeDeviceLock(driverState);
VIR_FREE(driverState); VIR_FREE(driverState);
return 0; return 0;
} }
@ -375,6 +388,8 @@ static int devkitDeviceMonitorShutdown(void)
static int devkitDeviceMonitorReload(void) static int devkitDeviceMonitorReload(void)
{ {
/* XXX This isn't thread safe because its free'ing the thing
* we're locking */
(void)devkitDeviceMonitorShutdown(); (void)devkitDeviceMonitorShutdown();
return devkitDeviceMonitorStartup(); return devkitDeviceMonitorStartup();
} }

View File

@ -403,53 +403,62 @@ static void free_udi(void *udi)
VIR_FREE(udi); VIR_FREE(udi);
} }
static void dev_create(char *udi) static void dev_create(const char *udi)
{ {
LibHalContext *ctx = DRV_STATE_HAL_CTX(driverState); LibHalContext *ctx;
char *parent_key = NULL; char *parent_key = NULL;
virNodeDeviceObjPtr dev; virNodeDeviceObjPtr dev = NULL;
virNodeDeviceDefPtr def = NULL;
const char *name = hal_name(udi); const char *name = hal_name(udi);
int rv; int rv;
char *privData = strdup(udi);
if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0) if (!privData)
return;
nodeDeviceLock(driverState);
ctx = DRV_STATE_HAL_CTX(driverState);
if (VIR_ALLOC(def) < 0)
goto failure; goto failure;
dev->privateData = udi; if ((def->name = strdup(name)) == NULL)
dev->privateFree = free_udi;
if ((dev->def->name = strdup(name)) == NULL)
goto failure; goto failure;
if (get_str_prop(ctx, udi, "info.parent", &parent_key) == 0) { if (get_str_prop(ctx, udi, "info.parent", &parent_key) == 0) {
dev->def->parent = strdup(hal_name(parent_key)); def->parent = strdup(hal_name(parent_key));
VIR_FREE(parent_key); VIR_FREE(parent_key);
if (dev->def->parent == NULL) if (def->parent == NULL)
goto failure; goto failure;
} }
rv = gather_capabilities(ctx, udi, &dev->def->caps); rv = gather_capabilities(ctx, udi, &def->caps);
if (rv != 0) goto failure; if (rv != 0) goto failure;
if (dev->def->caps == NULL) { if (def->caps == NULL)
virNodeDeviceDefFree(dev->def); goto cleanup;
VIR_FREE(dev);
VIR_FREE(udi);
return;
}
if (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0) dev = virNodeDeviceAssignDef(NULL,
&driverState->devs,
def);
if (!dev)
goto failure; goto failure;
driverState->devs.objs[driverState->devs.count++] = dev; dev->privateData = privData;
dev->privateFree = free_udi;
virNodeDeviceObjUnlock(dev);
nodeDeviceUnlock(driverState);
return; return;
failure: failure:
DEBUG("FAILED TO ADD dev %s", name); DEBUG("FAILED TO ADD dev %s", name);
if (dev) cleanup:
virNodeDeviceDefFree(dev->def); VIR_FREE(privData);
VIR_FREE(dev); if (def)
VIR_FREE(udi); virNodeDeviceDefFree(def);
nodeDeviceUnlock(driverState);
} }
@ -457,7 +466,7 @@ static void device_added(LibHalContext *ctx ATTRIBUTE_UNUSED,
const char *udi) const char *udi)
{ {
DEBUG0(hal_name(udi)); DEBUG0(hal_name(udi));
dev_create(strdup(udi)); dev_create(udi);
} }
@ -465,12 +474,16 @@ static void device_removed(LibHalContext *ctx ATTRIBUTE_UNUSED,
const char *udi) const char *udi)
{ {
const char *name = hal_name(udi); const char *name = hal_name(udi);
virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); virNodeDeviceObjPtr dev;
nodeDeviceLock(driverState);
dev = virNodeDeviceFindByName(&driverState->devs,name);
DEBUG0(name); DEBUG0(name);
if (dev) if (dev)
virNodeDeviceObjRemove(&driverState->devs, dev); virNodeDeviceObjRemove(&driverState->devs, dev);
else else
DEBUG("no device named %s", name); DEBUG("no device named %s", name);
nodeDeviceUnlock(driverState);
} }
@ -478,12 +491,18 @@ static void device_cap_added(LibHalContext *ctx,
const char *udi, const char *cap) const char *udi, const char *cap)
{ {
const char *name = hal_name(udi); const char *name = hal_name(udi);
virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); virNodeDeviceObjPtr dev;
nodeDeviceLock(driverState);
dev = virNodeDeviceFindByName(&driverState->devs,name);
nodeDeviceUnlock(driverState);
DEBUG("%s %s", cap, name); DEBUG("%s %s", cap, name);
if (dev) if (dev) {
(void)gather_capability(ctx, udi, cap, &dev->def->caps); (void)gather_capability(ctx, udi, cap, &dev->def->caps);
else virNodeDeviceObjUnlock(dev);
} else {
DEBUG("no device named %s", name); DEBUG("no device named %s", name);
}
} }
@ -492,16 +511,20 @@ static void device_cap_lost(LibHalContext *ctx ATTRIBUTE_UNUSED,
const char *cap) const char *cap)
{ {
const char *name = hal_name(udi); const char *name = hal_name(udi);
virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); virNodeDeviceObjPtr dev;
nodeDeviceLock(driverState);
dev = virNodeDeviceFindByName(&driverState->devs,name);
DEBUG("%s %s", cap, name); DEBUG("%s %s", cap, name);
if (dev) { if (dev) {
/* Simply "rediscover" device -- incrementally handling changes /* Simply "rediscover" device -- incrementally handling changes
* to sub-capabilities (like net.80203) is nasty ... so avoid it. * to sub-capabilities (like net.80203) is nasty ... so avoid it.
*/ */
virNodeDeviceObjRemove(&driverState->devs, dev); virNodeDeviceObjRemove(&driverState->devs, dev);
dev_create(strdup(udi)); dev_create(udi);
} else } else
DEBUG("no device named %s", name); DEBUG("no device named %s", name);
nodeDeviceUnlock(driverState);
} }
@ -512,7 +535,10 @@ static void device_prop_modified(LibHalContext *ctx ATTRIBUTE_UNUSED,
dbus_bool_t is_added ATTRIBUTE_UNUSED) dbus_bool_t is_added ATTRIBUTE_UNUSED)
{ {
const char *name = hal_name(udi); const char *name = hal_name(udi);
virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name); virNodeDeviceObjPtr dev;
nodeDeviceLock(driverState);
dev = virNodeDeviceFindByName(&driverState->devs,name);
DEBUG("%s %s", key, name); DEBUG("%s %s", key, name);
if (dev) { if (dev) {
/* Simply "rediscover" device -- incrementally handling changes /* Simply "rediscover" device -- incrementally handling changes
@ -520,9 +546,10 @@ static void device_prop_modified(LibHalContext *ctx ATTRIBUTE_UNUSED,
* specific ways) is nasty ... so avoid it. * specific ways) is nasty ... so avoid it.
*/ */
virNodeDeviceObjRemove(&driverState->devs, dev); virNodeDeviceObjRemove(&driverState->devs, dev);
dev_create(strdup(udi)); dev_create(udi);
} else } else
DEBUG("no device named %s", name); DEBUG("no device named %s", name);
nodeDeviceUnlock(driverState);
} }
@ -531,8 +558,8 @@ static void dbus_watch_callback(int fdatch ATTRIBUTE_UNUSED,
int events, void *opaque) int events, void *opaque)
{ {
DBusWatch *watch = opaque; DBusWatch *watch = opaque;
LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState); LibHalContext *hal_ctx;
DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx); DBusConnection *dbus_conn;
int dbus_flags = 0; int dbus_flags = 0;
if (events & VIR_EVENT_HANDLE_READABLE) if (events & VIR_EVENT_HANDLE_READABLE)
@ -546,6 +573,10 @@ static void dbus_watch_callback(int fdatch ATTRIBUTE_UNUSED,
(void)dbus_watch_handle(watch, dbus_flags); (void)dbus_watch_handle(watch, dbus_flags);
nodeDeviceLock(driverState);
hal_ctx = DRV_STATE_HAL_CTX(driverState);
dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
nodeDeviceUnlock(driverState);
while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) while (dbus_connection_dispatch(dbus_conn) == DBUS_DISPATCH_DATA_REMAINS)
/* keep dispatching while data remains */; /* keep dispatching while data remains */;
} }
@ -566,42 +597,63 @@ static int xlate_dbus_watch_flags(int dbus_flags)
} }
struct nodeDeviceWatchInfo
{
int watch;
};
static void nodeDeviceWatchFree(void *data) {
struct nodeDeviceWatchInfo *info = data;
VIR_FREE(info);
}
static dbus_bool_t add_dbus_watch(DBusWatch *watch, static dbus_bool_t add_dbus_watch(DBusWatch *watch,
void *data) void *data ATTRIBUTE_UNUSED)
{ {
int flags = 0; int flags = 0;
virDeviceMonitorStatePtr state = data; struct nodeDeviceWatchInfo *info;
if (VIR_ALLOC(info) < 0)
return 0;
if (dbus_watch_get_enabled(watch)) if (dbus_watch_get_enabled(watch))
flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch)); flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch));
if ((state->dbusWatch = info->watch = virEventAddHandle(dbus_watch_get_unix_fd(watch), flags,
virEventAddHandle(dbus_watch_get_unix_fd(watch), flags, dbus_watch_callback, watch, NULL);
dbus_watch_callback, watch, NULL)) < 0) if (info->watch < 0) {
VIR_FREE(info);
return 0; return 0;
}
dbus_watch_set_data(watch, info, nodeDeviceWatchFree);
return 1; return 1;
} }
static void remove_dbus_watch(DBusWatch *watch ATTRIBUTE_UNUSED, static void remove_dbus_watch(DBusWatch *watch,
void *data) void *data ATTRIBUTE_UNUSED)
{ {
virDeviceMonitorStatePtr state = data; struct nodeDeviceWatchInfo *info;
(void)virEventRemoveHandle(state->dbusWatch); info = dbus_watch_get_data(watch);
(void)virEventRemoveHandle(info->watch);
} }
static void toggle_dbus_watch(DBusWatch *watch, static void toggle_dbus_watch(DBusWatch *watch,
void *data) void *data ATTRIBUTE_UNUSED)
{ {
int flags = 0; int flags = 0;
virDeviceMonitorStatePtr state = data; struct nodeDeviceWatchInfo *info;
if (dbus_watch_get_enabled(watch)) if (dbus_watch_get_enabled(watch))
flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch)); flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch));
(void)virEventUpdateHandle(state->dbusWatch, flags); info = dbus_watch_get_data(watch);
(void)virEventUpdateHandle(info->watch, flags);
} }
@ -620,6 +672,9 @@ static int halDeviceMonitorStartup(void)
if (VIR_ALLOC(driverState) < 0) if (VIR_ALLOC(driverState) < 0)
return -1; return -1;
pthread_mutex_init(&driverState->lock, NULL);
nodeDeviceLock(driverState);
/* Allocate and initialize a new HAL context */ /* Allocate and initialize a new HAL context */
dbus_error_init(&err); dbus_error_init(&err);
hal_ctx = libhal_ctx_new(); hal_ctx = libhal_ctx_new();
@ -647,7 +702,7 @@ static int halDeviceMonitorStartup(void)
add_dbus_watch, add_dbus_watch,
remove_dbus_watch, remove_dbus_watch,
toggle_dbus_watch, toggle_dbus_watch,
driverState, NULL)) { NULL, NULL)) {
fprintf(stderr, "%s: dbus_connection_set_watch_functions failed\n", fprintf(stderr, "%s: dbus_connection_set_watch_functions failed\n",
__FUNCTION__); __FUNCTION__);
goto failure; goto failure;
@ -665,14 +720,18 @@ static int halDeviceMonitorStartup(void)
/* Populate with known devices */ /* Populate with known devices */
driverState->privateData = hal_ctx; driverState->privateData = hal_ctx;
nodeDeviceUnlock(driverState);
udi = libhal_get_all_devices(hal_ctx, &num_devs, &err); udi = libhal_get_all_devices(hal_ctx, &num_devs, &err);
if (udi == NULL) { if (udi == NULL) {
fprintf(stderr, "%s: libhal_get_all_devices failed\n", __FUNCTION__); fprintf(stderr, "%s: libhal_get_all_devices failed\n", __FUNCTION__);
goto failure; goto failure;
} }
for (i = 0; i < num_devs; i++) for (i = 0; i < num_devs; i++) {
dev_create(udi[i]); dev_create(udi[i]);
free(udi); VIR_FREE(udi[i]);
}
VIR_FREE(udi);
return 0; return 0;
@ -686,9 +745,10 @@ static int halDeviceMonitorStartup(void)
(void)libhal_ctx_free(hal_ctx); (void)libhal_ctx_free(hal_ctx);
if (udi) { if (udi) {
for (i = 0; i < num_devs; i++) for (i = 0; i < num_devs; i++)
free(udi[i]); VIR_FREE(udi[i]);
free(udi); VIR_FREE(udi);
} }
nodeDeviceUnlock(driverState);
VIR_FREE(driverState); VIR_FREE(driverState);
return -1; return -1;
@ -698,10 +758,12 @@ static int halDeviceMonitorStartup(void)
static int halDeviceMonitorShutdown(void) static int halDeviceMonitorShutdown(void)
{ {
if (driverState) { if (driverState) {
nodeDeviceLock(driverState);
LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState); LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState);
virNodeDeviceObjListFree(&driverState->devs); virNodeDeviceObjListFree(&driverState->devs);
(void)libhal_ctx_shutdown(hal_ctx, NULL); (void)libhal_ctx_shutdown(hal_ctx, NULL);
(void)libhal_ctx_free(hal_ctx); (void)libhal_ctx_free(hal_ctx);
nodeDeviceUnlock(driverState);
VIR_FREE(driverState); VIR_FREE(driverState);
return 0; return 0;
} }
@ -711,6 +773,8 @@ static int halDeviceMonitorShutdown(void)
static int halDeviceMonitorReload(void) static int halDeviceMonitorReload(void)
{ {
/* XXX This isn't thread safe because its free'ing the thing
* we're locking */
(void)halDeviceMonitorShutdown(); (void)halDeviceMonitorShutdown();
return halDeviceMonitorStartup(); return halDeviceMonitorStartup();
} }