Re: [PATCH 8/19]: SCST SYSFS interface implementation

From: Joe Eykholt
Date: Wed Nov 10 2010 - 15:42:09 EST




On 11/10/10 12:29 PM, Joe Eykholt wrote:
>
>
> On 11/10/10 12:19 PM, Vladislav Bolkhovitin wrote:
>> Boaz Harrosh, on 11/10/2010 12:58 PM wrote:
>>> On 11/09/2010 10:06 PM, Vladislav Bolkhovitin wrote:
>>>>
>>>> Sorry, but what is incorrect in the working implementation without any
>>>> bugs doing its job in the simplest, smallest and clearest way?
>>>>
>>>> If those objects remade to free themselves in the kobjects release(),
>>>> what value would it add to them? Would the implementation be simpler,
>>>> smaller or clearer? Not, I believe, new implementation would be only
>>>> bigger and less clear. So, what's the point to do it to make the code worse?
>>>>
>>>
>>> Totally theoretically speaking, since I have not inspected the code.
>>>
>>> If today you wait for the count to reach zero, then unregister
>>> and send an event to some other subsystem to free the object.
>>>
>>> Is it not the same as if you take an extra refcount, unregister and
>>> send the event at count=1. Then at that other place decrement the last
>>> count to cause the object to be freed.
>>>
>>> I agree that it is hard to do lockless. what some places do is have
>>> an extra kref. The kobj has a single ref on it. everything takes the
>>> other kref. when that reaches zero the unregister and event fires
>>> and at free you decrement the only kobj ref to deallocate. This is one
>>> way. In some situations you can manage with a single counter it all
>>> depends.
>>
>> Thanks for sharing your thoughts with us. But the question isn't about
>> if it's possible to implement what we need locklessly. The question is
>> in two approaches how to synchronously delete objects with entries on SYSFS:
>>
>> 1. struct object_x {
>> ...
>> struct kobject kobj;
>> struct completion *release_completion;
>> };
>>
>> static void x_release(struct kobject *kobj)
>> {
>> struct object_x *x;
>> struct completion *c;
>>
>> x = container_of(kobj, struct object_x, kobj);
>> c = x->release_completion;
>> kfree(x);
>> complete_all(c);
>> }
>>
>> void del_object(struct object_x *x)
>> {
>> DECLARE_COMPLETION_ONSTACK(completion);
>>
>> ...
>> x->release_completion = &completion;
>> kobject_put(&x->kobj);
>> wait_for_completion(&completion);
>> }
>>
>> and
>>
>> 2. struct object_x {
>> ...
>> struct kobject kobj;
>> struct completion release_completion;
>> };
>>
>> static void x_release(struct kobject *kobj)
>> {
>> struct object_x *x;
>>
>> x = container_of(kobj, struct object_x, kobj);
>> complete_all(&x->release_completion);
>> }
>>
>> void del_object(struct object_x *x)
>> {
>> ...
>> kobject_put(&x->kobj);
>> wait_for_completion(&completion);
>> ...
>> kfree(x);
>> }
>
> I'll admit I don't understand this all that well, but
> why not just have x_release() (based on (2))
> do free(x), and have del_object
> do the kobject_put(&x->kobj) as its very last thing?
> Then you don't need the completion.

Ah, well to answer my own question, I guess that's (1).
Never mind.

Joe

>> Greg asserts that (1) is the only correct approach while (2) is
>> incorrect, and I'm trying to justify that (2) is correct too and
>> sometimes could be better, i.e. simpler and clearer, because it
>> decouples object_x from SYSFS and its kobj. Then kobj becomes an
>> ordinary member of struct object_x without any special treatment and
>> with the same lifetime rules as other members of struct object_x. While
>> in (1) all lifetime of struct object_x is strictly attached to kobj, so
>> it needs be specially handled with additional code for that if struct
>> object_x has many other members which needed to be initialized/deleted
>> _before and after_ kobj as we have in SCST.
>>
>> Vlad
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/