]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Apr 2015 07:52:50 +0000 (09:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Apr 2015 07:52:50 +0000 (09:52 +0200)
added patches:
dcache-fix-locking-bugs-in-backported-deal-with-deadlock-in-d_walk.patch

queue-3.10/dcache-fix-locking-bugs-in-backported-deal-with-deadlock-in-d_walk.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/dcache-fix-locking-bugs-in-backported-deal-with-deadlock-in-d_walk.patch b/queue-3.10/dcache-fix-locking-bugs-in-backported-deal-with-deadlock-in-d_walk.patch
new file mode 100644 (file)
index 0000000..b04bca1
--- /dev/null
@@ -0,0 +1,110 @@
+From 20defcec264ceab2630356fb9d397f3d237b5e6d Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 11 Feb 2015 03:16:35 +0000
+Subject: dcache: Fix locking bugs in backported "deal with deadlock in d_walk()"
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+commit 20defcec264ceab2630356fb9d397f3d237b5e6d upstream in 3.2-stable
+
+Steven Rostedt reported:
+> Porting -rt to the latest 3.2 stable tree I triggered this bug:
+>
+> =====================================
+> [ BUG: bad unlock balance detected! ]
+> -------------------------------------
+> rm/1638 is trying to release lock (rcu_read_lock) at:
+> [<c04fde6c>] rcu_read_unlock+0x0/0x23
+> but there are no more locks to release!
+>
+> other info that might help us debug this:
+> 2 locks held by rm/1638:
+>  #0:  (&sb->s_type->i_mutex_key#9/1){+.+.+.}, at: [<c04f93eb>] do_rmdir+0x5f/0xd2
+>  #1:  (&sb->s_type->i_mutex_key#9){+.+.+.}, at: [<c04f9329>] vfs_rmdir+0x49/0xac
+>
+> stack backtrace:
+> Pid: 1638, comm: rm Not tainted 3.2.66-test-rt96+ #2
+> Call Trace:
+>  [<c083f390>] ? printk+0x1d/0x1f
+>  [<c0463cdf>] print_unlock_inbalance_bug+0xc3/0xcd
+>  [<c04653a8>] lock_release_non_nested+0x98/0x1ec
+>  [<c046228d>] ? trace_hardirqs_off_caller+0x18/0x90
+>  [<c0456f1c>] ? local_clock+0x2d/0x50
+>  [<c04fde6c>] ? d_hash+0x2f/0x2f
+>  [<c04fde6c>] ? d_hash+0x2f/0x2f
+>  [<c046568e>] lock_release+0x192/0x1ad
+>  [<c04fde83>] rcu_read_unlock+0x17/0x23
+>  [<c04ff344>] shrink_dcache_parent+0x227/0x270
+>  [<c04f9348>] vfs_rmdir+0x68/0xac
+>  [<c04f9424>] do_rmdir+0x98/0xd2
+>  [<c04f03ad>] ? fput+0x1a3/0x1ab
+>  [<c084dd42>] ? sysenter_exit+0xf/0x1a
+>  [<c0465b58>] ? trace_hardirqs_on_caller+0x118/0x149
+>  [<c04fa3e0>] sys_unlinkat+0x2b/0x35
+>  [<c084dd13>] sysenter_do_call+0x12/0x12
+>
+>
+>
+>
+> There's a path to calling rcu_read_unlock() without calling
+> rcu_read_lock() in have_submounts().
+>
+>      goto positive;
+>
+> positive:
+>      if (!locked && read_seqretry(&rename_lock, seq))
+>              goto rename_retry;
+>
+> rename_retry:
+>      rcu_read_unlock();
+>
+> in the above path, rcu_read_lock() is never done before calling
+> rcu_read_unlock();
+
+I reviewed locking contexts in all three functions that I changed when
+backporting "deal with deadlock in d_walk()".  It's actually worse
+than this:
+
+- We don't hold this_parent->d_lock at the 'positive' label in
+  have_submounts(), but it is unlocked after 'rename_retry'.
+- There is an rcu_read_unlock() after the 'out' label in
+  select_parent(), but it's not held at the 'goto out'.
+
+Fix all three lock imbalances.
+
+Reported-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Tested-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/dcache.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1072,7 +1072,7 @@ ascend:
+       return 0; /* No mount points found in tree */
+ positive:
+       if (!locked && read_seqretry(&rename_lock, seq))
+-              goto rename_retry;
++              goto rename_retry_unlocked;
+       if (locked)
+               write_sequnlock(&rename_lock);
+       return 1;
+@@ -1082,6 +1082,7 @@ rename_retry:
+       rcu_read_unlock();
+       if (locked)
+               goto again;
++rename_retry_unlocked:
+       locked = 1;
+       write_seqlock(&rename_lock);
+       goto again;
+@@ -1146,6 +1147,7 @@ resume:
+                */
+               if (found && need_resched()) {
+                       spin_unlock(&dentry->d_lock);
++                      rcu_read_lock();
+                       goto out;
+               }
index b99de882e420aa933e4aa284e5fb5fad6c2877f0..2cac66304c43c5a7339574e060910d07655bd3d2 100644 (file)
@@ -30,3 +30,4 @@ vm-make-stack-guard-page-errors-return-vm_fault_sigsegv-rather-than-sigbus.patch
 x86-mm-move-mmap_sem-unlock-from-mm_fault_error-to-caller.patch
 sb_edac-avoid-internal-error-message-in-edac-with-unspecified-channel.patch
 arc-mm-fix-build-failure.patch
+dcache-fix-locking-bugs-in-backported-deal-with-deadlock-in-d_walk.patch