On 06/29/2017 10:28 AM, Erik Skultety wrote:
On Thu, Jun 29, 2017 at 09:57:09AM -0400, John Ferlan wrote:
>
>
> On 06/29/2017 08:12 AM, Erik Skultety wrote:
>> On Sat, Jun 03, 2017 at 09:11:51AM -0400, John Ferlan wrote:
>>> Rather than passing the object to be removed by reference, pass by value
>>> and then let the caller decide whether or not the object should be
free'd.
>>> This function should just handle the remove of the object from the list
>>> for which it was placed during virNodeDeviceObjAssignDef.
>>>
>>> One caller in node_device_hal would fail to go through the dev_create path
>>> since the @dev would have been NULL after returning from the Remove API.
>>
>> This is the main motivation for the patch I presume - in which case, I'm
>> wondering why do we actually have to remove the device from the list when
>> handling 'change'/'update' for hal instead of just replacing the
->def with a
>> new instance but it's perfectly fine to do that for udev...I don't see
the
>> point in doing what we currently do for hal.
>>
>> [...]
>
> The main motivation is that in the previous review pass there was a
> "dislike" of passing the pointer to a pointer for something else I
> changed, see:
>
>
https://www.redhat.com/archives/libvir-list/2017-May/msg01074.html
>
> Also the initial pass at altering this function was questioned, see:
>
>
https://www.redhat.com/archives/libvir-list/2017-May/msg01001.html
>
Well, that comment is true, but the commit message of this patch says that it
drops the requirement of passing by reference, thus leaving the responsibility
to free the obj to the caller. Now, the way I see it what we should aim at
achieving here is reference counted objects, so the vir*ObjFree in the caller
would become and *Unref. Therefore IMHO it's not the best approach to introduce
another boolean for HAL and leave the vir*ObjFree in the Remove routine, you
wouldn't be clearing the object for the caller anyway, so I don't think that is
the way to go.
I actually think the better course of action is to be more like the
other functions. I believe virNodeDeviceObjRemove should do the
virNodeDeviceObjFree for the simple reason that *ObjAssignDef does the
alloc and list insertion and *Remove is the antecedent doing the list
removal and free. I will adjust the commit message and can even add
comments prior to the function (if desired; however, it'll eventually be
just a wrapper to a more generic object function).
Also, light has dawned over marble head and for hal's dev_refresh the
logic will then work correctly anyway since &dev wouldn't be set to
NULL. The code doesn't reference data in @dev. All that is important is
that @dev was found and removed. Still adding a bool rediscover just
makes it more obvious for the next poor soul tripping across this code.
If you search through history, you'll find that commit '611480747'
introduced this hal dev_refresh anomaly in order to fix a problem in
testNodeDeviceDestroy that @obj would not be present. Instead of setting
obj = NULL; after calls, the usage of &dev was introduced. I'm undoing
that and taking the other approach to set the removed @dev = NULL; (all
that during a freeze, too!).
See the quagmire this convergence creates ;-)
Anyway, I've attached a patch that should be able to be git am'd on top
of this one. It will cause merge conflicts in the rest of the series...
John
> So I took the approach that this code could/should follow other
API's. I
> used cscope and found other similar functions via "vir.*Obj.*Remove" on
> the "Find this global definition:" - that led me to 7 functions.
I went for basically every module equivalent of this. So the unnecessary lock
dance just to compare pointers could be a fairly straightforward follow-up
patch across multiple modules if they're consistent.
>
> Of those Interface, NWFilter, and StoragePool each used this forward
> linked list in a similar manner - so that's what I changed this model to
> be. As an aside, nwfilterDefineXML can call virNWFilterObjListRemove,
I won't comment on NWFilter as I'm not familiar with it at all.
>
> In hindsight, perhaps I should have solved this by setting a boolean to
> force calling dev_create(udi) rather than having/forcing each caller to
> handle calling virNodeDeviceObjFree.
See my comment above, I think that would be a step back in what we're trying to
achieve here (comparing it also with other OO languages' practice in this
aspect).
>>> /* Simply "rediscover" device -- incrementally handling
changes
>>> * to sub-capabilities (like net.80203) is nasty ... so avoid it.
>>> */
>>> - virNodeDeviceObjRemove(&driver->devs, &dev);
>>> + virNodeDeviceObjRemove(&driver->devs, dev);
>>
>> I guess now that freeing '@dev' is caller's responsibility, you want
to free it
>> on function exit after you checked that you actually want to recreate the
>> device - I already expressed my opinion about this above.
>>
>
> I'd like to ignore or get rid of the hal code ;-)
Who wouldn't, honestly...
>
> I think (now) the better option would be to have virNodeDeviceObjRemove
> make the virNodeDeviceObjFree call as well and have this one caller just
> know that it ran through this code path in order to force calling
> dev_create() after releasing the node device lock.
>
> Does that seem like a better option?
From my perspective, not really (but I might be wrong of course, wouldn't be
the first nor the last time).
>
>> ACK with @dev also freed in hal backend. I'd also like to hear your opinion
on
>> calling *AssignDef directly from hal's dev_refresh rather than first
removing
>> the device from the list completely.
>>
>> Erik
>>
>
> I suppose that's possible, but the comment above the call to
> virNodeDeviceObjRemove similar scares the sh*t out of me ;-)
It just needs a bit of love....and a bunch of cups of coffee ;)...and a
platform to test.
Erik