[libvirt] [PATCH] nwfilter: reorder locks

Stefan Berger stefanb at linux.vnet.ibm.com
Thu May 19 11:46:55 UTC 2011


Any comments?

    Stefan

On 05/11/2011 04:36 PM, Stefan Berger wrote:
> This patch reorders the locks for the nwfilter updates and the access 
> the nwfilter objects. In the case that the IP address learning thread 
> was instantiating filters while an update happened, the previous order 
> lead to a deadlock.
>
> I am also adding a text file describing the locking order of the 
> nwfilter subsystem.
>
> Signed-off-by: Stefan Berger <stefanb at us.ibm.com>
>
> ---
>  src/conf/nwfilter_conf.c       |    9 ++++----
>  src/nwfilter/locking.txt       |   45 
> +++++++++++++++++++++++++++++++++++++++++
>  src/nwfilter/nwfilter_driver.c |    4 +++
>  3 files changed, 54 insertions(+), 4 deletions(-)
>
> Index: libvirt-acl/src/conf/nwfilter_conf.c
> ===================================================================
> --- libvirt-acl.orig/src/conf/nwfilter_conf.c
> +++ libvirt-acl/src/conf/nwfilter_conf.c
> @@ -2440,15 +2440,13 @@ virNWFilterTestUnassignDef(virConnectPtr
>  {
>      int rc = 0;
>
> -    virNWFilterLockFilterUpdates();
> -
>      nwfilter->wantRemoved = 1;
>      /* trigger the update on VMs referencing the filter */
>      if (virNWFilterTriggerVMFilterRebuild(conn))
>          rc = 1;
>
>      nwfilter->wantRemoved = 0;
> -    virNWFilterUnlockFilterUpdates();
> +
>      return rc;
>  }
>
> @@ -2480,8 +2478,9 @@ virNWFilterObjAssignDef(virConnectPtr co
>          return NULL;
>      }
>
> +    virNWFilterLockFilterUpdates();
> +
>      if ((nwfilter = virNWFilterObjFindByName(nwfilters, def->name))) {
> -        virNWFilterLockFilterUpdates();
>          nwfilter->newDef = def;
>          /* trigger the update on VMs referencing the filter */
>          if (virNWFilterTriggerVMFilterRebuild(conn)) {
> @@ -2498,6 +2497,8 @@ virNWFilterObjAssignDef(virConnectPtr co
>          return nwfilter;
>      }
>
> +    virNWFilterUnlockFilterUpdates();
> +
>      if (VIR_ALLOC(nwfilter) < 0) {
>          virReportOOMError();
>          return NULL;
> Index: libvirt-acl/src/nwfilter/nwfilter_driver.c
> ===================================================================
> --- libvirt-acl.orig/src/nwfilter/nwfilter_driver.c
> +++ libvirt-acl/src/nwfilter/nwfilter_driver.c
> @@ -372,6 +372,8 @@ nwfilterUndefine(virNWFilterPtr obj) {
>      nwfilterDriverLock(driver);
>      virNWFilterCallbackDriversLock();
>
> +    virNWFilterLockFilterUpdates();
> +
>      nwfilter = virNWFilterObjFindByUUID(&driver->nwfilters, obj->uuid);
>      if (!nwfilter) {
>          virNWFilterReportError(VIR_ERR_NO_NWFILTER,
> @@ -399,6 +401,8 @@ cleanup:
>      if (nwfilter)
>          virNWFilterObjUnlock(nwfilter);
>
> +    virNWFilterUnlockFilterUpdates();
> +
>      virNWFilterCallbackDriversUnlock();
>      nwfilterDriverUnlock(driver);
>      return ret;
> Index: libvirt-acl/src/nwfilter/locking.txt
> ===================================================================
> --- /dev/null
> +++ libvirt-acl/src/nwfilter/locking.txt
> @@ -0,0 +1,45 @@
> +NWfilter locks:
> +---------------
> +
> +The following NWFilter functions grab locks:
> +
> +- nwfilterDriverLock(driverState)
> +   - protects driverState
> +- virNWFilterCallbackDriversLock()
> +   - lock access to callback drivers
> +- virNWFilterLockFilterUpdates()
> +   - prevent modification of any filter in use by any VM
> +- virNWFilterObjLock()
> +    called by
> +      - virNWFilterObjFindByUUID(),
> +      - virNWFilterObjFindByName(),
> +      - virNWFilterObjAssignDef()
> +    and the functions return with the lock held
> +
> +
> +NWFilter-Lock ordering:
> +-----------------------
> +
> +Order in which the NWFilter lock functions have to be called:
> +
> +1. nwFilterDriverLock
> +2. virNWFilterCallbackDriversLock
> +3. virNWFilterLockFilterUpdates
> +4. virNWFilterObjLock
> +
> +Other locks:
> +------------
> +
> +Other relevant locks to consider are related to hypervisor drivers. The
> +following locking orders are good with the qemu_driver as an example:
> +
> +qemu_driver - qemu_domain   - filter object
> +qemu_driver - filter object - qemu_domain
> +
> +The qemu_driver serves as a general lock for all subsequent locks to a
> +qemu_domain. This works because the qemu_driver will always be locked
> +for a qemu_domain, thus only one lock-sequence of either (qemu_domain,
> +filter object) or (filter object, qemu_domain) can be active at any 
> time.
> +
> +Reference:
> +https://www.redhat.com/archives/libvir-list/2010-October/msg00152.html
>
> -- 
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list




More information about the libvir-list mailing list