[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250209233341.GX1977892@ZenIV>
Date: Sun, 9 Feb 2025 23:33:41 +0000
From: Al Viro <viro@...iv.linux.org.uk>
To: NeilBrown <neilb@...e.de>
Cc: Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Jeff Layton <jlayton@...nel.org>,
Dave Chinner <david@...morbit.com>, linux-fsdevel@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH 00/19 v7?] RFC: Allow concurrent and async changes in a
directory
On Thu, Feb 06, 2025 at 04:42:37PM +1100, NeilBrown wrote:
> The idea behind the async support is to eventually connect this to
> io_uring so that one process can launch several concurrent directory
> operations. I have not looked deeply into io_uring and cannot be
> certain that the interface I've provided will be able to be used. I
> would welcome any advice on that matter, though I hope to find time to
> explore myself. For now if any _async op returns -EINPROGRESS we simply
> wait for the callback to indicate completion.
OK, after looking through that and playing around with the locking
scheme of yours:
Separating directory rwsem for reads/modifications from locking of
individual dentries may be feasible, but it needs to be a lot more
careful about the states it sleeps in. Your current variant is rife
with deadlocks; for the "wait on dentry itself" it's probably possible
to avoid, with some care; for "wait on parent" it's really not an option.
Quite a bit of headache comes from the fact that NFS et.al. are playing
silly buggers with "OK, we see that lookup is for <operation>; skip it,
the call of actual method will do the right thing". The trouble is,
d_lookup_done() of not-really-looked-up is fine under exclusive lock on
parent, but only because there won't be d_alloc_parallel() on the same
name until we drop that exclusive lock.
Your scheme, OTOH, has hard dependency upon those suckers staying visible
to d_alloc_parallel() until the actual operation is done. Which means
that this code, including the methods, is exposed to in-lookup dentries.
What's more, similar dependency is there for dentries getting unhashed
between the lookup and the end of operation - something which NFS
cheerfully violates. If method's argument gets hit with d_drop() and
d_rehash(), there's a window where it won't be found in dcache, leaving
no indication that it's being operated upon. Currently we are fine -
exclusive lock on parent means that on dcache miss we try to grab
the parent shared and repeat dcache lookup when we get that.
Your variant does not have such exclusion - parent is held shared and
child dentry involved is not there to be found during d_drop()/d_rehash()
window.
IOW, your in-update state might make sense, but not in the way it's done
at the moment - it's too brittle.
And the part about async tree topology modifications are bloody insane,
IMO. I won't believe that to be feasible until I see the algorithm and
proof of correctness; preferably _before_ the actual code.
Powered by blists - more mailing lists