]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Mar 2012 18:42:29 +0000 (11:42 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Mar 2012 18:42:29 +0000 (11:42 -0700)
added patches:
rt2x00-fix-random-stalls.patch
vfs-fix-double-put-after-complete_walk.patch
vfs-fix-return-value-from-do_last.patch

queue-3.0/rt2x00-fix-random-stalls.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/vfs-fix-double-put-after-complete_walk.patch [new file with mode: 0644]
queue-3.0/vfs-fix-return-value-from-do_last.patch [new file with mode: 0644]

diff --git a/queue-3.0/rt2x00-fix-random-stalls.patch b/queue-3.0/rt2x00-fix-random-stalls.patch
new file mode 100644 (file)
index 0000000..8118606
--- /dev/null
@@ -0,0 +1,93 @@
+From 3780d038fdf4b5ef26ead10b0604ab1f46dd9510 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Fri, 9 Mar 2012 12:39:54 +0100
+Subject: rt2x00: fix random stalls
+
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit 3780d038fdf4b5ef26ead10b0604ab1f46dd9510 upstream.
+
+Is possible that we stop queue and then do not wake up it again,
+especially when packets are transmitted fast. That can be easily
+reproduced with modified tx queue entry_num to some small value e.g. 16.
+
+If mac80211 already hold local->queue_stop_reason_lock, then we can wait
+on that lock in both rt2x00queue_pause_queue() and
+rt2x00queue_unpause_queue(). After drooping ->queue_stop_reason_lock
+is possible that __ieee80211_wake_queue() will be performed before
+__ieee80211_stop_queue(), hence we stop queue and newer wake up it
+again.
+
+Another race condition is possible when between rt2x00queue_threshold()
+check and rt2x00queue_pause_queue() we will process all pending tx
+buffers on different cpu. This might happen if for example interrupt
+will be triggered on cpu performing rt2x00mac_tx().
+
+To prevent race conditions serialize pause/unpause by queue->tx_lock.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rt2x00/rt2x00dev.c   |    6 +++++-
+ drivers/net/wireless/rt2x00/rt2x00mac.c   |    9 +++++++++
+ drivers/net/wireless/rt2x00/rt2x00queue.c |    3 +++
+ 3 files changed, 17 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -410,10 +410,14 @@ void rt2x00lib_txdone(struct queue_entry
+       /*
+        * If the data queue was below the threshold before the txdone
+        * handler we must make sure the packet queue in the mac80211 stack
+-       * is reenabled when the txdone handler has finished.
++       * is reenabled when the txdone handler has finished. This has to be
++       * serialized with rt2x00mac_tx(), otherwise we can wake up queue
++       * before it was stopped.
+        */
++      spin_lock_bh(&entry->queue->tx_lock);
+       if (!rt2x00queue_threshold(entry->queue))
+               rt2x00queue_unpause_queue(entry->queue);
++      spin_unlock_bh(&entry->queue->tx_lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *h
+       if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
+               goto exit_fail;
++      /*
++       * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
++       * we should not use spin_lock_bh variant as bottom halve was already
++       * disabled before ieee80211_xmit() call.
++       */
++      spin_lock(&queue->tx_lock);
+       if (rt2x00queue_threshold(queue))
+               rt2x00queue_pause_queue(queue);
++      spin_unlock(&queue->tx_lock);
+       return;
+  exit_fail:
++      spin_lock(&queue->tx_lock);
+       rt2x00queue_pause_queue(queue);
++      spin_unlock(&queue->tx_lock);
+  exit_free_skb:
+       dev_kfree_skb_any(skb);
+ }
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -562,6 +562,9 @@ int rt2x00queue_write_tx_frame(struct da
+       u8 rate_idx, rate_flags;
+       int ret = 0;
++      /*
++       * That function must be called with bh disabled.
++       */
+       spin_lock(&queue->tx_lock);
+       entry = rt2x00queue_get_entry(queue, Q_INDEX);
index ee0353f10467c39441c41c707e1cad08ca922923..50ebcf1ace624cd19238255ea874601e3f66fbf0 100644 (file)
@@ -6,3 +6,6 @@ pci-ignore-pre-1.1-aspm-quirking-when-aspm-is-disabled.patch
 firewire-cdev-fix-32-bit-userland-on-64-bit-kernel-compat-corner-cases.patch
 firewire-core-handle-ack_busy-when-fetching-the-config-rom.patch
 pm-driver-core-leave-runtime-pm-enabled-during-system-shutdown.patch
+rt2x00-fix-random-stalls.patch
+vfs-fix-return-value-from-do_last.patch
+vfs-fix-double-put-after-complete_walk.patch
diff --git a/queue-3.0/vfs-fix-double-put-after-complete_walk.patch b/queue-3.0/vfs-fix-double-put-after-complete_walk.patch
new file mode 100644 (file)
index 0000000..3d89bcc
--- /dev/null
@@ -0,0 +1,33 @@
+From 097b180ca09b581ef0dc24fbcfc1b227de3875df Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue, 6 Mar 2012 13:56:33 +0100
+Subject: vfs: fix double put after complete_walk()
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 097b180ca09b581ef0dc24fbcfc1b227de3875df upstream.
+
+complete_walk() already puts nd->path, no need to do it again at cleanup time.
+
+This would result in Oopses if triggered, apparently the codepath is not too
+well exercised.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/namei.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2208,7 +2208,7 @@ static struct file *do_last(struct namei
+       /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
+       error = complete_walk(nd);
+       if (error)
+-              goto exit;
++              return ERR_PTR(error);
+       error = -EISDIR;
+       if (S_ISDIR(nd->inode->i_mode))
+               goto exit;
diff --git a/queue-3.0/vfs-fix-return-value-from-do_last.patch b/queue-3.0/vfs-fix-return-value-from-do_last.patch
new file mode 100644 (file)
index 0000000..69ba097
--- /dev/null
@@ -0,0 +1,32 @@
+From 7f6c7e62fcc123e6bd9206da99a2163fe3facc31 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue, 6 Mar 2012 13:56:34 +0100
+Subject: vfs: fix return value from do_last()
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 7f6c7e62fcc123e6bd9206da99a2163fe3facc31 upstream.
+
+complete_walk() returns either ECHILD or ESTALE.  do_last() turns this into
+ECHILD unconditionally.  If not in RCU mode, this error will reach userspace
+which is complete nonsense.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/namei.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2109,7 +2109,7 @@ static struct file *do_last(struct namei
+               /* sayonara */
+               error = complete_walk(nd);
+               if (error)
+-                      return ERR_PTR(-ECHILD);
++                      return ERR_PTR(error);
+               error = -ENOTDIR;
+               if (nd->flags & LOOKUP_DIRECTORY) {