[libvirt] [PATCH v3] interfaces: Convert virInterfaceObjList to virObjectRWLockable
Erik Skultety
eskultet at redhat.com
Thu Oct 19 15:54:46 UTC 2017
On Thu, Oct 19, 2017 at 10:48:56AM -0400, John Ferlan wrote:
>
>
> On 10/19/2017 10:07 AM, Erik Skultety wrote:
> > On Fri, Oct 13, 2017 at 07:45:01AM -0400, John Ferlan wrote:
> >> Rather than a forward linked list, let's use the ObjectRWLockable object
> >> in order to manage the data.
> >>
> >> Requires numerous changes from List to Object management similar to
> >> many other drivers/vir*obj.c modules
> >>
> >
> > This patch should be split in two. One that converts it to RWLockable, the
> > other using a hash table instead of a linked list.
> >
> > [...]
>
> Personally, I don't recall during various conversions I've done to having:
>
> virObjectLockable parent;
>
> size_t count;
> virInterfaceObjPtr *objs;
>
> first, then converting to count/objs to (a) hash table(s). Although
> looking through history I see Michal had the networkobj code take a long
> winding path to get there, so it's not impossible - just IMO pointless.
>
> I think whenever I've converted from count/obs to a hash table with a
> 'real object', that the locking was done a the same time.
>
> As I recall, usually it's been converting from :
>
> size_t count;
> virInterfaceObjPtr *objs;
>
> to:
>
> virObjectLockable parent;
>
> /* name string -> virInterfaceObj mapping
> * for O(1), lockless lookup-by-name */
> virHashTable *objsName;
>
> then more recently the conversion from virObjectLockable to
> virObjectRWLockable
>
> Since this patch is taking @objs and converting to a hash table - it's
> avoiding the Lockable and going straight to RWLockable.
>
> >>
> >> @@ -253,9 +334,11 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
> >> {
> >> virInterfaceObjPtr obj;
> >>
> >> - if ((obj = virInterfaceObjListFindByName(interfaces, def->name))) {
> >> + virObjectRWLockWrite(interfaces);
> >> + if ((obj = virInterfaceObjListFindByNameLocked(interfaces, def->name))) {
> >> virInterfaceDefFree(obj->def);
> >> obj->def = def;
> >> + virObjectRWUnlock(interfaces);
> >>
> >> return obj;
> >> }
> >> @@ -263,13 +346,19 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
> >> if (!(obj = virInterfaceObjNew()))
> >> return NULL;
> >>
> >> - if (VIR_APPEND_ELEMENT_COPY(interfaces->objs,
> >> - interfaces->count, obj) < 0) {
> >> - virInterfaceObjEndAPI(&obj);
> >> - return NULL;
> >> - }
> >> + if (virHashAddEntry(interfaces->objsName, def->name, obj) < 0)
> >> + goto error;
> >> + virObjectRef(obj);
> >> +
> >> obj->def = def;
> >> - return virObjectRef(obj);
> >> + virObjectRWUnlock(interfaces);
> >> +
> >> + return obj;
> >> +
> >> + error:
> >> + virInterfaceObjEndAPI(&obj);
> >> + virObjectRWUnlock(interfaces);
> >> + return NULL;
> >> }
> >
> > ^This could be tweaked even more:
> >
>
> Sure, but in doing so eagle eyes now spots a problem in his own code...
>
>
> > diff --git a/src/conf/virinterfaceobj.c b/src/conf/virinterfaceobj.c
> > index cf3626def..941893fc5 100644
> > --- a/src/conf/virinterfaceobj.c
> > +++ b/src/conf/virinterfaceobj.c
> > @@ -337,19 +337,15 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
> > virObjectRWLockWrite(interfaces);
> > if ((obj = virInterfaceObjListFindByNameLocked(interfaces, def->name))) {
> > virInterfaceDefFree(obj->def);
> > - obj->def = def;
> > - virObjectRWUnlock(interfaces);
> > + } else {
> > + if (!(obj = virInterfaceObjNew()))
> > + return NULL;
>
> Leaving with RWLock, <sigh>
>
> >
> > - return obj;
> > + if (virHashAddEntry(interfaces->objsName, def->name, obj) < 0)
> > + goto error;
> > + virObjectRef(obj);
> > }
> >
> > - if (!(obj = virInterfaceObjNew()))
> > - return NULL;
> > -
> > - if (virHashAddEntry(interfaces->objsName, def->name, obj) < 0)
> > - goto error;
> > - virObjectRef(obj);
> > -
> > obj->def = def;
> > virObjectRWUnlock(interfaces);
> >
> >>
> >>
> >> @@ -277,20 +366,37 @@ void
> >> virInterfaceObjListRemove(virInterfaceObjListPtr interfaces,
> >> virInterfaceObjPtr obj)
> >> {
> >> - size_t i;
> >
> > if (!obj)
> > return;
> >
>
> OK - I think at some point in time I figured it wasn't possible, but
> adding it doesn't hurt. It's there in my branch.
>
> > I didn't bother to check whether it could happen (it's used in test driver only
> > anyway), but just in case there's an early cleanup exit path like it was in my
> > recent nodedev code which was missing this very check too which would have made
> > it fail miserably in such scenario.
> >
> > With the patch split in 2 introducing 2 distinct changes + the NULL check:
> > Reviewed-by: Erik Skultety <eskultet at redhat.com>
>
> Hopefully you reconsider the desire for 2 patches...
Well, since I was apparently fine with the change when reviewing the same
changes to nodedev, I guess I should be fine with it now too, I don't know what
made me change my opinion as time has passed, nevermind, it's not a deal breaker
for me.
>
> >
> >
> > PS: I'm also sad, that we have two backends here just like we have in nodedev
> > with one of them being essentially useless (just like in nodedev) we have this
> > 'conf' generic code (just like in nodedev), yet in this case it's only used in
> > the test driver. I'd very much appreciate if those backends could be adjusted
> > in a way where we could make use of these functions. I can also imagine a
> > cooperation of the udev backend with the nodedev driver where we have an active
> > connection to the monitor, thus reacting to all events realtime, instead of
> > defining a bunch of filters and then letting udev re-enumerate the list of
> > interfaces each and every time (and by saying that I'm also aware that udev is
> > actually the useless backend here).
> >
> > Erik
> >
>
> Yeah - the driver code here is quite different/strange and could
> possibly use a bit more convergence. I feel too battered and bruised
> over this convergence right now though ;-).... Besides the differences
I hope it didn't sound like a request, it was meant to be more like a wish that
we should do something about it (sometime).
Erik
> between the two really kind of are a bit scary w/r/t needing to call
> some sort of netcf* or udev* interface to get the answers.
>
> John
More information about the libvir-list
mailing list