Re: [PATCH 10/22] fsnotify: Detach mark from object list when last reference is dropped

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

 



On Thu, Dec 22, 2016 at 11:15 AM, Jan Kara <jack@xxxxxxx> wrote:
> Instead of removing mark from object list from fsnotify_detach_mark(),
> remove the mark when last reference to the mark is dropped. This will
> allow fanotify to wait for userspace response to event without having to
> hold onto fsnotify_mark_srcu.
>
> Signed-off-by: Jan Kara <jack@xxxxxxx>
> ---
...

+/* Called with mark->obj_list_head->lock held, releases it */
+static void fsnotify_detach_from_object(struct fsnotify_mark *mark)
 {

IMO, the implicit release in this function makes the code using it hard
to read and maintain. Please consider splitting it into 2 functions
to be called from code that explicitly unlocks, e.g.:

     free_list = fsnotify_detach_from_object_locked(mark, &inode);
     spin_unlock(&list->lock);
     if (inode)
        iput(inode);
     if (free_list)
        fsnotify_free_list(list);

...
> +               inode = fsnotify_detach_list_from_object(list);
>                 free_list = true;
>         } else
>                 __fsnotify_recalc_mask(list);
>         mark->obj_list_head = NULL;
>         spin_unlock(&list->lock);
>
> +       if (inode)
> +               iput(inode);
> +

Question: if list is holding inode anyway, what's the use of
FSNOTIFY_MARK_FLAG_OBJECT_PINNED?
or maybe you are removing it later on in the series?


...
> +       /*
> +        * We have to be careful since we can race with e.g.
> +        * fsnotify_clear_marks_by_group() and once we drop the list->lock, the
> +        * list can get modified. However we are holding mark reference and
> +        * thus our mark cannot be removed from obj_list so we can continue
> +        * iteration after regaining list->lock.
> +        */
> +       hlist_for_each_entry(mark, &list->list, obj_list) {
>                 fsnotify_get_mark(mark);
> -               fsnotify_put_list(list);
> +               spin_unlock(&list->lock);
> +               if (old_mark)
> +                       fsnotify_put_mark(old_mark);
> +               old_mark = mark;
>                 fsnotify_destroy_mark(mark, mark->group);
> -               fsnotify_put_mark(mark);
> +               spin_lock(&list->lock);
>         }
> +       /*
> +        * Detach list from object now so that we don't pin inode until all
> +        * mark references get dropped. It would lead to strange results such
> +        * as delaying inode deletion or blocking unmount.
> +        */
> +       inode = fsnotify_detach_list_from_object(list);
> +       fsnotify_put_list(list);
> +       if (inode)
> +               iput(inode);
> +       if (old_mark)
> +               fsnotify_put_mark(old_mark);

I must be missing something subtle here. I don't see where the list->lock
is unlocked. Also, I am not sure if you placed put old_mark after
fsnotify_put_list
for a reason. If you did, I did not find that reason in the comments. If you
didn't I think it would be more appropriate after the list iteration
ends, although
it appear that put old_mark should be called after list->lock unlock.

Please untangle this knot for me.


> diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
> index 6086fc7ff6df..76b3c34172c7 100644
> --- a/include/linux/fsnotify_backend.h
> +++ b/include/linux/fsnotify_backend.h
> @@ -244,9 +244,9 @@ struct fsnotify_mark {
>         struct list_head g_list;
>         /* Protects inode / mnt pointers, flags, masks */
>         spinlock_t lock;
> -       /* List of marks for inode / vfsmount [obj_list_head->lock] */
> +       /* List of marks for inode / vfsmount [obj_list_head->lock, mark ref] */
>         struct hlist_node obj_list;
> -       /* Head of list of marks for an object [mark->lock, group->mark_mutex] */
> +       /* Head of list of marks for an object [mark ref] */
>         struct fsnotify_mark_list *obj_list_head;

What is the meaning of [mark ref] here?
If the mark is on the obj_list its refcount is already elevated.
I thought it's the mark that is holding a ref on the list_head (or tap
if you accept my suggestion)
and not the other way around.
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[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