Skip to content

Commit 8ba64dc

Browse files
committed
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
2 parents 36a8b9a + 2159184 commit 8ba64dc

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

fs/dcache.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,13 +1239,13 @@ static void d_walk(struct dentry *parent, void *data,
12391239
/* might go back up the wrong parent if we have had a rename. */
12401240
if (need_seqretry(&rename_lock, seq))
12411241
goto rename_retry;
1242-
next = child->d_child.next;
1243-
while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
1242+
/* go into the first sibling still alive */
1243+
do {
1244+
next = child->d_child.next;
12441245
if (next == &this_parent->d_subdirs)
12451246
goto ascend;
12461247
child = list_entry(next, struct dentry, d_child);
1247-
next = next->next;
1248-
}
1248+
} while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
12491249
rcu_read_unlock();
12501250
goto resume;
12511251
}

0 commit comments

Comments
 (0)