[...]
> +struct _udevEventData {
> + virObjectLockable parent;
> +
> struct udev_monitor *udev_monitor;
> int watch;
> bool privileged;
> };
Mental note - maybe the driver->privateData should change to
driver->udevEventData in _virNodeDeviceDriverState
I like the notion of generic private data per backend, even though one of them
doesn't use it all. But in principle, I agree with you, I'd just wait 'till
we
decide that we can safely deprecate hal backend in upstream completely.
You interchange using @priv and @data throughout which right now could
make sense, but in the future may make less sense. I have a preference
for consistency, so calling @data in some places and @priv in others
leads to inconsistency. I believe pick one and be consistent.
Good point, noted.
>
> +static virClassPtr udevEventDataClass;
> +
> +static void
> +udevEventDataDispose(void *obj)
> +{
> + struct udev *udev = NULL;
> + udevEventDataPtr data = obj;
> +
> + if (data->watch != -1)
> + virEventRemoveHandle(data->watch);
> +
> + if (data->udev_monitor)
> + udev = udev_monitor_get_udev(data->udev_monitor);
> +
> + udev_unref(udev);
> + udev_monitor_unref(data->udev_monitor);
This is a different order than previous cleanup - perhaps should be:
if (data->udev_monitor) {
udev = udev_monitor_get_udev(data->udev_monitor);
udev_monitor_unref(data->udev_monitor);
udev_unref(udev);
}
libudev handles NULLs gracefully...
or
if (!data->udev_monitor)
return;
udev = udev_monitor_get_udev(data->udev_monitor);
udev_monitor_unref(data->udev_monitor);
udev_unref(udev);
I'll go with this version then, I did it this way, because udev keeps a pointer
to the context withing the monitor, but doesn't touch it when freeing, leaving
the responsibility to the caller. But I agree that releasing the monitor before
releasing the context makes more sense.
Just not clear what happens to udev if you unref udev before unref
udev_monitor. Better safe than sorry and go in the opposite order of
Initialization.
> +}
> +
> +
> +static int
> +udevEventDataOnceInit(void)
> +{
> + if (!(udevEventDataClass = virClassNew(virClassForObjectLockable(),
> + "udevEventData",
> + sizeof(udevEventData),
> + udevEventDataDispose)))
> + return -1;
> +
> + return 0;
> +}
> +
> +VIR_ONCE_GLOBAL_INIT(udevEventData)
> +
> +static udevEventDataPtr
> +udevEventDataNew(void)
> +{
> + udevEventDataPtr ret = NULL;
> +
> + if (udevEventDataInitialize() < 0)
> + return NULL;
> +
> + if (!(ret = virObjectLockableNew(udevEventDataClass)))
> + return NULL;
> +
> + ret->watch = -1;
> + return ret;
> +}
> +
> +
> +static bool
> +udevEventDataIsPrivileged(udevEventDataPtr data)
> +{
> + bool privileged;
Hmmm... is @data privileged or is the driver that needs the privilege
check... IOW: should privileged by a DriverState value (even though it'd
be unused in _hal). It comes in as a virDrvStateInitialize value. That
way it's just a driver->privileged check regardless of whether there is
an event thread running.
Good observation, a patch will be added.
I know - should have thought of this sooner, but sometimes things are
more obvious at odd points in review time. Moving privileged would be a
patch 1.5 and thus make this helper unnecessary. It'd be a simple move
from private to NodeDeviceDriverState and then store/read from there
instead of @priv. Then udevGetDMIData wouldn't need to get @priv.
No problem.
[..]
> {
> + udevEventDataPtr priv = driver->privateData;
> struct udev_device *device = NULL;
> - struct udev_monitor *udev_monitor = NULL;
>
> - udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
Should we add a "if (!priv) return" before this?
This would only be necessary if that was a user's input, but it's us who's
completely responsible for that and @data are only touched by stateCleanup,
which runs after the eventloop ends, so this check would be essentially useless.
> + virObjectLock(priv);
>
> - if (!udevEventMonitorSanityCheck(udev_monitor, fd))
> + if (!udevEventMonitorSanityCheck(priv, fd)) {
> + virObjectUnlock(priv);
> return;
> + }
> +
> + device = udev_monitor_receive_device(priv->udev_monitor);
> + virObjectUnlock(priv);
>
> - device = udev_monitor_receive_device(udev_monitor);
> if (device == NULL) {
> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> _("udev_monitor_receive_device returned NULL"));
> @@ -1675,12 +1725,13 @@ udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
> static void
> udevGetDMIData(virNodeDevCapSystemPtr syscap)
> {
> + udevEventDataPtr priv = driver->privateData;
> struct udev *udev = NULL;
> struct udev_device *device = NULL;
> virNodeDevCapSystemHardwarePtr hardware = &syscap->hardware;
> virNodeDevCapSystemFirmwarePtr firmware = &syscap->firmware;
>
> - udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
> + udev = udev_monitor_get_udev(priv->udev_monitor);
There's no lock/unlock around priv-> access here (although there is
earlier).
this is called from within Initialize which holds the lock almost the whole
time, so this would cause a deadlock (I only realized this when I tried it). So
because what you say makes more sense, I'll add a separate patch that will move
the object lock in Initialize before trying to set up the system node (there's
no need to hold it the whole time) and then we can go with this suggestion.
>
> device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
> if (device == NULL) {
> @@ -1791,15 +1842,9 @@ nodeStateInitialize(bool privileged,
> virStateInhibitCallback callback ATTRIBUTE_UNUSED,
> void *opaque ATTRIBUTE_UNUSED)
> {
> - udevPrivate *priv = NULL;
> + udevEventDataPtr priv = NULL;
> struct udev *udev = NULL;
>
> - if (VIR_ALLOC(priv) < 0)
> - return -1;
> -
> - priv->watch = -1;
> - priv->privileged = privileged;
FWIW: You lost priv->privileged setting in this patch... So it'd always
be false
Great eyes ;).
> -
> if (VIR_ALLOC(driver) < 0) {
> VIR_FREE(priv);
^^ won't be necessary and then of course the { } won't be either...
Same a few lines lower where there's VIR_FREE(priv), but the { } would
stay after a virMutexInit failure
It's always mistakes like these that are so obvious yet they can be only
spotted during a review :), thanks. Also, I appreciate the RBs but since I'll
be adding 3 more patches (even though trivial ones) I'd still appreciate one
more (final) review.
Erik