Re: [PATCH v2 08/20] fsnotify: generalize iteration of marks by object type

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 17, 2018 at 8:01 PM, Jan Kara <jack@xxxxxxx> wrote:
> On Thu 05-04-18 16:18:09, Amir Goldstein wrote:
>> Make some code that handles marks of object types inode and vfsmount
>> generic, so it can handle other object types.
>>
>> Introduce foreach_obj_type macros to iterate marks by object type
>> with or without consulting a type mask.
>>
>> This is going to be used for adding mark of another object type
>> (super block mark).
>>
>> Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx>
>> ---
>>  fs/notify/fsnotify.c             | 54 ++++++++++++++++++++++++----------------
>>  fs/notify/mark.c                 | 23 +++++++++++------
>>  include/linux/fsnotify_backend.h | 38 +++++++++++++++++++++-------
>>  3 files changed, 76 insertions(+), 39 deletions(-)
>>
>> diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
>> index 665f681dd913..1759121db50d 100644
>> --- a/fs/notify/fsnotify.c
>> +++ b/fs/notify/fsnotify.c
>> @@ -263,21 +263,31 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
>>  /*
>>   * iter_info is a multi head priority queue of marks.
>>   * fsnotify_iter_first() picks a subset of marks from queue heads, all with the
>> - * same priority and clears the type_mask for other marks.
>> + * same group and clears the type_mask for other marks.
>>   * Returns the type_mask of the chosen subset.
>>   */
>>  static unsigned int fsnotify_iter_first(struct fsnotify_iter_info *iter_info)
>>  {
>> -     struct fsnotify_mark *inode_mark = iter_info->inode_mark;
>> -     struct fsnotify_mark *vfsmount_mark = iter_info->vfsmount_mark;
>> -
>> -     if (inode_mark && vfsmount_mark) {
>> -             int cmp = fsnotify_compare_groups(inode_mark->group,
>> -                                               vfsmount_mark->group);
>> -             if (cmp > 0)
>> -                     iter_info->type_mask &= ~FSNOTIFY_OBJ_TYPE_INODE_FL;
>> -             else if (cmp < 0)
>> -                     iter_info->type_mask &= ~FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL;
>> +     struct fsnotify_group *max_prio_group = NULL;
>> +     unsigned int type_mask = iter_info->type_mask;
>> +     struct fsnotify_mark *mark;
>> +     int type;
>> +
>> +     if (!type_mask || is_power_of_2(type_mask))
>> +             return type_mask;
>> +
>> +     /* Choose max prio group among groups of all queue heads */
>> +     fsnotify_iter_foreach_obj_type_mark(iter_info, type, mark) {
>
> Does this macro really bring any benefit over:
>
>         fsnotify_foreach_obj_type(type) {
>                 mark = iter_info->marks[type];

You mean:
       mark = fsnotify_iter_type_mark(info, type, mark);

Which is non NULL only if type was selected.
Needs a better name??
How about fsnotify_iter_test_type_mark() to counter
fsnotify_iter_set_type_mark()?

>
> Frankly the second makes it clearer what's going on and you don't have to
> wonder whether unset types are also included or not... What might be worth it
> is something like fsnotify_iter_foreach_mark() which would iterate over all
> *set* marks. But then there's the question whether you are iterating over
> all types set in the mask or all types set in the ->marks array so probably
> that will be error prone.

I had such a macro in an earlier version, but it was quite ugly so I let it go.
I'll get rid of fsnotify_iter_foreach_obj_type_mark() and see if it looks nicer.

>
>> diff --git a/fs/notify/mark.c b/fs/notify/mark.c
>> index ef44808b28ca..3df2d5ecf0b7 100644
>> --- a/fs/notify/mark.c
>> +++ b/fs/notify/mark.c
>> @@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
>>
>>  bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
>>  {
>> -     /* This can fail if mark is being removed */
>> -     if (!fsnotify_get_mark_safe(iter_info->inode_mark))
>> -             return false;
>> -     if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) {
>> -             fsnotify_put_mark_wake(iter_info->inode_mark);
>> -             return false;
>> +     int type;
>> +
>> +     fsnotify_foreach_obj_type(type) {
>> +             /* This can fail if mark is being removed */
>> +             if (!fsnotify_get_mark_safe(iter_info->marks[type]))
>> +                     goto fail;
>>       }
>>
>>       /*
>> @@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
>>       srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
>>
>>       return true;
>> +
>> +fail:
>> +     while (type-- > 0)
>
> Can you please rewrite it as:
>
>         for (type--; type >= 0; type--)
>
> I know I'm lame but your version made me think for a while whether index 0
> and the last index will be actually treated correctly. And we had bugs like
> this in the past...
>

Sure.

Thanks,
Amir.



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux