diff options
Diffstat (limited to 'deal-with-deadlock-in-d_walk.patch')
-rw-r--r-- | deal-with-deadlock-in-d_walk.patch | 86 |
1 files changed, 0 insertions, 86 deletions
diff --git a/deal-with-deadlock-in-d_walk.patch b/deal-with-deadlock-in-d_walk.patch deleted file mode 100644 index fd0e21c33..000000000 --- a/deal-with-deadlock-in-d_walk.patch +++ /dev/null @@ -1,86 +0,0 @@ -From: Al Viro <viro@zeniv.linux.org.uk> -Date: Sun, 26 Oct 2014 19:31:10 -0400 -Subject: [PATCH] deal with deadlock in d_walk() - -... by not hitting rename_retry for reasons other than rename having -happened. In other words, do _not_ restart when finding that -between unlocking the child and locking the parent the former got -into __dentry_kill(). Skip the killed siblings instead... - -Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> ---- - fs/dcache.c | 31 ++++++++++++++++--------------- - 1 file changed, 16 insertions(+), 15 deletions(-) - -diff --git a/fs/dcache.c b/fs/dcache.c -index c3ea5b765f6a..71acf8d6f2be 100644 ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -495,7 +495,7 @@ static void __dentry_kill(struct dentry *dentry) - } - /* if it was on the hash then remove it */ - __d_drop(dentry); -- list_del(&dentry->d_child); -+ __list_del_entry(&dentry->d_child); - /* - * Inform d_walk() that we are no longer attached to the - * dentry tree -@@ -1082,33 +1082,31 @@ resume: - /* - * All done at this level ... ascend and resume the search. - */ -+ rcu_read_lock(); -+ascend: - if (this_parent != parent) { - struct dentry *child = this_parent; - this_parent = child->d_parent; - -- rcu_read_lock(); - spin_unlock(&child->d_lock); - spin_lock(&this_parent->d_lock); - -- /* -- * might go back up the wrong parent if we have had a rename -- * or deletion -- */ -- if (this_parent != child->d_parent || -- (child->d_flags & DCACHE_DENTRY_KILLED) || -- need_seqretry(&rename_lock, seq)) { -- spin_unlock(&this_parent->d_lock); -- rcu_read_unlock(); -+ /* might go back up the wrong parent if we have had a rename. */ -+ if (need_seqretry(&rename_lock, seq)) - goto rename_retry; -+ next = child->d_child.next; -+ while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { -+ if (next == &this_parent->d_subdirs) -+ goto ascend; -+ child = list_entry(next, struct dentry, d_child); -+ next = next->next; - } - rcu_read_unlock(); -- next = child->d_child.next; - goto resume; - } -- if (need_seqretry(&rename_lock, seq)) { -- spin_unlock(&this_parent->d_lock); -+ if (need_seqretry(&rename_lock, seq)) - goto rename_retry; -- } -+ rcu_read_unlock(); - if (finish) - finish(data); - -@@ -1118,6 +1116,9 @@ out_unlock: - return; - - rename_retry: -+ spin_unlock(&this_parent->d_lock); -+ rcu_read_unlock(); -+ BUG_ON(seq & 1); - if (!retry) - return; - seq = 1; --- -2.1.0 - |