mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-27 02:51:16 +00:00
Add locking for thread safety to nodedevice drivers
This commit is contained in:
parent
e8a4ea75a3
commit
d48717054c
@ -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
|
||||||
|
@ -510,6 +510,7 @@ LIBVIRT_PRIVATE_@VERSION@ {
|
|||||||
virNodeDeviceDefFormat;
|
virNodeDeviceDefFormat;
|
||||||
virNodeDeviceObjLock;
|
virNodeDeviceObjLock;
|
||||||
virNodeDeviceObjUnlock;
|
virNodeDeviceObjUnlock;
|
||||||
|
virNodeDeviceAssignDef;
|
||||||
|
|
||||||
|
|
||||||
/* qparams.h */
|
/* qparams.h */
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user