tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Fileassoc locking
On Dec,Saturday 26 2009, at 2:33 AM, Elad Efrat wrote:
> On Fri, Dec 25, 2009 at 7:50 PM, Adam Hamsik <haaaad%gmail.com@localhost>
> wrote:
>
>> RW locks have some performance problems, and they should not be used until
>> it's needed. I think that same think can be accomplished by using reference
>> counters and mutexes/cv variables. You can look at dm_dev_t I have used same
>> approach there. Rw locks has very bad effect on CPU caches and can slow
>> things down on a bigger SMP systems.
>
> I didn't think it was this bad... Okay, I'll have a look and try to
> redo it using mutexes and condition variables.
>
>> Also it would be good to describe locking protocol used in fileassoc on top
>> of this file
>
> Once it's done...
>
>>> +/* Expects faf writer-locked. */
>>> static void
>>> file_free(struct fileassoc_file *faf)
>>> {
>>> @@ -126,11 +134,19 @@ file_free(struct fileassoc_file *faf)
>>>
>>> LIST_REMOVE(faf, faf_list);
>>>
>>> + rw_enter(&fileassoc_list_lock, RW_READER);
>>> LIST_FOREACH(assoc, &fileassoc_list, assoc_list) {
>>> + rw_enter(&assoc->assoc_lock, RW_READER);
>>> file_cleanup(faf, assoc);
>>> + rw_exit(&assoc->assoc_lock);
>>> }
>>> + rw_exit(&fileassoc_list_lock);
>>> +
>>> vfs_composefh_free(faf->faf_handle);
>>> specificdata_fini(fileassoc_domain, &faf->faf_data);
>>> +
>>> + rw_exit(&faf->faf_lock);
>>> +
>>
>> Where faf->faf_lock was entered here ?
>
> file_free() expects it to be locked -- see comment.
Locking structure in one routine and then releasing it in other is not standard
behavior. I think that you should revisit it. In best case you should do
mutex_enter(foo) and mutex_exit(foo) in same routine not in two or more.
>>> + rw_init(&assoc->assoc_lock);
>>>
>>> + /* Lock it so no one can use this assoc until we're done. */
>>> + rw_enter(&assoc->assoc_lock, RW_WRITER);
>>> +
>>> + rw_enter(&fileassoc_list_lock, RW_WRITER);
>>> LIST_INSERT_HEAD(&fileassoc_list, assoc, assoc_list);
>>> + rw_exit(&fileassoc_list_lock);
>>> +
>>> + rw_exit(&assoc->assoc_lock);
>>>
>>
>> With one mutex used for fileassoc_list_lock you do not need to do this dance
>> you jsut lock mutex, insert head, unlock.
>
> I have removed the locking on "assoc" here. There's going to be a
> favorable reader:writer ratio forfileassoc_list_lock -- should it
> still be a mutex?
I think that mutexes are much cheaper then rw locks in locking. bu you should
hold mutex on fileassoc_list_lock only for absolutely required time (you should
not do any heavy operations like, memory allocation, memory free etc.)
>
>> If function returns locked tbl it should be documented somewhere in this
>> file.
>
> Comments added where necessary...
>
>>> - return file_getdata(faf, assoc);
>>> + rw_enter(&assoc->assoc_lock, RW_READER);
>>> + data = file_getdata(faf, assoc);
>>> + rw_exit(&assoc->assoc_lock);
>>> +
>>> + rw_exit(&faf->faf_lock);
>>> +
>>> + return data;
>>
>> Here you return pointer for assoc data but, this can be released/freed by
>> another thread while caller of this will sleep. With reference counting you
>> will hold reference counter on assoc/data and no one can change them until
>> he has last reference holding by himself.
>
> I think maybe to make fileassoc_lookup() always increase the reference
> count on the file entry before it returns, and require the caller
> (user of the KPI) to fileassoc_release() once it's done to avoid the
> data being freed while in use.
Yes this seems like a good approach to me. protocol can be
mutex_enter(faf_list)
... find faf ...
mutex_enter(faf)
increase ref counter
mutex_exit(faf)
mutex_exit(faf_list)
But you need to be sure that there is no other code who is doing mutex_enter on
faf_list and faf locks in a reversed order.
>> Maybe you should post whole file somewhere because it's hard to review your
>> changes this way because they are too large.
>
> I'll do that in future posts.
>
> Thanks,
>
> -e.
Regards
Adam.
Home |
Main Index |
Thread Index |
Old Index