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

Daniel Veillard veillard at redhat.com
Tue Dec 2 10:15:52 UTC 2008


On Sun, Nov 30, 2008 at 11:47:21PM +0000, Daniel P. Berrange wrote:
> 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

  I must admit I'm a bit lost ...

> @@ -192,14 +291,18 @@ virDomainEventQueueFree(virDomainEventQu
>  virDomainEventQueueFree(virDomainEventQueuePtr queue)
>  {
>      int i;
> -    for ( i=0 ; i<queue->count ; i++ ) {
> -        VIR_FREE(queue->events[i]);
> +    if (!queue)
> +        return;
> +
> +    for (i = 0; i < queue->count ; i++) {
> +        virDomainEventFree(queue->events[i]);
>      }
> +    VIR_FREE(queue->events);
>      VIR_FREE(queue);
>  }

  okay we were leaking queue->events here !

[...]
>  struct _virDomainEventCallback {
>      virConnectPtr conn;
>      virConnectDomainEventCallback cb;
>      void *opaque;
>      virFreeCallback freecb;
> -
> +    int deleted;
>  };

  Yup, I'm lost here ... seems we are making something asynchronous here

>  struct _virDomainEvent {
> -    virDomainPtr dom;
> -    int event;
> +    int id;
> +    char *name;
> +    unsigned char uuid[VIR_UUID_BUFLEN];
> +    int type;
>      int detail;
>  };

  Okay we don't want to held references anymore. But the lookups will
require search and locking, I completely fail to build a mental
representation where I can figure out why we don't risk deadlocks there.
There is a risk of lock reentrancy I'm sure but I can't see the model.

[...]
> 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
> @@ -382,9 +382,21 @@ LIBVIRT_PRIVATE_ at VERSION@ {
>  	virDomainEventCallbackListFree;
>  	virDomainEventCallbackListRemove;
>  	virDomainEventCallbackListRemoveConn;
> +	virDomainEventCallbackListMarkDelete;
> +	virDomainEventCallbackListPurgeMarked;
> +	virDomainEventQueueNew;
>  	virDomainEventQueueFree;
> -	virDomainEventCallbackQueuePop;
> -	virDomainEventCallbackQueuePush;
> +	virDomainEventQueuePop;
> +	virDomainEventQueuePush;
> +	virDomainEventNew;
> +	virDomainEventNewFromDom;
> +	virDomainEventNewFromObj;
> +	virDomainEventNewFromDef;
> +	virDomainEventFree;
> +	virDomainEventDispatchDefaultFunc;
> +	virDomainEventDispatch;
> +	virDomainEventQueueDispatch;
> +

  reminds me I need to make room in libvirt_sym.version.in for APIs
introduced post 0.5.0, I have the (trivial) patch, will post it asap.

   I'm lost, I failed to figure out most of the remaining of this patch,
but don't consider this a blocker, ...
   Still I'm worried about the increased complexity of the code and
making harder for people to contribute patches or drivers.

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list