Re: [PATCH] spin_lock_irqsave() in autofs_write() is bogus

Al Viro <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.autofs
Message-ID <20250817174741.GX222315@ZenIV>
On Sun, Aug 17, 2025 at 09:50:25AM -0700, Linus Torvalds wrote:
> On Sun, 17 Aug 2025 at 09:36, Al Viro <[email protected]> wrote:
> >
> >         That function should never be (and never is) called with irqs
> > disabled - we have an explicit mutex_lock() in there, if nothing else.
> > Which makes spin_lock_irqsave() use in there pointless - we do need to
> > disable irqs for ->siglock, but that should be spin_lock_irq().
> 
> I think we basically did the irqsave/restore version as the default
> when not wanting to think about the context.
>
> Your patch looks fine, but I doubt it's measurable outside of "it
> makes the code a few bytes smaller".
>
> So ACK on it, but I'm not convinced it's worth spending time actively
> _looking_ for these kinds of things.

It's obviously not a hot path of any sort; the only cost is head-scratching
of later readers.  OTOH, seeing that nobody had looked at it that one in
what, 28 years...

For another head-scratcher in that area: I started to look at __rcu sparse
noise, and ->sighand->siglock accesses had been quite a part of that.
current->sighand is obviously stable and should need no rcu_dereference(),
right?  So what the hell is
        rcu_read_lock();
	sighand = rcu_dereference(current->sighand);
	spin_lock_irqsave(&sighand->siglock, flags);
	recalc_sigpending();
	spin_unlock_irqrestore(&sighand->siglock, flags);
	rcu_read_unlock();
in net/sunrpc/svc.c:svc_unregister() about?  Is there something subtle I'm
missing there?  AFAICS, that came from 00a87e5d1d67 "SUNRPC: Address
RCU warning in net/sunrpc/svc.c" and commit message in there contains
no explanation beyond "sparse is complaining, let's make it STFU"...

Looking for ->sighand stores gives this:
fs/exec.c:1070:         rcu_assign_pointer(me->sighand, newsighand);
	store to current->sighand, called from begin_new_exec(), with
'me' set to current.
kernel/exit.c:215:      tsk->sighand = NULL;
	__exit_signal(), from release_task(), and if it's ever done
asynchronously to the current thread, we are really fucked (note that
we do *not* check that sighand is non-NULL in that snippet).
kernel/fork.c:1608:     RCU_INIT_POINTER(tsk->sighand, sig);
	copy_sighand(), from copy_process(), done to the child task
that is nowhere near running at that point.

So nothing weird has happened and that code looks very much like
a pointless head-scratcher.  Sure, the cost in execution time is
not going to be measurable, but the cost for readers is non-trivial...

FWIW, I suspect that the right way would be something like
static inline struct sighand_struct *current_sighand(void)
{
	return unrcu_pointer(current->sighand);
}
if unrcu_pointer is idiomatic in such case, plus conversion of open-coded
instances to it...
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.