Re: [PATCH v1 03/12] fsnotify: don't hold a spin_lock across fsnotify_recalc_mask() calls.

NeilBrown <[email protected]>
Newsgroups org.kernel.vger.ceph-devel,org.kernel.vger.autofs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs
Message-ID <[email protected]>
On Tue, 11 Aug 2026, NeilBrown wrote:
> On Tue, 11 Aug 2026, Miklos Szeredi wrote:
> > On Mon, 3 Aug 2026 at 03:39, NeilBrown <[email protected]> wrote:
> > 
> > > @@ -116,11 +117,15 @@ static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
> > >                 else {
> > >                         *prev = dn->dn_next;
> > >                         kmem_cache_free(dnotify_struct_cache, dn);
> > > -                       dnotify_recalc_inode_mask(inode_mark);
> > > +                       need_recalc = true;
> > >                 }
> > >         }
> > >
> > > +       if (need_recalc)
> > > +               need_recalc = dnotify_recalc_inode_mask(inode_mark);
> > >         spin_unlock(&inode_mark->lock);
> > > +       if (need_recalc)
> > > +               fsnotify_recalc_mask(inode_mark->connector);
> > 
> > Is the fsnotify_group_lock() held in this case?   I don't see it.
> 
> It isn't held.  Doesn't it need to be...
> It seems to protect marks, so maybe it does.
> 
> srcu seems to be used to protect this section, so maybe we can rely on
> that.

I dug into this some more, and we do rely on srcu, but don't need the
extra code below.
inode_mark->lock doesn't protect inode_mark->connector, so moving the
dereference out of the lock has no effect.
srcu_read_lock is taken before we get the ref to the mark, so the mark
and the connector cannot disappear underneath us.
A race could result in inode_mark->connector reading as NULL, but
fsnotify_recalc_mask() checks for NULL, so there is no risk for harm.

Thanks for encouraging me to dig into this.

NeilBrown

> Maybe:
> 
> diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
> index 7553fe0d7850..ba746284bded 100644
> --- a/fs/notify/dnotify/dnotify.c
> +++ b/fs/notify/dnotify/dnotify.c
> @@ -17,6 +17,7 @@
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
>  #include <linux/fsnotify_backend.h>
> +#include "../fsnotify.h"
>  
>  static int dir_notify_enable __read_mostly = 1;
>  #ifdef CONFIG_SYSCTL
> @@ -94,6 +95,7 @@ static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
>  	struct dnotify_struct *dn;
>  	struct dnotify_struct **prev;
>  	struct fown_struct *fown;
> +	struct fsnotify_mark_connector *conn;
>  	bool need_recalc = false;
>  	__u32 test_mask = mask & ~FS_EVENT_ON_CHILD;
>  
> @@ -123,9 +125,10 @@ static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask,
>  
>  	if (need_recalc)
>  		need_recalc = dnotify_recalc_inode_mask(inode_mark);
> +	conn = srcu_dereference(inode_mark->connector, &fsnotify_mark_srcu);
>  	spin_unlock(&inode_mark->lock);
>  	if (need_recalc)
> -		fsnotify_recalc_mask(inode_mark->connector);
> +		fsnotify_recalc_mask(conn);
>  
>  	return 0;
>  }
> 
> Does that make sense?
> 
> Thanks,
> NeilBrown
> 
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.