summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 18:48:10 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 18:48:10 -0700
commit2e321806b681b1920b6dfa7d81bbe3d312fe1d19 (patch)
treeba9d8b2e4ac401ef1ce0ac86662af2e032584485
parentc23ddf7857bdb2e8001b0a058603497c765a580d (diff)
downloadlwn-2e321806b681b1920b6dfa7d81bbe3d312fe1d19.tar.gz
lwn-2e321806b681b1920b6dfa7d81bbe3d312fe1d19.zip
Revert "vfs: remove unnecessary d_unhashed() check from __d_lookup_rcu"
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>
-rw-r--r--fs/dcache.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index a7675e0109f0..8c1ab8fb5012 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -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)) {