#include "virterror_internal.h"
#include "datatypes.h"
#include "memory.h"
-
+#include "logging.h"
#include "node_device_conf.h"
#include "node_device.h"
}
+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,
unsigned int flags ATTRIBUTE_UNUSED)
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]);
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"));
ret = virGetNodeDevice(conn, name);
cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
return ret;
}
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"));
ret = virNodeDeviceDefFormat(dev->conn, obj->def);
cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
return ret;
}
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"));
virNodeDeviceReportError(dev->conn, VIR_ERR_NO_MEMORY, NULL);
cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
return ret;
}
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"));
ret = ncaps;
cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
return ret;
}
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"));
ret = ncaps;
cleanup:
+ if (obj)
+ virNodeDeviceObjUnlock(obj);
if (ret == -1) {
--ncaps;
while (--ncaps >= 0)
DevkitDevice *dkdev = _dkdev;
const char *sysfs_path = devkit_device_get_native_path(dkdev);
virNodeDeviceObjPtr dev = NULL;
+ virNodeDeviceDefPtr def = NULL;
const char *name;
int rv;
else
++name;
- if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0)
+ if (VIR_ALLOC(def) < 0)
goto failure;
- dev->privateData = dkdev;
-
- if ((dev->def->name = strdup(name)) == NULL)
+ if ((def->name = strdup(name)) == NULL)
goto failure;
// 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 (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0)
+ nodeDeviceLock(driverState);
+ dev = virNodeDeviceAssignDef(NULL,
+ &driverState->devs,
+ def);
+
+ if (!dev) {
+ nodeDeviceUnlock(driverState);
goto failure;
+ }
- driverState->devs.objs[driverState->devs.count++] = dev;
+ dev->privateData = dkdev;
+ dev->privateFree = NULL; /* XXX some free func needed ? */
+ virNodeDeviceObjUnlock(dev);
+
+ nodeDeviceUnlock(driverState);
return;
failure:
DEBUG("FAILED TO ADD dev %s", name);
- if (dev)
- virNodeDeviceDefFree(dev->def);
- VIR_FREE(dev);
+ if (def)
+ virNodeDeviceDefFree(def);
}
if (VIR_ALLOC(driverState) < 0)
return -1;
- // TODO: Is it really ok to call this multiple times??
- // Is there something analogous to call on close?
+ pthread_mutex_init(&driverState->lock, NULL);
+
g_type_init();
/* Get new devkit_client and connect to daemon */
static int devkitDeviceMonitorShutdown(void)
{
if (driverState) {
- DevkitClient *devkit_client = DRV_STATE_DKCLIENT(driverState);
+ DevkitClient *devkit_client;
+
+ nodeDeviceLock(driverState);
+ devkit_client = DRV_STATE_DKCLIENT(driverState);
virNodeDeviceObjListFree(&driverState->devs);
if (devkit_client)
g_object_unref(devkit_client);
+ nodeDeviceLock(driverState);
VIR_FREE(driverState);
return 0;
}
static int devkitDeviceMonitorReload(void)
{
+ /* XXX This isn't thread safe because its free'ing the thing
+ * we're locking */
(void)devkitDeviceMonitorShutdown();
return devkitDeviceMonitorStartup();
}
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;
- virNodeDeviceObjPtr dev;
+ virNodeDeviceObjPtr dev = NULL;
+ virNodeDeviceDefPtr def = NULL;
const char *name = hal_name(udi);
int rv;
+ char *privData = strdup(udi);
- if (VIR_ALLOC(dev) < 0 || VIR_ALLOC(dev->def) < 0)
- goto failure;
+ if (!privData)
+ return;
- dev->privateData = udi;
- dev->privateFree = free_udi;
+ nodeDeviceLock(driverState);
+ ctx = DRV_STATE_HAL_CTX(driverState);
+
+ if (VIR_ALLOC(def) < 0)
+ goto failure;
- if ((dev->def->name = strdup(name)) == NULL)
+ if ((def->name = strdup(name)) == NULL)
goto failure;
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);
- if (dev->def->parent == NULL)
+ if (def->parent == NULL)
goto failure;
}
- rv = gather_capabilities(ctx, udi, &dev->def->caps);
+ rv = gather_capabilities(ctx, udi, &def->caps);
if (rv != 0) goto failure;
- if (dev->def->caps == NULL) {
- virNodeDeviceDefFree(dev->def);
- VIR_FREE(dev);
- VIR_FREE(udi);
- return;
- }
+ if (def->caps == NULL)
+ goto cleanup;
- if (VIR_REALLOC_N(driverState->devs.objs, driverState->devs.count + 1) < 0)
+ dev = virNodeDeviceAssignDef(NULL,
+ &driverState->devs,
+ def);
+
+ if (!dev)
goto failure;
- driverState->devs.objs[driverState->devs.count++] = dev;
+ dev->privateData = privData;
+ dev->privateFree = free_udi;
+ virNodeDeviceObjUnlock(dev);
+ nodeDeviceUnlock(driverState);
return;
failure:
DEBUG("FAILED TO ADD dev %s", name);
- if (dev)
- virNodeDeviceDefFree(dev->def);
- VIR_FREE(dev);
- VIR_FREE(udi);
+cleanup:
+ VIR_FREE(privData);
+ if (def)
+ virNodeDeviceDefFree(def);
+ nodeDeviceUnlock(driverState);
}
const char *udi)
{
DEBUG0(hal_name(udi));
- dev_create(strdup(udi));
+ dev_create(udi);
}
const char *udi)
{
const char *name = hal_name(udi);
- virNodeDeviceObjPtr dev = virNodeDeviceFindByName(&driverState->devs,name);
+ virNodeDeviceObjPtr dev;
+
+ nodeDeviceLock(driverState);
+ dev = virNodeDeviceFindByName(&driverState->devs,name);
DEBUG0(name);
if (dev)
virNodeDeviceObjRemove(&driverState->devs, dev);
else
DEBUG("no device named %s", name);
+ nodeDeviceUnlock(driverState);
}
const char *udi, const char *cap)
{
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);
- if (dev)
+ if (dev) {
(void)gather_capability(ctx, udi, cap, &dev->def->caps);
- else
+ virNodeDeviceObjUnlock(dev);
+ } else {
DEBUG("no device named %s", name);
+ }
}
const char *cap)
{
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);
if (dev) {
/* Simply "rediscover" device -- incrementally handling changes
* to sub-capabilities (like net.80203) is nasty ... so avoid it.
*/
virNodeDeviceObjRemove(&driverState->devs, dev);
- dev_create(strdup(udi));
+ dev_create(udi);
} else
DEBUG("no device named %s", name);
+ nodeDeviceUnlock(driverState);
}
dbus_bool_t is_added ATTRIBUTE_UNUSED)
{
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);
if (dev) {
/* Simply "rediscover" device -- incrementally handling changes
* specific ways) is nasty ... so avoid it.
*/
virNodeDeviceObjRemove(&driverState->devs, dev);
- dev_create(strdup(udi));
+ dev_create(udi);
} else
DEBUG("no device named %s", name);
+ nodeDeviceUnlock(driverState);
}
int events, void *opaque)
{
DBusWatch *watch = opaque;
- LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState);
- DBusConnection *dbus_conn = libhal_ctx_get_dbus_connection(hal_ctx);
+ LibHalContext *hal_ctx;
+ DBusConnection *dbus_conn;
int dbus_flags = 0;
if (events & VIR_EVENT_HANDLE_READABLE)
(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)
/* keep dispatching while data remains */;
}
}
+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,
- void *data)
+ void *data ATTRIBUTE_UNUSED)
{
int flags = 0;
- virDeviceMonitorStatePtr state = data;
+ struct nodeDeviceWatchInfo *info;
+
+ if (VIR_ALLOC(info) < 0)
+ return 0;
if (dbus_watch_get_enabled(watch))
flags = xlate_dbus_watch_flags(dbus_watch_get_flags(watch));
- if ((state->dbusWatch =
- virEventAddHandle(dbus_watch_get_unix_fd(watch), flags,
- dbus_watch_callback, watch, NULL)) < 0)
+ info->watch = virEventAddHandle(dbus_watch_get_unix_fd(watch), flags,
+ dbus_watch_callback, watch, NULL);
+ if (info->watch < 0) {
+ VIR_FREE(info);
return 0;
+ }
+ dbus_watch_set_data(watch, info, nodeDeviceWatchFree);
+
return 1;
}
-static void remove_dbus_watch(DBusWatch *watch ATTRIBUTE_UNUSED,
- void *data)
+static void remove_dbus_watch(DBusWatch *watch,
+ 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,
- void *data)
+ void *data ATTRIBUTE_UNUSED)
{
int flags = 0;
- virDeviceMonitorStatePtr state = data;
+ struct nodeDeviceWatchInfo *info;
if (dbus_watch_get_enabled(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);
}
if (VIR_ALLOC(driverState) < 0)
return -1;
+ pthread_mutex_init(&driverState->lock, NULL);
+ nodeDeviceLock(driverState);
+
/* Allocate and initialize a new HAL context */
dbus_error_init(&err);
hal_ctx = libhal_ctx_new();
add_dbus_watch,
remove_dbus_watch,
toggle_dbus_watch,
- driverState, NULL)) {
+ NULL, NULL)) {
fprintf(stderr, "%s: dbus_connection_set_watch_functions failed\n",
__FUNCTION__);
goto failure;
/* Populate with known devices */
driverState->privateData = hal_ctx;
+
+ nodeDeviceUnlock(driverState);
udi = libhal_get_all_devices(hal_ctx, &num_devs, &err);
if (udi == NULL) {
fprintf(stderr, "%s: libhal_get_all_devices failed\n", __FUNCTION__);
goto failure;
}
- for (i = 0; i < num_devs; i++)
+ for (i = 0; i < num_devs; i++) {
dev_create(udi[i]);
- free(udi);
+ VIR_FREE(udi[i]);
+ }
+ VIR_FREE(udi);
return 0;
(void)libhal_ctx_free(hal_ctx);
if (udi) {
for (i = 0; i < num_devs; i++)
- free(udi[i]);
- free(udi);
+ VIR_FREE(udi[i]);
+ VIR_FREE(udi);
}
+ nodeDeviceUnlock(driverState);
VIR_FREE(driverState);
return -1;
static int halDeviceMonitorShutdown(void)
{
if (driverState) {
+ nodeDeviceLock(driverState);
LibHalContext *hal_ctx = DRV_STATE_HAL_CTX(driverState);
virNodeDeviceObjListFree(&driverState->devs);
(void)libhal_ctx_shutdown(hal_ctx, NULL);
(void)libhal_ctx_free(hal_ctx);
+ nodeDeviceUnlock(driverState);
VIR_FREE(driverState);
return 0;
}
static int halDeviceMonitorReload(void)
{
+ /* XXX This isn't thread safe because its free'ing the thing
+ * we're locking */
(void)halDeviceMonitorShutdown();
return halDeviceMonitorStartup();
}