Re: [PATCH 1/7] __follow_mount_rcu(): verify that mount_lock remains unchanged

Al Viro
2022-07-05T03:50:00Z

On Mon, Jul 04, 2022 at 05:06:17PM -0700, Linus Torvalds wrote:

> I wonder if the solution might not be to create a new structure like
>
> struct rcu_dentry {
> struct dentry *dentry;
> unsigned seq;
> };
>
> and in fact then we could make __d_lookup_rcu() return one of these
> things (we already rely on that "returning a two-word structure is
> efficient" elsewhere).
>
> That would then make that "this dentry goes with this sequence number"
> be a very clear thing, and I actually thjink that it would make
> __d_lookup_rcu() have a cleaner calling convention too, ie we'd go
> from
>
> dentry = __d_lookup_rcu(parent, &nd->last, &nd->next_seq);
>
> rto
>
> dseq = __d_lookup_rcu(parent, &nd->last);
>
> and it would even improve code generation because it now returns the
> dentry and the sequence number in registers, instead of returning one
> in a register and one in memory.
>
> I did *not* look at how it would change some of the other places, but
> I do like the notion of "keep the dentry and the sequence number that
> goes with it together".
>
> That "keep dentry as a local, keep the sequence number that goes with
> it as a field in the 'nd'" really does seem an odd thing. So I'm
> throwing the above out as a "maybe we could do this instead..".

I looked into that; turns out to be quite messy, unfortunately. For one
thing, the distance between the places where we get the seq count and
the place where we consume it is large; worse, there's a bunch of paths
where we are in non-RCU mode converging to the same consumer and those
need a 0/1/-1/whatever paired with dentry. Gets very clumsy...

There might be a clever way to deal with pairs cleanly, but I don't see it
at the moment. I'll look into that some more, but...

BTW, how good gcc and clang are at figuring out that e.g.

static int foo(int n)
{
if (likely(n >= 0))
return 0;
....
}

....
if (foo(n))
whatever();

should be treated as
if (unlikely(foo(n)))
whatever();

They certainly do it just fine if the damn thing is inlined (e.g.
all those unlikely(read_seqcount_retry(....)) can and should lose
unlikely), but do they manage that for non-inlined functions in
the same compilation unit? Relatively recent gcc seems to...