Re: [PATCH] fs/dcache.c: re-add cond_resched() in shrink_dcache_parent()
From: Linus Torvalds
Date: Sun Apr 15 2018 - 14:34:32 EST
On Sat, Apr 14, 2018 at 5:51 PM, Al Viro <viro@xxxxxxxxxxxxxxxxxx> wrote:
>> if (!list_empty(&data.select.found))
That was obviously meant to be just
if (data.select.found)
I had just cut-and-pasted a bit too much.
> You would have to do the same in check_and_drop() as well,
> and that brings back d_invalidate()/d_invalidate() livelock
> we used to have. See 81be24d263db...
Ugh. These are all really incestuous and very intertwined. Yes.
> I'm trying to put something together, but the damn thing is
> full of potential livelocks, unfortunately ;-/ Will send
> a followup once I have something resembling a sane solution...
Ok, that patch of yours looks like a nice cleanup, although *please*
don't do this:
- struct detach_data *data = _data;
-
if (d_mountpoint(dentry)) {
__dget_dlock(dentry);
- data->mountpoint = dentry;
+ *(struct dentry **)_data = dentry;
Please keep the temporary variable, and make it do
+ struct dcache **victim = _victim;
...
+ *victim = dentry;
to kind of match the caller, which does
d_walk(dentry, &victim, find_submount);
because I abhor those casts inside code, and we have a pattern of
passing 'void *_xyz' to callback functions and then making the right
type by that kind of
struct right_type *xyz = _xyz;
at the very top of the function.
No, it's obviously not type-safe, but at least it's _legible_, and is
a pattern, while that "let's randomly just do a cast in the middle of
the code" is just nasty.
Side note: I do feel like "d_walk()" should be returning whether it
terminated early or not. For example, this very same code in the
caller does
+ struct dentry *victim = NULL;
+ d_walk(dentry, &victim, find_submount);
+ if (!victim) {
but in many ways it would be more natural to just check the exit condition, and
+ struct dentry *victim;
+ if (!d_walk(dentry, &victim, find_submount)) {
don't you think? Because that matches the actual setting condition in
the find_submount() callback.
There are other situations where the same thing is true: that
path_check_mount() currently has that "info->mounted" flag, but again,
it could be replaced by just checking what the quit condition was, and
whether we terminated early or not. Because the two are 100%
equivalent, and the return value in many ways would be more logical, I
feel.
(I'm not sure if we should just return the actual exit condition -
defaulting to D_WALK_CONTINUE if there was nothing to walk at all - or
whether we should just return a boolean for "terminated early")
Hmm?
Linus