[libvirt] [PATCH 14/17] nwfilter: Add @refs logic to __virNWFilterObj

John Ferlan jferlan at redhat.com
Sun Jul 16 14:16:53 UTC 2017



On 07/13/2017 10:40 AM, Michal Privoznik wrote:
> On 06/02/2017 12:25 PM, John Ferlan wrote:
>> "Simple" conversion to the virObjectLockable object isn't quite possible
>> yet because the nwfilter lock requires usage of recursive locking due to
>> algorithms handing filter "<rule>"'s and "<filterref>"'s. The list search
>> logic would also benefit from using hash tables for lookups. So this patch
>> is step 1 in the process - add the @refs to _virNWFilterObj and modify the
>> algorithms to use (a temporary) virNWFilterObj{Ref|Unref} in order to set
>> things up for the list logic to utilize virObjectLockable hash tables.
>>
>> Signed-off-by: John Ferlan <jferlan at redhat.com>
>> ---
>>  src/conf/virnwfilterobj.c              | 75 ++++++++++++++++++++++++++--------
>>  src/conf/virnwfilterobj.h              | 15 ++++---
>>  src/libvirt_private.syms               |  5 ++-
>>  src/nwfilter/nwfilter_driver.c         | 13 +++---
>>  src/nwfilter/nwfilter_gentech_driver.c | 11 +++--
>>  5 files changed, 80 insertions(+), 39 deletions(-)
>>

FWIW: I've pushed 1, 4, and 8-13 since they were ACK. Since 2, 3, and
5-7 are being dropped and I want to insert a revert prior to here
(separate patch posted) - I'll respond to the queries from 14-17, but
they will get reposted as a v2 once the revert is in.

>> diff --git a/src/conf/virnwfilterobj.c b/src/conf/virnwfilterobj.c
>> index b21b570..99be59c 100644
>> --- a/src/conf/virnwfilterobj.c
>> +++ b/src/conf/virnwfilterobj.c
>> @@ -23,6 +23,7 @@
>>  #include "datatypes.h"
>>  
>>  #include "viralloc.h"
>> +#include "viratomic.h"
>>  #include "virerror.h"
>>  #include "virfile.h"
>>  #include "virlog.h"
>> @@ -33,8 +34,15 @@
>>  
>>  VIR_LOG_INIT("conf.virnwfilterobj");
>>  
>> +static void
>> +virNWFilterObjLock(virNWFilterObjPtr obj);
>> +
>> +static void
>> +virNWFilterObjUnlock(virNWFilterObjPtr obj);
>> +
>>  struct _virNWFilterObj {
>>      virMutex lock;
>> +    int refs;
>>  
>>      bool wantRemoved;
>>  
>> @@ -67,11 +75,24 @@ virNWFilterObjNew(virNWFilterDefPtr def)
>>  
>>      virNWFilterObjLock(obj);
>>      obj->def = def;
>> +    virAtomicIntSet(&obj->refs, 1);
> 
> Technically, this doesn't need to be virAtomic. Bare assignment would
> work as: a) the object is locked at this point, b) there's no other
> reference to the object (we are just creating the first one). But I'm
> fine with leaving this as is, just wanted to point out my comment.
> 

True, but in order to "show" the progression from point A to point B
*and* because of that recursive locking algorithm currently in place, I
essentially lifted code from virobject.c (this is from virObjectNew and
virObjectLockableNew).

