[lkml]   [2014]   [Oct]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
SubjectRe: fs: lockup on rename_mutex in fs/dcache.c:1035
On Sat, Oct 25, 2014 at 8:57 PM, Al Viro <> wrote:
> [context for Linus]
> Fuzzer has triggered deadlock in d_walk() with rename_lock taken twice.
> AFAICS, the plausible scenario is
> (child->d_flags & DCACHE_DENTRY_KILLED) ||
> triggering while ascending to parent, on the pass with rename_lock already
> held exclusive. In that case we go to rename_retry and either return without
> unlocking rename_lock, or try to take in exclusive one more time, again
> without unlocking it first.

Your patch looks fine, and I don't think we can livelock - because we
always set 'seq' to 1 if we retry, and that causes us to get the
exclusive lock, so we'd better not then enter the retry loop again.
Although I guess not only renames cause it - looks like we get to that
mis-named "rename_retry" for a deletion too according to the comment.
Although I'm not sure that comment is correct - I don't think we
change d_parent for deletes, do we?

So at a quick glance, the one-liner patch looks fine. That said, I
really detest how that code is written. Especially if the rename_retry
really can only happen once, I get the feeling that we would be *much*
better off doing this explicitly with a wrapper function, and do
something like

void d_walk(,..)
/* Try non-exclusive first */
seq = read_seqbegin(lock);
retry = __d_walk(.. seq);
if (retry) {
// lock->seqcount is now guaranteed stable
retry = __d_walk(.. lock->seqcount);
WARN_ON_ONCE(retry, "Really?");

or whatever. But maybe I'm missing some reason why the above is just
crazy, and I'm a moron. Entirely possible.


 \ /
  Last update: 2014-10-26 20:21    [W:0.060 / U:46.916 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site