Revert "vfs: remove unnecessary d_unhashed() check from __d_lookup_rcu"
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 May 2012 01:48:10 +0000 (18:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 May 2012 01:48:10 +0000 (18:48 -0700)
This reverts commit 8c01a529b861ba97c7d78368e6a5d4d42e946f75.

It turns out the d_unhashed() check isn't unnecessary after all: while
it's true that unhashing will increment the sequence numbers, that does
not necessarily invalidate the RCU lookup, because it might have seen
the dentry pointer (before it got unhashed), but by the time it loaded
the sequence number, it could have seen the *new* sequence number (after
it got unhashed).

End result: we might look up an unhashed dentry that is about to be
freed, with the sequence number never indicating anything bad about it.
So checking that the dentry is still hashed (*after* reading the sequence
number) is indeed the proper fix, and was never unnecessary.

Reported-by: Dave Jones <davej@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/dcache.c

index a7675e0109f08fa5c9c153172411c7863655a0c3..8c1ab8fb501228e082c04160fbc69aaeafd3cbee 100644 (file)
@@ -1877,6 +1877,8 @@ seqretry:
                seq = raw_seqcount_begin(&dentry->d_seq);
                if (dentry->d_parent != parent)
                        continue;
+               if (d_unhashed(dentry))
+                       continue;
                *seqp = seq;
 
                if (unlikely(parent->d_flags & DCACHE_OP_COMPARE)) {