aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-05-31 19:00:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-05-31 19:00:34 -0400
commit8ba64dc33830fbcd57d59fddc2ca1c24a6a394c4 (patch)
treec7c5fa2b739d21752bff033d2df596a30a1d86bb /fs
parent36a8b9a774f8f283cdf9e6959ea9b5208681e8ed (diff)
parent2159184ea01e4ae7d15f2017e296d4bc82d5aeb0 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fix from Al Viro: "Off-by-one in d_walk()/__dentry_kill() race fix. It's very hard to hit; possible in the same conditions as the original bug, except that you need the skipped branch to contain all the remaining evictables, so that the d_walk()-calling loop in d_invalidate() decides there's nothing more to do and doesn't go for another pass - otherwise that next pass will sweep the sucker. So it's not too urgent, but seeing that the fix is obvious and the original commit has spread into all -stable branches..." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: d_walk() might skip too much
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 656ce522a218..37b5afdaf698 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1239,13 +1239,13 @@ ascend:
1239 /* might go back up the wrong parent if we have had a rename. */ 1239 /* might go back up the wrong parent if we have had a rename. */
1240 if (need_seqretry(&rename_lock, seq)) 1240 if (need_seqretry(&rename_lock, seq))
1241 goto rename_retry; 1241 goto rename_retry;
1242 next = child->d_child.next; 1242 /* go into the first sibling still alive */
1243 while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { 1243 do {
1244 next = child->d_child.next;
1244 if (next == &this_parent->d_subdirs) 1245 if (next == &this_parent->d_subdirs)
1245 goto ascend; 1246 goto ascend;
1246 child = list_entry(next, struct dentry, d_child); 1247 child = list_entry(next, struct dentry, d_child);
1247 next = next->next; 1248 } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
1248 }
1249 rcu_read_unlock(); 1249 rcu_read_unlock();
1250 goto resume; 1250 goto resume;
1251 } 1251 }