>>  
>>      return obj;
>>  }
>>  
>>  
>> +void
>> +virNWFilterObjEndAPI(virNWFilterObjPtr *obj)
>> +{
>> +    if (!*obj)
>> +        return;
>> +
>> +    virNWFilterObjUnlock(*obj);
>> +    virNWFilterObjUnref(*obj);
>> +    *obj = NULL;
>> +}
>> +
>> +
>>  virNWFilterDefPtr
>>  virNWFilterObjGetDef(virNWFilterObjPtr obj)
>>  {
>> @@ -109,12 +130,33 @@ virNWFilterObjFree(virNWFilterObjPtr obj)
>>  }
>>  
>>  
>> +virNWFilterObjPtr
>> +virNWFilterObjRef(virNWFilterObjPtr obj)
>> +{
>> +    if (obj)
>> +        virAtomicIntInc(&obj->refs);
>> +    return obj;
>> +}
>> +
>> +
>> +bool
>> +virNWFilterObjUnref(virNWFilterObjPtr obj)
>> +{
>> +    bool lastRef;
>> +    if (obj)
>> +        return false;
> 
> This can hardly work. The condition needs to be inverted.
> 

Oh right....  Good eyes!  My testing wouldn't see it because I tested
the whole series which would essentially replace this.

>> +    if ((lastRef = virAtomicIntDecAndTest(&obj->refs)))
>> +        virNWFilterObjFree(obj);
>> +    return !lastRef;
>> +}
>> +
>> +
>>  void
>>  virNWFilterObjListFree(virNWFilterObjListPtr nwfilters)
>>  {
>>      size_t i;
>>      for (i = 0; i < nwfilters->count; i++)
>> -        virNWFilterObjFree(nwfilters->objs[i]);
>> +        virNWFilterObjUnref(nwfilters->objs[i]);
>>      VIR_FREE(nwfilters->objs);
>>      VIR_FREE(nwfilters);
>>  }
>> @@ -143,7 +185,7 @@ virNWFilterObjListRemove(virNWFilterObjListPtr nwfilters,
>>          virNWFilterObjLock(nwfilters->objs[i]);
>>          if (nwfilters->objs[i] == obj) {
>>              virNWFilterObjUnlock(nwfilters->objs[i]);
>> -            virNWFilterObjFree(nwfilters->objs[i]);
>> +            virNWFilterObjUnref(nwfilters->objs[i]);
>>  
>>              VIR_DELETE_ELEMENT(nwfilters->objs, i, nwfilters->count);
>>              break;
>> @@ -166,7 +208,7 @@ virNWFilterObjListFindByUUID(virNWFilterObjListPtr nwfilters,
>>          virNWFilterObjLock(obj);
>>          def = obj->def;
>>          if (!memcmp(def->uuid, uuid, VIR_UUID_BUFLEN))
>> -            return obj;
>> +            return virNWFilterObjRef(obj);
>>          virNWFilterObjUnlock(obj);
>>      }
>>  
>> @@ -187,7 +229,7 @@ virNWFilterObjListFindByName(virNWFilterObjListPtr nwfilters,
>>          virNWFilterObjLock(obj);
>>          def = obj->def;
>>          if (STREQ_NULLABLE(def->name, name))
>> -            return obj;
>> +            return virNWFilterObjRef(obj);
>>          virNWFilterObjUnlock(obj);
>>      }
>>  
>> @@ -210,7 +252,7 @@ virNWFilterObjListFindInstantiateFilter(virNWFilterObjListPtr nwfilters,
>>      if (virNWFilterObjWantRemoved(obj)) {
>>          virReportError(VIR_ERR_NO_NWFILTER,
>>                         _("Filter '%s' is in use."), filtername);
>> -        virNWFilterObjUnlock(obj);
>> +        virNWFilterObjEndAPI(&obj);
>>          return NULL;
> 
> Can we remove this "return NULL" line and rely on "return obj" which
> follow immediately (not to be seen in the context here though)?
> 

Sure that's fine, same result.

>>      }
>>  
>> @@ -245,7 +287,7 @@ _virNWFilterObjListDefLoopDetect(virNWFilterObjListPtr nwfilters,
>>              if (obj) {
>>                  rc = _virNWFilterObjListDefLoopDetect(nwfilters, obj->def,
>>                                                        filtername);
>> -                virNWFilterObjUnlock(obj);
>> +                virNWFilterObjEndAPI(&obj);
>>                  if (rc < 0)
>>                      break;
>>              }
>> @@ -338,10 +380,10 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>>                             _("filter with same UUID but different name "
>>                               "('%s') already exists"),
>>                             objdef->name);
>> -            virNWFilterObjUnlock(obj);
>> +            virNWFilterObjEndAPI(&obj);
>>              return NULL;
>>          }
>> -        virNWFilterObjUnlock(obj);
>> +        virNWFilterObjEndAPI(&obj);
>>      } else {
>>          if ((obj = virNWFilterObjListFindByName(nwfilters, def->name))) {
>>              char uuidstr[VIR_UUID_STRING_BUFLEN];
>> @@ -351,7 +393,7 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>>              virReportError(VIR_ERR_OPERATION_FAILED,
>>                             _("filter '%s' already exists with uuid %s"),
>>                             def->name, uuidstr);
>> -            virNWFilterObjUnlock(obj);
>> +            virNWFilterObjEndAPI(&obj);
>>              return NULL;
>>          }
>>      }
>> @@ -362,7 +404,6 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>>          return NULL;
>>      }
>>  
>> -
>>      if ((obj = virNWFilterObjListFindByName(nwfilters, def->name))) {
>>  
>>          objdef = obj->def;
> 
> I've got an unrelated question: here, after this line you can find the
> following code:
> 
>         if (virNWFilterDefEqual(def, objdef, false)) {
>             virNWFilterDefFree(objdef);
>             obj->def = def;
>             return obj;
>         }
> 
> Firstly, I think we can s/false/true/ because if UUIDs were not the
> same, we would have errored out way sooner. But more importantly, if
> definition is equal what's the point in replacing it?
> 

Let's see, looks like commit id '46a811db07' added the if we cannot find
by UUID, then let's find by Name and if the name exists, then cause
failure because we have a defined Name with a different UUID.

But it didn't adjust this algorithm; however, rather than change to
passing true, since this is the only caller, the @cmpUUIDs should be
removed from virNWFilterDefEqual.  In a separate followup patch of course.

As noted above - I'll fix stuff up here, add the patch, and post a v2

Tks -

John

>> @@ -376,7 +417,7 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>>          /* trigger the update on VMs referencing the filter */
>>          if (virNWFilterTriggerVMFilterRebuild() < 0) {
>>              obj->newDef = NULL;
>> -            virNWFilterObjUnlock(obj);
>> +            virNWFilterObjEndAPI(&obj);
>>              return NULL;
>>          }
>>  
>> @@ -397,12 +438,12 @@ virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>>      if (VIR_APPEND_ELEMENT_COPY(nwfilters->objs, nwfilters->count, obj) < 0)
>>          goto error;
>>  
>> -    return obj;
>> +    return virNWFilterObjRef(obj);
>>  
>>   error:
>>      obj->def = NULL;
>>      virNWFilterObjUnlock(obj);
>> -    virNWFilterObjFree(obj);
>> +    virNWFilterObjUnref(obj);
>>      return NULL;
>>  }
>>  
>> @@ -600,8 +641,8 @@ virNWFilterObjListLoadAllConfigs(virNWFilterObjListPtr nwfilters,
>>              continue;
>>  
>>          obj = virNWFilterObjListLoadConfig(nwfilters, configDir, entry->d_name);
>> -        if (obj)
>> -            virNWFilterObjUnlock(obj);
>> +
>> +        virNWFilterObjEndAPI(&obj);
>>      }
>>  
>>      VIR_DIR_CLOSE(dir);
>> @@ -609,14 +650,14 @@ virNWFilterObjListLoadAllConfigs(virNWFilterObjListPtr nwfilters,
>>  }
>>  
>>  
>> -void
>> +static void
>>  virNWFilterObjLock(virNWFilterObjPtr obj)
>>  {
>>      virMutexLock(&obj->lock);
>>  }
>>  
>>  
>> -void
>> +static void
>>  virNWFilterObjUnlock(virNWFilterObjPtr obj)
>>  {
>>      virMutexUnlock(&obj->lock);
>> diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h
>> index 85c8ead..31aa345 100644
>> --- a/src/conf/virnwfilterobj.h
>> +++ b/src/conf/virnwfilterobj.h
>> @@ -41,6 +41,9 @@ struct _virNWFilterDriverState {
>>      bool watchingFirewallD;
>>  };
>>  
>> +void
>> +virNWFilterObjEndAPI(virNWFilterObjPtr *obj);
>> +
>>  virNWFilterDefPtr
>>  virNWFilterObjGetDef(virNWFilterObjPtr obj);
>>  
>> @@ -50,6 +53,12 @@ virNWFilterObjGetNewDef(virNWFilterObjPtr obj);
>>  bool
>>  virNWFilterObjWantRemoved(virNWFilterObjPtr obj);
>>  
>> +virNWFilterObjPtr
>> +virNWFilterObjRef(virNWFilterObjPtr obj);
>> +
>> +bool
>> +virNWFilterObjUnref(virNWFilterObjPtr obj);
>> +
> 
> ACK
> 
> Michal
> 




More information about the libvir-list mailing list