Commit b93e0acc authored by Jari Ruusu's avatar Jari Ruusu Committed by Greg Kroah-Hartman

d_walk() might skip too much

When Al Viro's VFS deadlock fix "deal with deadlock in d_walk()" was
backported to 3.10.y 3.4.y and 3.2.y stable kernel brances, the deadlock fix
was copied to 3 different places. Later, a bug in that code was discovered.
Al Viro's fix involved fixing only one part of code in mainline kernel. That
fix is called "d_walk() might skip too much".

3.10.y 3.4.y and 3.2.y stable kernel brances need that later fix copied to 3
different places. Greg Kroah-Hartman included Al Viro's "d_walk() might skip
too much" fix only once in 3.10.80 kernel, leaving 2 more places without a
fix.

The patch below was not written by me. I only applied Al Viro's "d_walk()
might skip too much" fix 2 more times to 3.10.80 kernel, and cheched that
the fixes went to correct places. With this patch applied, all 3 places that
I am aware of 3.10.y stable branch are now fixed.
Signed-off-by: default avatarJari Ruusu <jariruusu@users.sourceforge.net>
Cc: Willy Tarreau <w@1wt.eu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c1e1eb15
...@@ -1053,13 +1053,13 @@ int have_submounts(struct dentry *parent) ...@@ -1053,13 +1053,13 @@ int have_submounts(struct dentry *parent)
/* might go back up the wrong parent if we have had a rename. */ /* might go back up the wrong parent if we have had a rename. */
if (!locked && read_seqretry(&rename_lock, seq)) if (!locked && read_seqretry(&rename_lock, seq))
goto rename_retry; goto rename_retry;
/* go into the first sibling still alive */
do {
next = child->d_child.next; next = child->d_child.next;
while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
if (next == &this_parent->d_subdirs) if (next == &this_parent->d_subdirs)
goto ascend; goto ascend;
child = list_entry(next, struct dentry, d_child); child = list_entry(next, struct dentry, d_child);
next = next->next; } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
}
rcu_read_unlock(); rcu_read_unlock();
goto resume; goto resume;
} }
...@@ -2977,13 +2977,13 @@ void d_genocide(struct dentry *root) ...@@ -2977,13 +2977,13 @@ void d_genocide(struct dentry *root)
/* might go back up the wrong parent if we have had a rename. */ /* might go back up the wrong parent if we have had a rename. */
if (!locked && read_seqretry(&rename_lock, seq)) if (!locked && read_seqretry(&rename_lock, seq))
goto rename_retry; goto rename_retry;
/* go into the first sibling still alive */
do {
next = child->d_child.next; next = child->d_child.next;
while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) {
if (next == &this_parent->d_subdirs) if (next == &this_parent->d_subdirs)
goto ascend; goto ascend;
child = list_entry(next, struct dentry, d_child); child = list_entry(next, struct dentry, d_child);
next = next->next; } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED));
}
rcu_read_unlock(); rcu_read_unlock();
goto resume; goto resume;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment