[libvirt PATCH v2] nwfilter: merge updateMutex and updateLock

Michal Prívozník mprivozn at redhat.com
Fri Mar 18 10:45:26 UTC 2022


On 3/17/22 16:30, Daniel P. Berrangé wrote:
> The updateLock is a R/W lock held by anything which needs to read or
> modify the rules associated with an NWFilter.
> 
> APIs for defining/undefining NW filters rules hold a write lock on
> updateLock.
> 
> APIs for creating/deleting NW filter bindings hold a read lock on
> updateLock, which prevents define/undefine taking place concurrently.
> 
> The problems arise when we attempt to creating two NW filter bindings in
> parallel.
> 
> Thread 1 can acquire the mutex for filter A
> 
> Thread 2 can acquire the mutex for filter B
> 
> Consider if filters A and B both reference filters C and D, but in
> different orders:
> 
>   Filter A
>      -> filter C
>      -> filter D
> 
>   Filter B
>      -> filter D
>      -> filter C
> 
> Thread 1 will try to acquire locks in order A, C, D while thread 1 will
> try to acquire in order A, D, C. Deadlock can still occur.
> 
> Think we can sort the list of filters before acquiring locks on all of
> them ? Nope, we allow arbitrary recursion:
> 
>   Filter A
>      -> filter C
>           -> filter E
>              -> filter F
>                 -> filter H
>                 -> filter K
>      -> filter D
>          -> filter G
>          -> filter I
> 
> So we can't tell from looking at 'A' which filters we're going to
> need to lock. We can only see the first level of filters references
> and we need to lock those before we can see the second level of
> filters, etc.
> 
> We could probably come up with some cleverness to address this but
> it isn't worth the time investment. It is simpler to just keep the
> process of creating NW filter bindings totally serialized.
> 
> Using two separate locks for this serialization though is pointless.
> 
> Every code path which gets a read(updateLock) will go on to hold
> updateMutex. It is simpler to just hold write(updateLock) and
> get rid of updateMutex. At that point we don't need updateLock
> to be a R/W lock, it can be a plain mutex.
> 
> Thus this patch gets rid of the current updateLock and updateMutex
> and introduces a new top level updateMutex.
> 
> This has a secondary benefit of introducing fairness into the
> locking.  With a POSIX R/W lock, you get writer starvation if
> you have lots of readers. IOW, if we call virNWFilterBIndingCreate
> and virNWFilterBindingDelete in a tight loop from a couple of
> threads, we can prevent virNWFilterDefine from ever acquiring
> a write lock.
> 
> Getting rid of the R/W lock gives us FIFO lock acquisition
> preventing starvation of any API call servicing.
> 
> Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
> ---
>  src/conf/nwfilter_conf.c               | 33 +---------
>  src/conf/nwfilter_conf.h               |  9 ---
>  src/conf/virnwfilterobj.h              |  3 +
>  src/libvirt_private.syms               |  3 -
>  src/nwfilter/nwfilter_driver.c         | 77 ++++++++++++------------
>  src/nwfilter/nwfilter_gentech_driver.c | 83 +++-----------------------
>  6 files changed, 52 insertions(+), 156 deletions(-)

Reviewed-by: Michal Privoznik <mprivozn at redhat.com>

Michal



More information about the libvir-list mailing list